Home / Docs / Credits and usage

Credits and usage

Read your balance, your spending limits and the usage behind a bill.

Router credit is not on sale yet; nobody can top up today. Use this page to read your balance, your spending limits and the usage behind a bill. Money is held in wallets and counted in mu, the unit of account.

Read your balance and spending

Today the balance and the spending page are session endpoints of the console, not relay-key endpoints:

GET /api/me/wallets

Authentication signed-in session; roles: admin, cfo_viewer, fde, hr_ops, manager, member, operator

Response

FieldTypeDescription
wallets requiredarray of object
wallets[].id requiredstringThe answer's id.
wallets[].tenantIdstring
wallets[].ownerKindstring
wallets[].ownerIdstring
wallets[].kind requiredstring
wallets[].balanceMu requiredinteger
wallets[].heldMu requiredinteger
wallets[].currencyHintstring or null
wallets[].expiresAtstring or null
wallets[].spendPriorityinteger
wallets[].sourceKindstring or null
wallets[].sourceRefstring or null
wallets[].periodStartstring or null
wallets[].periodEndstring or null
wallets[].rolloverCapMuinteger or null
wallets[].createdAtstring
wallets[].closedAtstring or null
Example response (shape)
{
  "wallets": [
    {
      "id": "<id>",
      "tenantId": "<tenantId>",
      "ownerKind": "<ownerKind>",
      "ownerId": "<ownerId>",
      "kind": "<kind>",
      "balanceMu": 0,
      "heldMu": 0,
      "currencyHint": "<currencyHint>",
      "expiresAt": "<expiresAt>",
      "spendPriority": 0,
      "sourceKind": "<sourceKind>",
      "sourceRef": "<sourceRef>",
      "periodStart": "<periodStart>",
      "periodEnd": "<periodEnd>",
      "rolloverCapMu": "<rolloverCapMu>",
      "createdAt": "<createdAt>",
      "closedAt": "<closedAt>"
    }
  ]
}

Common errors

  • 401 not signed in

Every error has the same JSON shape; see Errors and Limits.

Full schema (JSON)

Response schema

{
  "description": "A session credential. A person with no personal workspace yet gets an empty list, not an error. Amounts are in mu (the unit of account).",
  "type": "object",
  "required": [
    "wallets"
  ],
  "properties": {
    "wallets": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "id",
          "kind",
          "balanceMu",
          "heldMu"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "tenantId": {
            "type": "string"
          },
          "ownerKind": {
            "type": "string"
          },
          "ownerId": {
            "type": "string"
          },
          "kind": {
            "type": "string"
          },
          "balanceMu": {
            "type": "integer"
          },
          "heldMu": {
            "type": "integer"
          },
          "currencyHint": {
            "type": [
              "string",
              "null"
            ]
          },
          "expiresAt": {
            "type": [
              "string",
              "null"
            ]
          },
          "spendPriority": {
            "type": "integer"
          },
          "sourceKind": {
            "type": [
              "string",
              "null"
            ]
          },
          "sourceRef": {
            "type": [
              "string",
              "null"
            ]
          },
          "periodStart": {
            "type": [
              "string",
              "null"
            ]
          },
          "periodEnd": {
            "type": [
              "string",
              "null"
            ]
          },
          "rolloverCapMu": {
            "type": [
              "integer",
              "null"
            ]
          },
          "createdAt": {
            "type": "string"
          },
          "closedAt": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      }
    }
  }
}

GET /api/me/spending

Authentication signed-in session; roles: admin, cfo_viewer, fde, hr_ops, manager, member, operator

Response

FieldTypeDescription
wallets requiredarray of object
wallets[].id requiredstringThe answer's id.
wallets[].tenantIdstring
wallets[].ownerKindstring
wallets[].ownerIdstring
wallets[].kind requiredstring
wallets[].balanceMu requiredinteger
wallets[].heldMu requiredinteger
wallets[].currencyHintstring or null
wallets[].expiresAtstring or null
wallets[].spendPriorityinteger
wallets[].sourceKindstring or null
wallets[].sourceRefstring or null
wallets[].periodStartstring or null
wallets[].periodEndstring or null
wallets[].rolloverCapMuinteger or null
wallets[].createdAtstring
wallets[].closedAtstring or null
caps requiredarray of object
caps[].idstringThe answer's id.
caps[].periodstring
caps[].tierobject
caps[].botKeyobject
caps[].limitMuinteger or null
caps[].perRequestMuinteger or null
caps[].reservedMuinteger or null
caps[].spentMuinteger
caps[].periodStartedAtstring or null
caps[].runsOutAtstring or null
pause requiredobject or null
pause.pausedAtstring
pause.pausedBystring
pause.notestring or null
topUpPolicyobject or null
topUpPolicy.idstringThe answer's id.
topUpPolicy.amountMuinteger
topUpPolicy.triggerBalanceMuinteger
topUpPolicy.monthlyCeilingMuinteger or null
topUpIntents requiredarray of object
topUpIntents[].idstringThe answer's id.
topUpIntents[].amountMuinteger
topUpIntents[].reasonstring
topUpIntents[].statestring
topUpIntents[].periodStartstring
topUpIntents[].confirmedAtstring or null
topUpIntents[].createdAtstring
skippedRuns requiredarray of object
skippedRuns[].idstringThe answer's id.
skippedRuns[].reasonstring
skippedRuns[].detailstring or null
skippedRuns[].createdAtstring
trial requiredobject or null
trial.balanceMuinteger
trial.expiresAtstring or null
trial.daysLeftnumber
trial.freeLaneCallsThisPeriodinteger
Example response (shape)
{
  "wallets": [
    {
      "id": "<id>",
      "tenantId": "<tenantId>",
      "ownerKind": "<ownerKind>",
      "ownerId": "<ownerId>",
      "kind": "<kind>",
      "balanceMu": 0,
      "heldMu": 0,
      "currencyHint": "<currencyHint>",
      "expiresAt": "<expiresAt>",
      "spendPriority": 0,
      "sourceKind": "<sourceKind>",
      "sourceRef": "<sourceRef>",
      "periodStart": "<periodStart>",
      "periodEnd": "<periodEnd>",
      "rolloverCapMu": "<rolloverCapMu>",
      "createdAt": "<createdAt>",
      "closedAt": "<closedAt>"
    }
  ],
  "caps": [
    {
      "id": "<id>",
      "period": "<period>",
      "tier": "<tier>",
      "botKey": "<botKey>",
      "limitMu": "<limitMu>",
      "perRequestMu": "<perRequestMu>",
      "reservedMu": "<reservedMu>",
      "spentMu": 0,
      "periodStartedAt": "<periodStartedAt>",
      "runsOutAt": "<runsOutAt>"
    }
  ],
  "pause": {
    "pausedAt": "<pausedAt>",
    "pausedBy": "<pausedBy>",
    "note": "<note>"
  },
  "topUpPolicy": {
    "id": "<id>",
    "amountMu": 0,
    "triggerBalanceMu": 0,
    "monthlyCeilingMu": "<monthlyCeilingMu>"
  },
  "topUpIntents": [
    {
      "id": "<id>",
      "amountMu": 0,
      "reason": "<reason>",
      "state": "<state>",
      "periodStart": "<periodStart>",
      "confirmedAt": "<confirmedAt>",
      "createdAt": "<createdAt>"
    }
  ],
  "skippedRuns": [
    {
      "id": "<id>",
      "reason": "<reason>",
      "detail": "<detail>",
      "createdAt": "<createdAt>"
    }
  ],
  "trial": {
    "balanceMu": 0,
    "expiresAt": "<expiresAt>",
    "daysLeft": 0,
    "freeLaneCallsThisPeriod": 0
  }
}

Common errors

  • 401 not signed in

Every error has the same JSON shape; see Errors and Limits.

Full schema (JSON)

Response schema

{
  "description": "A session credential. With no personal workspace the page is empty (topUpPolicy is then absent).",
  "type": "object",
  "required": [
    "wallets",
    "caps",
    "pause",
    "topUpIntents",
    "skippedRuns",
    "trial"
  ],
  "properties": {
    "wallets": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "id",
          "kind",
          "balanceMu",
          "heldMu"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "tenantId": {
            "type": "string"
          },
          "ownerKind": {
            "type": "string"
          },
          "ownerId": {
            "type": "string"
          },
          "kind": {
            "type": "string"
          },
          "balanceMu": {
            "type": "integer"
          },
          "heldMu": {
            "type": "integer"
          },
          "currencyHint": {
            "type": [
              "string",
              "null"
            ]
          },
          "expiresAt": {
            "type": [
              "string",
              "null"
            ]
          },
          "spendPriority": {
            "type": "integer"
          },
          "sourceKind": {
            "type": [
              "string",
              "null"
            ]
          },
          "sourceRef": {
            "type": [
              "string",
              "null"
            ]
          },
          "periodStart": {
            "type": [
              "string",
              "null"
            ]
          },
          "periodEnd": {
            "type": [
              "string",
              "null"
            ]
          },
          "rolloverCapMu": {
            "type": [
              "integer",
              "null"
            ]
          },
          "createdAt": {
            "type": "string"
          },
          "closedAt": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      }
    },
    "caps": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "period": {
            "type": "string"
          },
          "tier": {},
          "botKey": {},
          "limitMu": {
            "type": [
              "integer",
              "null"
            ]
          },
          "perRequestMu": {
            "type": [
              "integer",
              "null"
            ]
          },
          "reservedMu": {
            "type": [
              "integer",
              "null"
            ]
          },
          "spentMu": {
            "type": "integer"
          },
          "periodStartedAt": {
            "type": [
              "string",
              "null"
            ]
          },
          "runsOutAt": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      }
    },
    "pause": {
      "type": [
        "object",
        "null"
      ],
      "properties": {
        "pausedAt": {
          "type": "string"
        },
        "pausedBy": {
          "type": "string"
        },
        "note": {
          "type": [
            "string",
            "null"
          ]
        }
      }
    },
    "topUpPolicy": {
      "type": [
        "object",
        "null"
      ],
      "properties": {
        "id": {
          "type": "string"
        },
        "amountMu": {
          "type": "integer"
        },
        "triggerBalanceMu": {
          "type": "integer"
        },
        "monthlyCeilingMu": {
          "type": [
            "integer",
            "null"
          ]
        }
      }
    },
    "topUpIntents": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "amountMu": {
            "type": "integer"
          },
          "reason": {
            "type": "string"
          },
          "state": {
            "type": "string"
          },
          "periodStart": {
            "type": "string"
          },
          "confirmedAt": {
            "type": [
              "string",
              "null"
            ]
          },
          "createdAt": {
            "type": "string"
          }
        }
      }
    },
    "skippedRuns": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "reason": {
            "type": "string"
          },
          "detail": {
            "type": [
              "string",
              "null"
            ]
          },
          "createdAt": {
            "type": "string"
          }
        }
      }
    },
    "trial": {
      "type": [
        "object",
        "null"
      ],
      "properties": {
        "balanceMu": {
          "type": "integer"
        },
        "expiresAt": {
          "type": [
            "string",
            "null"
          ]
        },
        "daysLeft": {
          "type": "number"
        },
        "freeLaneCallsThisPeriod": {
          "type": "integer"
        }
      }
    }
  }
}

A wallet has a balance and an amount held. A spending cap has a period, a limit, what is spent so far, and a forecast of the day it runs out. A person can pause spending, and the page lists the runs a pause skipped.

What happens when a budget runs out

Budgets degrade before they block. When a budget runs out the router first lowers autonomy or files a request for help; a hard stop comes after. When a request does stop for money it answers 402; see Errors.

Read usage with your relay key

Four read-only endpoints under /v1 take the relay key itself as the bearer, exactly as the completion endpoints do. A revoked, expired or unknown key is refused with the same 401 as everywhere else. They read the key's own ledgers: a decision of another key or another workspace is a 404, never a 403. Each costs one request against the key's rate limit.

curl
curl https://api.massrelay.ai/v1/key -H "Authorization: Bearer mrk_<prefix>_<secret>"

Key

GET /v1/key

Authentication relay key (bearer)

Example request

curl
curl https://api.massrelay.ai/v1/key \
  -H "Authorization: Bearer $RELAY_KEY"
Python
import os, requests

r = requests.get(
    "https://api.massrelay.ai/v1/key",
    headers={"Authorization": f"Bearer {os.environ['RELAY_KEY']}"},
)
r.raise_for_status()
print(r.json())
TypeScript
const r = await fetch("https://api.massrelay.ai/v1/key", {
  method: "GET",
  headers: { Authorization: `Bearer ${process.env.RELAY_KEY}` },
});
if (!r.ok) throw new Error(`${r.status} ${await r.text()}`);
console.log(await r.json());

Response

FieldTypeDescription
object requiredstringThe kind of object returned, for example chat.completion. Always "key".
id requiredstringThe answer's id.
prefix requiredstring
scopes requiredarray of string
budgetEnvelopeId requiredstring or null
expiresAt requiredstring or null
createdAt requiredstring
lastUsedAt requiredstring or null
unit requiredstring Always "mu".
spendMu requiredintegermicro-dollars, the unit of account
period requiredobject
period.from requiredstring
period.to requiredstring
Example response (shape)
{
  "object": "key",
  "id": "<id>",
  "prefix": "<prefix>",
  "scopes": [
    "<scopes>"
  ],
  "budgetEnvelopeId": "<budgetEnvelopeId>",
  "expiresAt": "<expiresAt>",
  "createdAt": "<createdAt>",
  "lastUsedAt": "<lastUsedAt>",
  "unit": "mu",
  "spendMu": 0,
  "period": {
    "from": "<from>",
    "to": "<to>"
  }
}

Common errors

  • 401 invalid_api_key
  • 403 insufficient_scope
  • 429 over the request rate; read Retry-After

Every error has the same JSON shape; see Errors and Limits.

Full schema (JSON)

Response schema

{
  "type": "object",
  "required": [
    "object",
    "id",
    "prefix",
    "scopes",
    "budgetEnvelopeId",
    "expiresAt",
    "createdAt",
    "lastUsedAt",
    "unit",
    "spendMu",
    "period"
  ],
  "properties": {
    "object": {
      "const": "key"
    },
    "id": {
      "type": "string"
    },
    "prefix": {
      "type": "string"
    },
    "scopes": {
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "budgetEnvelopeId": {
      "type": [
        "string",
        "null"
      ]
    },
    "expiresAt": {
      "type": [
        "string",
        "null"
      ]
    },
    "createdAt": {
      "type": "string"
    },
    "lastUsedAt": {
      "type": [
        "string",
        "null"
      ]
    },
    "unit": {
      "const": "mu"
    },
    "spendMu": {
      "type": "integer",
      "description": "micro-dollars, the unit of account"
    },
    "period": {
      "type": "object",
      "required": [
        "from",
        "to"
      ],
      "properties": {
        "from": {
          "type": "string"
        },
        "to": {
          "type": "string"
        }
      }
    }
  }
}

Returns the key's id, prefix, scopes, budget envelope, expiry, and what it spent this calendar month in mu. Never the hash.

Credits

GET /v1/credits

Authentication relay key (bearer)

Example request

curl
curl https://api.massrelay.ai/v1/credits \
  -H "Authorization: Bearer $RELAY_KEY"
Python
import os, requests

r = requests.get(
    "https://api.massrelay.ai/v1/credits",
    headers={"Authorization": f"Bearer {os.environ['RELAY_KEY']}"},
)
r.raise_for_status()
print(r.json())
TypeScript
const r = await fetch("https://api.massrelay.ai/v1/credits", {
  method: "GET",
  headers: { Authorization: `Bearer ${process.env.RELAY_KEY}` },
});
if (!r.ok) throw new Error(`${r.status} ${await r.text()}`);
console.log(await r.json());

Response

FieldTypeDescription
object requiredstringThe kind of object returned, for example chat.completion. Always "credits".
unit requiredstring Always "mu".
displayCurrency requiredstring or null
totalBalanceMu requiredintegermicro-dollars, the unit of account
totalAvailableMu requiredintegermicro-dollars, the unit of account
wallets requiredarray of object
wallets[].id requiredstringThe answer's id.
wallets[].kind requiredobject One of: prepaid, allowance, grant, pool, sponsor.
wallets[].balanceMu requiredintegermicro-dollars, the unit of account
wallets[].heldMu requiredintegermicro-dollars, the unit of account
wallets[].availableMu requiredintegermicro-dollars, the unit of account
wallets[].currency requiredstring or null
wallets[].expiresAt requiredstring or null
freeAllowanceLeft requiredinteger or nullrequests left in this month's free allowance; null when the plan has none
freeAllowance requiredobject or null
freeAllowance.meterstring
freeAllowance.planstring or null
freeAllowance.allowanceinteger
freeAllowance.usedinteger
freeAllowance.resetsAtstring
Example response (shape)
{
  "object": "credits",
  "unit": "mu",
  "displayCurrency": "<displayCurrency>",
  "totalBalanceMu": 0,
  "totalAvailableMu": 0,
  "wallets": [
    {
      "id": "<id>",
      "kind": "prepaid",
      "balanceMu": 0,
      "heldMu": 0,
      "availableMu": 0,
      "currency": "<currency>",
      "expiresAt": "<expiresAt>"
    }
  ],
  "freeAllowanceLeft": "<freeAllowanceLeft>",
  "freeAllowance": {
    "meter": "<meter>",
    "plan": "<plan>",
    "allowance": 0,
    "used": 0,
    "resetsAt": "<resetsAt>"
  }
}

Common errors

  • 401 invalid_api_key
  • 403 insufficient_scope
  • 429 over the request rate; read Retry-After

Every error has the same JSON shape; see Errors and Limits.

Full schema (JSON)

Response schema

{
  "description": "The wallets are the key's workspace's own (owner kind workspace).",
  "type": "object",
  "required": [
    "object",
    "unit",
    "displayCurrency",
    "totalBalanceMu",
    "totalAvailableMu",
    "wallets",
    "freeAllowanceLeft",
    "freeAllowance"
  ],
  "properties": {
    "object": {
      "const": "credits"
    },
    "unit": {
      "const": "mu"
    },
    "displayCurrency": {
      "type": [
        "string",
        "null"
      ]
    },
    "totalBalanceMu": {
      "type": "integer",
      "description": "micro-dollars, the unit of account"
    },
    "totalAvailableMu": {
      "type": "integer",
      "description": "micro-dollars, the unit of account"
    },
    "wallets": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "id",
          "kind",
          "balanceMu",
          "heldMu",
          "availableMu",
          "currency",
          "expiresAt"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "kind": {
            "enum": [
              "prepaid",
              "allowance",
              "grant",
              "pool",
              "sponsor"
            ]
          },
          "balanceMu": {
            "type": "integer",
            "description": "micro-dollars, the unit of account"
          },
          "heldMu": {
            "type": "integer",
            "description": "micro-dollars, the unit of account"
          },
          "availableMu": {
            "type": "integer",
            "description": "micro-dollars, the unit of account"
          },
          "currency": {
            "type": [
              "string",
              "null"
            ]
          },
          "expiresAt": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      }
    },
    "freeAllowanceLeft": {
      "type": [
        "integer",
        "null"
      ],
      "description": "requests left in this month's free allowance; null when the plan has none"
    },
    "freeAllowance": {
      "type": [
        "object",
        "null"
      ],
      "properties": {
        "meter": {
          "type": "string"
        },
        "plan": {
          "type": [
            "string",
            "null"
          ]
        },
        "allowance": {
          "type": "integer"
        },
        "used": {
          "type": "integer"
        },
        "resetsAt": {
          "type": "string"
        }
      }
    }
  }
}

Returns the wallets of the workspace that owns the key: balance, held and available per wallet in mu, with the currency the wallet shows in, plus freeAllowanceLeft, the requests left in this month's free allowance (null when the plan has none).

Generation

GET /v1/generation/{id}

Authentication relay key (bearer)

Path parameters

id requiredstring

Example request

curl
curl https://api.massrelay.ai/v1/generation/{id} \
  -H "Authorization: Bearer $RELAY_KEY"
Python
import os, requests

r = requests.get(
    "https://api.massrelay.ai/v1/generation/{id}",
    headers={"Authorization": f"Bearer {os.environ['RELAY_KEY']}"},
)
r.raise_for_status()
print(r.json())
TypeScript
const r = await fetch("https://api.massrelay.ai/v1/generation/{id}", {
  method: "GET",
  headers: { Authorization: `Bearer ${process.env.RELAY_KEY}` },
});
if (!r.ok) throw new Error(`${r.status} ${await r.text()}`);
console.log(await r.json());

Response

FieldTypeDescription
object requiredstringThe kind of object returned, for example chat.completion. Always "generation".
id requiredstringThe answer's id.
model requiredstring or nullThe model id. In a request it is optional: without it the key's routing chooses.
provider requiredstring or null
inputTokens requiredinteger
outputTokens requiredinteger
unit requiredstring Always "mu".
costMu requiredintegermicro-dollars, the unit of account
fee requiredobject or null
fee.costMuintegermicro-dollars, the unit of account
fee.planstring or null
fee.reasonstring or null
latencyMs requiredinteger or null
createdAt requiredstring or null
explain requiredstringthe /v1/route/explain/{id} path
Example response (shape)
{
  "object": "generation",
  "id": "<id>",
  "model": "provider/model-id",
  "provider": "<provider>",
  "inputTokens": 0,
  "outputTokens": 0,
  "unit": "mu",
  "costMu": 0,
  "fee": {
    "costMu": 0,
    "plan": "<plan>",
    "reason": "<reason>"
  },
  "latencyMs": "<latencyMs>",
  "createdAt": "<createdAt>",
  "explain": "<explain>"
}

Common errors

  • 401 invalid_api_key
  • 403 insufficient_scope
  • 429 over the request rate; read Retry-After

Every error has the same JSON shape; see Errors and Limits.

Full schema (JSON)

Response schema

{
  "description": "404 decision_not_found for another key's, another workspace's or a missing id.",
  "type": "object",
  "required": [
    "object",
    "id",
    "model",
    "provider",
    "inputTokens",
    "outputTokens",
    "unit",
    "costMu",
    "fee",
    "latencyMs",
    "createdAt",
    "explain"
  ],
  "properties": {
    "object": {
      "const": "generation"
    },
    "id": {
      "type": "string"
    },
    "model": {
      "type": [
        "string",
        "null"
      ]
    },
    "provider": {
      "type": [
        "string",
        "null"
      ]
    },
    "inputTokens": {
      "type": "integer"
    },
    "outputTokens": {
      "type": "integer"
    },
    "unit": {
      "const": "mu"
    },
    "costMu": {
      "type": "integer",
      "description": "micro-dollars, the unit of account"
    },
    "fee": {
      "type": [
        "object",
        "null"
      ],
      "properties": {
        "costMu": {
          "type": "integer",
          "description": "micro-dollars, the unit of account"
        },
        "plan": {
          "type": [
            "string",
            "null"
          ]
        },
        "reason": {
          "type": [
            "string",
            "null"
          ]
        }
      }
    },
    "latencyMs": {
      "type": [
        "integer",
        "null"
      ]
    },
    "createdAt": {
      "type": [
        "string",
        "null"
      ]
    },
    "explain": {
      "type": "string",
      "description": "the /v1/route/explain/{id} path"
    }
  }
}

Returns one decision: model, provider, tokens, cost in mu, the request-fee line when one was charged, latency, and the path of its explanation (/v1/route/explain/{id}).

Usage

GET /v1/usage

Authentication relay key (bearer)

Example request

curl
curl https://api.massrelay.ai/v1/usage \
  -H "Authorization: Bearer $RELAY_KEY"
Python
import os, requests

r = requests.get(
    "https://api.massrelay.ai/v1/usage",
    headers={"Authorization": f"Bearer {os.environ['RELAY_KEY']}"},
)
r.raise_for_status()
print(r.json())
TypeScript
const r = await fetch("https://api.massrelay.ai/v1/usage", {
  method: "GET",
  headers: { Authorization: `Bearer ${process.env.RELAY_KEY}` },
});
if (!r.ok) throw new Error(`${r.status} ${await r.text()}`);
console.log(await r.json());

Response

FieldTypeDescription
object requiredstringThe kind of object returned, for example chat.completion. Always "usage".
unit requiredstring Always "mu".
period requiredobject
period.from requiredstring
period.to requiredstring
endUserstring
requests requiredinteger
inputTokens requiredinteger
outputTokens requiredinteger
costMu requiredintegermicro-dollars, the unit of account
byEndUserarray of object
byEndUser[].endUser requiredstring
byEndUser[].requests requiredinteger
byEndUser[].inputTokens requiredinteger
byEndUser[].outputTokens requiredinteger
byEndUser[].costMu requiredintegermicro-dollars, the unit of account
Example response (shape)
{
  "object": "usage",
  "unit": "mu",
  "period": {
    "from": "<from>",
    "to": "<to>"
  },
  "endUser": "<endUser>",
  "requests": 0,
  "inputTokens": 0,
  "outputTokens": 0,
  "costMu": 0,
  "byEndUser": [
    {
      "endUser": "<endUser>",
      "requests": 0,
      "inputTokens": 0,
      "outputTokens": 0,
      "costMu": 0
    }
  ]
}

Common errors

  • 401 invalid_api_key
  • 403 insufficient_scope
  • 429 over the request rate; read Retry-After

Every error has the same JSON shape; see Errors and Limits.

Full schema (JSON)

Response schema

{
  "description": "Query: from, to (ISO date or datetime, default the UTC calendar month), end_user (one tag), group_by=end_user (one row per tag).",
  "type": "object",
  "required": [
    "object",
    "unit",
    "period",
    "requests",
    "inputTokens",
    "outputTokens",
    "costMu"
  ],
  "properties": {
    "object": {
      "const": "usage"
    },
    "unit": {
      "const": "mu"
    },
    "period": {
      "type": "object",
      "required": [
        "from",
        "to"
      ],
      "properties": {
        "from": {
          "type": "string"
        },
        "to": {
          "type": "string"
        }
      }
    },
    "endUser": {
      "type": "string"
    },
    "requests": {
      "type": "integer"
    },
    "inputTokens": {
      "type": "integer"
    },
    "outputTokens": {
      "type": "integer"
    },
    "costMu": {
      "type": "integer",
      "description": "micro-dollars, the unit of account"
    },
    "byEndUser": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "endUser",
          "requests",
          "inputTokens",
          "outputTokens",
          "costMu"
        ],
        "properties": {
          "endUser": {
            "type": "string"
          },
          "requests": {
            "type": "integer"
          },
          "inputTokens": {
            "type": "integer"
          },
          "outputTokens": {
            "type": "integer"
          },
          "costMu": {
            "type": "integer",
            "description": "micro-dollars, the unit of account"
          }
        }
      }
    }
  }
}

Returns the rollup of the key's ledger rows for a period: requests, tokens and cost. from and to take an ISO date or datetime (default: this UTC calendar month). end_user narrows to one end-user tag, and group_by=end_user returns one row per tag.

curl
curl "https://api.massrelay.ai/v1/usage?group_by=end_user" \
  -H "Authorization: Bearer mrk_<prefix>_<secret>"

Read the rate-limit headers

Every /v1 answer whose request reached the rate limiter carries the state of the limit that binds that key, read from the same evaluation that admitted the request, so a header never costs a second slot.

  • **X-RateLimit-Limit** — requests per minute of the binding limit (the key's, or its workspace's if that is tighter).
  • **X-RateLimit-Remaining** — whole requests still admitted right now without being queued.
  • **X-RateLimit-Reset** — seconds, rounded up, until one more request would be admitted without queueing (0 while some remain).
  • **Retry-After** — on a 429 only: seconds to wait, rounded up.

When no limit is configured for the key or its workspace, the three X-RateLimit-* headers are not sent. The same headers ride on streamed answers and on the 429. See Limits for how limits are applied.