Skip to main content

REST API Overview

The REST control plane lives at:

https://rms.metered.ca/v1

Five endpoints, all authenticated with your secret key pair (sk_id_…:sk_secret_…) via the Bearer header.

MethodPathPurpose
POST/v1/tokensMint a JWT for a peer (alternative to signing one yourself)
GET/v1/channels/:id/peersList peers currently subscribed to a channel
POST/v1/channels/:id/publishPublish to a channel from your backend, no WebSocket needed
DELETE/v1/peers/:idForcibly close every WebSocket owned by a peer (admin kick)
GET/v1/usageLive concurrent count + period totals + plan limits

Authentication

Authorization: Bearer sk_id_xxxxxxxx:sk_secret_xxxxxxxx

The credential is your secret key pair, colon-joined: the key id (sk_id_…) and its signing secret (sk_secret_…). The key id alone is not accepted — it travels in the public kid header of every browser JWT, so the signing secret must accompany it to prove the call came from your backend.

  • sk_ keys only. pk_live_… keys are rejected — they're shipped to browsers and must never be able to mint tokens or kick peers.
  • The sk_ key's channelPatterns and actions apply to channel-scoped REST endpoints: a key that can't subscribe to app_abc/* can't GET /v1/channels/app_abc/room-1/peers either.

Errors

All endpoints share an error shape:

{
"error": "channel_not_authorized",
"message": "channel not in key's allowed patterns: other-app/room-1"
}

error is the machine-readable code (stable); message is human-readable detail (informational).

Error codes by HTTP status

HTTPError codesWhen
400invalid_request, channel_reservedMalformed body, missing required fields, reserved channel name
401unauthorizedMissing / malformed credential, missing or wrong secret, key id without its secret, unknown sk, pk used by mistake
403channel_not_authorized, action_not_permittedsk_ valid but lacking scope for this resource
404not_foundUnknown endpoint
413invalid_requestBody exceeds 32 KB cap (REST endpoint cap; WS layer caps at 64 KB)
429(no error code; HTTP only)Per-IP / per-key rate limit hit on REST
503internal_errorPlan-cache failure, infra blip

Same-status-different-code is timing-safe for auth: unauthorized covers unknown / revoked / wrong-type keys with the same response so attackers can't enumerate valid keyIds.

Where to find your sk_ key

  1. DashboardRealtime MessagingKeys
  2. Click + Create key, choose type Secret
  3. Copy the signing secret when it's shown — it is never shown again

Send both parts as the Bearer credential, colon-joined: sk_id_…:sk_secret_…. The sk_secret_… is also your JWT signing material if you mint tokens yourself instead of calling POST /v1/tokens.

OpenAPI spec

Full machine-readable schema for the five endpoints:

Common patterns

You want toUse
Get a connect token to ship to a logged-in userPOST /v1/tokens — recommended; alternative is signing the JWT yourself
Send a server-side broadcast (chat moderation, AI-agent fan-out)POST /v1/channels/:id/publish
Know who's currently in a roomGET /v1/channels/:id/peers
Implement a user-initiated logout that drops their WebSocketDELETE /v1/peers/:id
Read live usage for a billing widgetGET /v1/usage