Events, webhooks & billing
MOQOM gives your backend two feeds of truth:
- Room events — a gRPC server stream of everything that happens in a room or across your
tenant (
Events.StreamRoomEvents). - Billing state — your balance, admission status and recent ledger entries over REST
(
GET /v1/billing).
Room events
Section titled “Room events”flowchart LR
Room["Room activity<br/>joins · mutes · grants · moderation"] --> CP["Control plane"]
CP -- "StreamRoomEvents<br/>(gRPC server stream)" --> BE["Your backend"]
BE --> DB[("Your cursor:<br/>last sequence")]
| Event kind | Body |
|---|---|
PARTICIPANT_JOINED |
participant, first_device (true for the person’s first device) |
PARTICIPANT_LEFT |
identity, was_removed, code, last_device |
PRESENCE_CHANGED |
identity, from, to (connected, reconnecting, away, backgrounded, left) |
GRANTS_CHANGED |
identity, from, to |
MUTE_CHANGED |
identity and the full mute state: self_muted, forced_muted_for_everyone, forced_muted_for_audience |
SPOTLIGHT_CHANGED |
identity (unset when cleared) |
PUBLISH_STARTED / PUBLISH_STOPPED |
identity, track, started |
WATCHDOG_CHANGED |
watchdog, detached |
LIFECYCLE_CHANGED |
from, to, acting_host |
MODERATION_APPLIED |
the full ModerationEntry |
Delivery guarantees
Section titled “Delivery guarantees”- At-least-once, ordered per room.
- Each event carries a
sequencethat is contiguous within its room and never reused. A gap means you missed something. - Pass
after_sequenceto resume exactly where you stopped. Zero starts at the present — right for a dashboard, wrong for anything that must not miss an event. - A server restart closes the stream; reconnect from your cursor.
- Each event has
atand atimecode(instant + uncertainty + clock trust). Within one room, order bysequence, not by time.
Follow one room (room set) or every room in the tenant (room empty — the right choice for a
moderation queue). Filter with kind.
Billing state
Section titled “Billing state”curl -sS https://api.moqom.cloud/v1/billing -H "Authorization: Bearer $MOQOM_API_KEY"{ "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" }, "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" }, { "kind": "top_up", "amount": { "micros": 50000000, "display": "$50.000000" }, "reference": "pi_3Q…", "detail": "auto_top_up", "at": "2026-10-05T22:40:19Z" } ]}admitted— whether new sessions and tokens are being admitted right now. Alert onfalse.balance— prepaid credit remaining.recent— up to the 50 most recent ledger entries.last_top_up_error— present ontenantwhen an automatic top-up failed (for example, a declined card).
Ledger entry kinds
Section titled “Ledger entry kinds”kind |
Sign | Meaning |
|---|---|---|
top_up |
+ | A payment credited (checkout or automatic top-up). Activates a pending tenant. |
usage |
− | Usage charged. capped: true when the per-minute ceiling applied. reference is the room. |
refund |
− | A refunded payment, removed from credit. |
signup_credit |
+ | Promotional credit granted at signup. |
adjustment |
± | A manual correction by MOQOM. |
Recommended alerting
Section titled “Recommended alerting”- Poll
GET /v1/billingevery few minutes. - Alert when
admittedisfalseorbalancedrops below your threshold. - Turn on auto top-up so you rarely reach zero.
- Watch
last_top_up_errorfor card failures.
When credit runs out, joins return 402 and MintClientToken returns
FailedPrecondition; moderation keeps working throughout.