Appearance
Usage
What was used, what a credit buys, and the credit ledgers of the identities a tenant enforces.
Usage, summed by day, identity or room
GET /v1/usage
usage_records summed per group. A seat counts in the window it started in, so two windows never count one seat twice. A seat still live is counted as of the last 60-second flush (final: false). Relay bytes are reconciled from TURN hourly, so a group is turnBytesFinal: false until every seat in it has been — a number that will still grow, said so rather than quietly changed. Groups come in key order.
Credential: API key — Authorization: Bearer <api_key>.<api_secret>
Rate limit: read, 600 a minute
Parameters
| Name | In | Type | Description |
|---|---|---|---|
limit? | query | integer | 1–100. Default 20. |
cursor? | query | string | The nextCursor of the previous page. 1–512 characters. |
from? | query | string (date-time) | Seats that started at or after this. The first of the current month (UTC) if absent. |
to? | query | string (date-time) | Seats that started before this. Now if absent. |
groupBy? | query | string | One of day, identity, room. Default "day". |
identity? | query | string | One identity's seats only. 1–200 characters. |
Response 200 — One page of groups.
| Field | Type | Description |
|---|---|---|
from | string (date-time) | |
to | string (date-time) | |
groupBy | string | One of day, identity, room. |
data | UsageGroup[] | |
nextCursor | string | null | The cursor for the next page; null on the last. |
Errors
| Status | Code |
|---|---|
| 400 | validation_failed, token_ttl_too_long |
| 401 | unauthenticated, token_expired, token_replayed, token_not_yet_valid |
| 403 | permission_denied, app_suspended, quota_exhausted |
| 429 | rate_limited |
| 500 | internal |
What a credit buys
GET /v1/usage/rates
The tenant's rate table. A dimension it does not name costs nothing.
Credential: API key — Authorization: Bearer <api_key>.<api_secret>
Rate limit: read, 600 a minute
Response 200 — The rate table.
| Field | Type | Description |
|---|---|---|
rates | object | Credits per unit — a second, or a byte — by dimension. |
Errors
| Status | Code |
|---|---|
| 401 | unauthenticated, token_expired, token_replayed, token_not_yet_valid |
| 403 | permission_denied, app_suspended, quota_exhausted |
| 429 | rate_limited |
| 500 | internal |
Replace the rate table
PUT /v1/usage/rates
The whole table: a dimension left out is free from now on. Applies to seats charged from now — a seat is charged when it leaves, at the rates then in force.
Credential: API key — Authorization: Bearer <api_key>.<api_secret>
Rate limit: write, 120 a minute
Request body application/json
| Field | Type | Description |
|---|---|---|
rates | object | Credits per unit — a second, or a byte — by dimension. |
Response 200 — The rate table now.
| Field | Type | Description |
|---|---|---|
rates | object | Credits per unit — a second, or a byte — by dimension. |
Errors
| Status | Code |
|---|---|
| 400 | validation_failed, token_ttl_too_long |
| 401 | unauthenticated, token_expired, token_replayed, token_not_yet_valid |
| 403 | permission_denied, app_suspended, quota_exhausted |
| 429 | rate_limited |
| 500 | internal |
An identity's credit balance
GET /v1/credits/{identity}
Only an identity with an account is enforced; one with none is 404 and is never charged. The first entry written for an identity creates its account.
Credential: API key — Authorization: Bearer <api_key>.<api_secret>
Rate limit: read, 600 a minute
Parameters
| Name | In | Type | Description |
|---|---|---|---|
identity | path | string | The tenant's opaque identity string, URL-encoded. 1–200 characters. |
Response 200 — The account.
| Field | Type | Description |
|---|---|---|
identity | string | |
balance | integer | Credits. |
updatedAt | string (date-time) |
Errors
Write one ledger entry
POST /v1/credits/{identity}
A grant, refund, expiry or adjustment, in whole credits, and the balance it leaves. The ledger is the truth and the balance its sum. Idempotent on idempotencyKey, which is the tenant's and unique within it: the same entry again is answered with the one already written (replayed: true); the same key for a different entry is 409. Consumption is written by the platform, one entry per seat, never by a tenant.
Credential: API key — Authorization: Bearer <api_key>.<api_secret>
Rate limit: write, 120 a minute
Parameters
| Name | In | Type | Description |
|---|---|---|---|
identity | path | string | The tenant's opaque identity string, URL-encoded. 1–200 characters. |
Request body application/json
| Field | Type | Description |
|---|---|---|
delta | integer | Whole credits, signed. -1000000000000–1000000000000. |
reason | string | One of grant, refund, expiry, adjust. |
idempotencyKey | string | 1–200 characters. |
refType? | string | 1–60 characters. |
refId? | string | 1–200 characters. |
Response 201 — The entry and the balance after it.
| Field | Type | Description |
|---|---|---|
identity | string | |
balance | integer | null | The balance after the entry. |
entry | LedgerEntry | |
replayed | boolean | True when the key had already written this entry. |
Errors
The ledger, newest first
GET /v1/credits/{identity}/ledger
The answer to "why was I charged". Consumption is one entry per seat, with reason consume and refType participant.
Credential: API key — Authorization: Bearer <api_key>.<api_secret>
Rate limit: read, 600 a minute
Parameters
| Name | In | Type | Description |
|---|---|---|---|
identity | path | string | The tenant's opaque identity string, URL-encoded. 1–200 characters. |
limit? | query | integer | 1–100. Default 20. |
cursor? | query | string | The nextCursor of the previous page. 1–512 characters. |
Response 200 — One page of entries.
| Field | Type | Description |
|---|---|---|
data | LedgerEntry[] | |
nextCursor | string | null | The cursor for the next page; null on the last. |
Errors
| Status | Code |
|---|---|
| 400 | validation_failed, token_ttl_too_long |
| 401 | unauthenticated, token_expired, token_replayed, token_not_yet_valid |
| 403 | permission_denied, app_suspended, quota_exhausted |
| 429 | rate_limited |
| 500 | internal |