Skip to content

Billing & keys REST API

The billing API is plain JSON over HTTPS.

Base URL https://api.moqom.cloud
Auth Authorization: Bearer mqk_<16 hex>_<secret>
Content type application/json (requests and responses)
Caching Every response is Cache-Control: no-store
Request bodies At most 1 MiB. Unknown fields are rejected with 400.
Money Integers in micro-dollars plus a display string (see below)

Every amount is an object:

{ "micros": 50000000, "display": "$50.000000" }

micros is millionths of a US dollar (1 USD = 1,000,000 micros), so sub-cent usage charges are exact. Request bodies take cents (amount_cents, below_cents).

Errors are a JSON object with a single message:

{ "error": "insufficient credit: top up to admit new sessions" }
Status When
400 Invalid request: malformed JSON, unknown field, out-of-range value
401 Missing, malformed, unknown or revoked key — or a key of the wrong kind
402 Payment required (tenant never paid) or insufficient credit
403 Tenant suspended, archived or deleted
404 Not found
409 Conflict: already exists, or a status change that is not allowed
429 Rate limited (signup)
502 Upstream payment provider (Stripe) error
503 Payments are not configured on this deployment
500 Internal error (message is always "internal error")

See the full error codes table.

Routes marked backend key require a key of kind backend; a relay key gets 401 on them. POST /v1/usage takes a relay key — see the Usage reporting API.

Method Path Auth Purpose
GET /v1/rates none Public rate card
POST /v1/signup none New tenant, first API key, first checkout
GET /v1/billing backend key Balance, status, recent ledger
POST /v1/billing/checkout backend key Open a top-up checkout
POST /v1/billing/portal backend key Open the Stripe customer portal
PUT /v1/billing/auto-top-up backend key Configure automatic top-ups
GET /v1/keys backend key List keys
POST /v1/keys backend key Issue a key (secret shown once)
DELETE /v1/keys/{id} backend key Revoke a key
POST /v1/usage relay key Report usage (reference)
POST /v1/stripe/webhook Stripe signature Reserved for Stripe — not for customer use

The rate card in force. No authentication.

Terminal window
curl -sS https://api.moqom.cloud/v1/rates
{
"currency": "usd",
"model": "prepaid, cost-plus, capped",
"egress_cost_per_gib": { "micros": 120000, "display": "$0.120000" },
"markup_basis_points": 1500,
"platform_fee_per_gib": { "micros": 10000, "display": "$0.010000" },
"ceiling_per_1000_participant_minutes": {
"host": {
"audio": { "micros": 980000, "display": "$0.980000" },
"hd": { "micros": 3980000, "display": "$3.980000" },
"full_hd": { "micros": 8980000, "display": "$8.980000" },
"2k": { "micros": 15980000, "display": "$15.980000" },
"2k_plus": { "micros": 35980000, "display": "$35.980000" }
},
"audience": {
"audio": { "micros": 980000, "display": "$0.980000" },
"hd": { "micros": 3980000, "display": "$3.980000" },
"full_hd": { "micros": 8980000, "display": "$8.980000" },
"2k": { "micros": 15980000, "display": "$15.980000" },
"2k_plus": { "micros": 35980000, "display": "$35.980000" }
},
"broadcast_audience": {
"audio": { "micros": 580000, "display": "$0.580000" },
"hd": { "micros": 1980000, "display": "$1.980000" },
"full_hd": { "micros": 4580000, "display": "$4.580000" },
"2k": { "micros": 7980000, "display": "$7.980000" },
"2k_plus": { "micros": 17980000, "display": "$17.980000" }
}
}
}
Field Meaning
egress_cost_per_gib MOQOM’s bandwidth cost basis per GiB of relay egress
markup_basis_points Markup on cost; 1500 = 15%
platform_fee_per_gib Fee per GiB of egress, charged whoever hosts the relay
ceiling_per_1000_participant_minutes The cap, by role and tier

The values above are illustrative; the live response is authoritative. See Pricing model.


Creates a tenant, its first backend API key (named default), and a checkout for the first top-up. The tenant is pending until that payment succeeds. No authentication; limited to 5 signups per hour per client address (429 beyond that).

Field Type Rules
email string A valid address, at most 254 characters
name string 1–200 characters
Terminal window
curl -sS https://api.moqom.cloud/v1/signup \
-H 'Content-Type: application/json' \
-d '{"email":"dev@example.com","name":"Example Inc"}'

201 Created

{
"tenant": "t_3f9a0c1d2e4b5a69",
"status": "pending",
"api_key": "mqk_9c1e2f3a4b5d6e7f_x2VtQ…",
"key_id": "9c1e2f3a4b5d6e7f",
"checkout_url": "https://checkout.stripe.com/c/pay/cs_…",
"note": "The API key is shown once. Store it now; it cannot be recovered, only revoked and replaced."
}

checkout_url is for the default first top-up. If it could not be opened, it is empty and you can open one later with POST /v1/billing/checkout using the new key.


Balance, status and recent ledger for the key’s tenant. Backend key.

Terminal window
curl -sS https://api.moqom.cloud/v1/billing \
-H "Authorization: Bearer $MOQOM_API_KEY"

200 OK

{
"tenant": {
"id": "t_3f9a0c1d2e4b5a69",
"name": "Example Inc",
"email": "dev@example.com",
"status": "active",
"has_card": true,
"auto_top_up": {
"enabled": false,
"below": { "micros": 0, "display": "$0.000000" },
"amount": { "micros": 0, "display": "$0.000000" }
},
"created_at": "2026-10-01T17:03:11Z"
},
"balance": { "micros": 41237500, "display": "$41.237500" },
"admitted": true,
"recent": [
{
"kind": "usage",
"amount": { "micros": -3980, "display": "-$0.003980" },
"capped": true,
"reference": "live/42",
"at": "2026-10-06T09:16:02Z"
}
]
}
Field Meaning
tenant.status pending, active, suspended, archived, deleted
tenant.has_card A saved payment method exists (needed for auto top-up)
tenant.last_top_up_error Present when the last automatic top-up failed
balance Prepaid credit remaining
admitted Whether new sessions and tokens are admitted now
recent[] Up to 50 recent ledger entries: kind, amount, capped, reference, detail, at

Opens a hosted checkout page for buying credit. Backend key.

Field Type Rules
amount_cents integer Whole cents, from $10.00 (1000) to $10,000.00 (1000000)
Terminal window
curl -sS https://api.moqom.cloud/v1/billing/checkout \
-H "Authorization: Bearer $MOQOM_API_KEY" \
-H 'Content-Type: application/json' \
-d '{"amount_cents": 5000}'

200 OK

{ "checkout_url": "https://checkout.stripe.com/c/pay/cs_…" }

After payment the customer returns to moqom.cloud; credit is added when the payment succeeds. Errors: 400 out of range, 403 tenant archived/deleted, 502 Stripe error, 503 payments not configured.


Opens the Stripe customer portal (receipts, saved cards). Backend key. No body.

Terminal window
curl -sS -X POST https://api.moqom.cloud/v1/billing/portal \
-H "Authorization: Bearer $MOQOM_API_KEY"

200 OK

{ "portal_url": "https://billing.stripe.com/p/session/…" }

400 if the tenant has never paid (there is nothing to manage yet).


Configures automatic top-ups: when a usage charge takes the balance below below_cents, MOQOM charges the saved card amount_cents. Backend key.

Field Type Rules
enabled boolean
below_cents integer Threshold, not negative
amount_cents integer When enabled: $10.00–$10,000.00
Terminal window
curl -sS -X PUT https://api.moqom.cloud/v1/billing/auto-top-up \
-H "Authorization: Bearer $MOQOM_API_KEY" \
-H 'Content-Type: application/json' \
-d '{"enabled": true, "below_cents": 1000, "amount_cents": 5000}'

200 OK — the updated tenant:

{
"id": "t_3f9a0c1d2e4b5a69",
"name": "Example Inc",
"email": "dev@example.com",
"status": "active",
"has_card": true,
"auto_top_up": {
"enabled": true,
"below": { "micros": 10000000, "display": "$10.000000" },
"amount": { "micros": 50000000, "display": "$50.000000" }
},
"created_at": "2026-10-01T17:03:11Z"
}

Auto top-up needs a saved card, which is stored when you pay a checkout. See Top-ups & auto top-up.


Lists the tenant’s keys, including revoked ones. Secrets are never returned. Backend key.

Terminal window
curl -sS https://api.moqom.cloud/v1/keys -H "Authorization: Bearer $MOQOM_API_KEY"

200 OK

{
"keys": [
{ "id": "9c1e2f3a4b5d6e7f", "name": "default", "kind": "backend", "created_at": "2026-10-01T17:03:11Z" },
{ "id": "5b7e0d2a9c3f1e48", "name": "relay-us-east-1", "kind": "relay", "created_at": "2026-10-06T09:12:44Z" },
{ "id": "0a1b2c3d4e5f6a7b", "name": "old-ci", "kind": "backend", "created_at": "2026-09-02T10:00:00Z", "revoked_at": "2026-10-02T08:30:00Z" }
]
}

Issues a new key. The plaintext api_key appears only in this response. Backend key.

Field Type Rules
name string 1–100 characters
kind string backend (default) or relay
Terminal window
curl -sS https://api.moqom.cloud/v1/keys \
-H "Authorization: Bearer $MOQOM_API_KEY" \
-H 'Content-Type: application/json' \
-d '{"name":"prod-backend","kind":"backend"}'

201 Created

{
"key": { "id": "7f6e5d4c3b2a1908", "name": "prod-backend", "kind": "backend", "created_at": "2026-10-06T09:20:00Z" },
"api_key": "mqk_7f6e5d4c3b2a1908_Q1wE…"
}

Revokes a key immediately. Backend key.

Terminal window
curl -sS -X DELETE https://api.moqom.cloud/v1/keys/0a1b2c3d4e5f6a7b \
-H "Authorization: Bearer $MOQOM_API_KEY"

204 No Content

You cannot revoke the key the request is authenticated with (400): issue a replacement first, then revoke the old key using the new one. 404 if no such key exists in your tenant.


Rotates a key with no gap in service. Backend key. Issues a replacement with the same name and kind, and keeps the old key working for overlap_seconds (default 86400, at most 604800) while you roll the new one out. Live sessions are never affected: client tokens don’t depend on the API key that minted them.

Terminal window
curl -sS -X POST https://api.moqom.cloud/v1/keys/0a1b2c3d4e5f6a7b/rotate \
-H "Authorization: Bearer $MOQOM_API_KEY" \
-d '{"overlap_seconds": 3600}'

201 Created

{
"key": { "id": "9f8e7d6c5b4a3921", "name": "production", "kind": "backend", "created_at": "2026-10-06T13:00:00Z" },
"api_key": "mqk_9f8e7d6c5b4a3921_…",
"old_key_retires": "2026-10-06T14:00:00Z"
}

The new key is shown once. Until old_key_retires, GET /v1/keys lists the old key with retires_at; afterwards with revoked_at. Revoking a retiring key early is allowed. Rotating the key the request is authenticated with is allowed too.


MOQOM’s receiver for Stripe events, verified by Stripe’s signature. It is listed here only so you recognise it; it is not part of the customer API.