Usage reporting API
Self-hosted relays report what they served with POST /v1/usage. MOQOM rates each record,
charges your prepaid balance, and tells the relay whether to keep admitting new sessions.
| Endpoint | POST https://api.moqom.cloud/v1/usage |
| Auth | Authorization: Bearer mqk_… with a relay key |
| Batch size | At most 5,000 records per request |
| Body | At most 1 MiB; unknown fields rejected |
| Idempotency | Per record, by id |
Backend keys are refused here (401); relay keys are refused everywhere else.
Request
Section titled “Request”{ "records": [ { "id": "relay-eu-1:2026-10-06T09:15:00Z:bea/41d07a9e", "tenant": "t_3f9a0c1d2e4b5a69", "room": "live/42", "participant": "bea/41d07a9e", "role": "broadcast_audience", "tier": "full_hd", "seconds": 60, "egress_bytes": 104857600, "ingress_bytes": 0 } ]}Record fields
Section titled “Record fields”| Field | Type | Required | Rules |
|---|---|---|---|
id |
string | yes | 1–200 characters. Unique per participant-interval from your relay. Makes the record idempotent. |
tenant |
string | no | Optional with a relay key. If present it must equal the key’s tenant, or the request is rejected. |
room |
string | no | Room name. Shown as the ledger entry’s reference. |
participant |
string | no | Participant identifier, for your own reconciliation. |
role |
string | yes | host, audience, or broadcast_audience |
tier |
string | yes | audio, hd, full_hd, 2k, 2k_plus — see Tiers |
seconds |
integer | yes | Connected time in this interval, 0–86400 |
egress_bytes |
integer | yes | Bytes sent to this participant, ≥ 0 |
ingress_bytes |
integer | yes | Bytes received from this participant, ≥ 0 |
Tier is chosen by the sum of pixels of every video stream the participant received at
once — audio-only is audio; up to 1280×720 is hd; up to 1920×1080 full_hd; up to
2560×1440 2k; above that 2k_plus.
Choosing ids
Section titled “Choosing ids”The id is what makes retries safe: a record whose id has already been charged for your tenant
is counted as a duplicate and charged nothing. A good id combines relay, interval start and
participant, e.g. relay-eu-1:2026-10-06T09:15:00Z:bea/41d07a9e. Never reuse an id for a
different interval.
Validation
Section titled “Validation”The whole request is rejected with 400 (and nothing is charged) if any record:
- has an empty or over-long
id, - has an unknown
roleortier, - has negative quantities or
secondsabove 86,400, - names a different tenant from the relay key’s.
There are more than 5,000 records → 400 at most 5000 records per report.
Response
Section titled “Response”200 OK
{ "charged": 1, "duplicates": 0, "unbilled": 0, "total": { "micros": 977, "display": "$0.000977" }, "admitted": true}| Field | Meaning |
|---|---|
charged |
Records charged in this request |
duplicates |
Records whose id was already charged — safe to ignore |
unbilled |
Records accepted but not charged (e.g. exempt test tenants) |
total |
Sum charged by this request |
admitted |
Whether the tenant may admit new sessions. When false, stop admitting new sessions until it returns to true. |
Retry policy
Section titled “Retry policy”- On a network error, timeout or
5xx: retry the same batch with the same ids. Duplicates are free. - On
400: fix the batch; retrying unchanged will fail again. - On
401: the relay key is wrong or revoked.
How a record is priced
Section titled “How a record is priced”Self-hosted records are charged the per-GiB platform fee on egress_bytes only, capped by the
per-minute ceiling for the record’s role and tier:
charge = min( platform_fee_per_gib × egress_GiB , ceiling(role, tier) × seconds / 60,000 )where ceiling is the price per 1,000 participant-minutes from
GET /v1/rates. The example above —
100 MiB at a $0.01/GiB fee — is about $0.000977, well under the Full HD broadcast-audience
ceiling for one minute ($0.00458). See Self-hosted fee.
After a batch is charged, auto top-up runs if the balance fell below your threshold.