Skip to content

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).
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
  • At-least-once, ordered per room.
  • Each event carries a sequence that is contiguous within its room and never reused. A gap means you missed something.
  • Pass after_sequence to 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 at and a timecode (instant + uncertainty + clock trust). Within one room, order by sequence, 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.

Code: Go · Rust.

Terminal window
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 on false.
  • balance — prepaid credit remaining.
  • recent — up to the 50 most recent ledger entries.
  • last_top_up_error — present on tenant when an automatic top-up failed (for example, a declined card).
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.
  1. Poll GET /v1/billing every few minutes.
  2. Alert when admitted is false or balance drops below your threshold.
  3. Turn on auto top-up so you rarely reach zero.
  4. Watch last_top_up_error for card failures.

When credit runs out, joins return 402 and MintClientToken returns FailedPrecondition; moderation keeps working throughout.