Skip to main content

GET /v1/usage

Live composite of: current concurrent connections, period totals, overage accrual, and your plan limits. Same numbers the dashboard's Realtime Messaging → Usage page displays.

Endpoint

GET https://rms.metered.ca/v1/usage
Authorization: Bearer sk_live_xxx...

The endpoint is scoped to whichever app the sk_ belongs to — there's no :appId in the path.

Response — 200 OK

{
"appId": "app_abc",
"periodStartUnix": 1714435200,
"periodEndUnix": 1717027200,
"concurrentNow": 7,
"peakConcurrent": 132,
"messagesUsed": 47813,
"overageMessages": 0,
"overageConnections": 0,
"plan": {
"name": "SIGNALLING_BASIC",
"maxConcurrentConnections": 1000,
"maxMessagesPerPeriod": 5000000,
"overagesAllowed": true,
"overagesEnabled": true
}
}
FieldTypeNotes
appIdstringYour app's ID.
periodStartUnix / periodEndUnixint | nullCurrent billing-period boundary. null for brand-new customers who haven't had a period set yet.
concurrentNowintLive count. Updated on connect/disconnect.
peakConcurrentintMaximum simultaneous connections observed this period. Used for billing on the concurrent axis.
messagesUsedintCumulative messages attempted this period (publish + send). Includes soft-dropped over-quota attempts.
overageMessagesintMessages billed at overage rate so far this period. Lags real-time by ≤60s (one server flush interval).
overageConnectionsintConcurrent-admit overages billed so far this period. Same ≤60s lag.
plan.namestring | nullPlan tier identifier (e.g. SIGNALLING_FREE, SIGNALLING_BASIC, SIGNALLING_BUNDLED).
plan.maxConcurrentConnections / plan.maxMessagesPerPeriodintPlan caps on each axis.
plan.overagesAllowedboolWhether the plan permits overages at all (free tier: false).
plan.overagesEnabledboolCustomer toggle (defaults to true on tiers where overages are allowed).

Errors

HTTPerrorWhen
401unauthorizedsk_ missing / invalid
503internal_errorPlan lookup failed (auth-API blip). Retry after a short backoff — live signalling traffic is NOT affected by this error.

Freshness

  • concurrentNow is live — the underlying counter is incremented/decremented per connect/disconnect.
  • peakConcurrent is set-if-greater on every connect, so it's also effectively live for the live workload.
  • messagesUsed is incremented per message, live.
  • overageMessages / overageConnections lag by ≤60s — they reflect what's been flushed and billed, not what's still in-flight on the signalling-server's pending counter. The dashboard shows the same lag.

Example — curl

curl https://rms.metered.ca/v1/usage \
-H "Authorization: Bearer sk_live_xxx..."

Example — building a customer-facing usage widget

usage-widget.tsx
async function fetchUsage() {
const resp = await fetch(
"https://rms.metered.ca/v1/usage",
{ headers: { Authorization: `Bearer ${SK}` } },
);
if (!resp.ok) throw new Error(`usage fetch failed: ${resp.status}`);
return resp.json();
}

// Render
const usage = await fetchUsage();
const concurrentPct = Math.round(100 * usage.peakConcurrent / usage.plan.maxConcurrentConnections);
const messagesPct = Math.round(100 * usage.messagesUsed / usage.plan.maxMessagesPerPeriod);

return (
<div>
<Bar label="Concurrent peak" value={concurrentPct} caption={`${usage.peakConcurrent} / ${usage.plan.maxConcurrentConnections}`} />
<Bar label="Messages used" value={messagesPct} caption={`${usage.messagesUsed} / ${usage.plan.maxMessagesPerPeriod}`} />
{usage.overageMessages > 0 && (
<p className="text-yellow-700">+ {usage.overageMessages} overage messages this period</p>
)}
</div>
);

Same shape as the Realtime Messaging → Usage dashboard page — feel free to point the widget directly at the dashboard URL instead of building your own.