21-Apr-2026 — Tenants and API tokens


A tenant is the scope your data lives in. An API token authorises calls against exactly one tenant. You will need at least one of each before the public API will return anything.

← Back to the overview

Tenants

A tenant is either:

The kind matters for the API path: groups are queried as /api/groups/{code}/members, areas as /api/areas/{code}/members.

The dashboard sidebar lists every tenant you own. Click + New to add one, or click an existing code (KT, KT06) to open its detail pane.

Create a tenant

In the dashboard sidebar, click + New next to "Tenants" and fill in:

Hit Create. The tenant appears in the sidebar; click it to open the detail pane, which has three tabs: Members, Generate, and Tokens.

Tenant codes are globally unique

Tenant codes are unique across the whole mock server, not just per operator. If KT50 has already been claimed by someone else, you'll get a 409 conflict on create. Pick a different code, or request a transfer.

This is intentional: the public API path /api/groups/{code}/members would otherwise be ambiguous, and downstream consumers wouldn't know whose dataset they were calling against.

API tokens

Open the tenant's Tokens tab. Each token authorises calls against this tenant only — there is no concept of a multi-tenant or operator-wide token.

The Tokens tab inside a tenant's detail pane. Type a label, hit Generate token, and copy the revealed plaintext immediately — it's only shown once.

Generate a token

Type a human-readable label (the input placeholder shows MailMan - NS03 dev as one example; NGX production sync and James local laptop are equally fine — the label is just for your own bookkeeping) and hit Generate token.

A panel reveals the full token string with a Copy button. Copy it now. The plaintext is shown exactly once; on the next page load all you'll see is the 16-character prefix in the table below. The server stores only a SHA-256 hash, so nobody — not even the root operator — can retrieve the original after generation.

Token format

rsm_<tenantCode>_<48-hex-random>

The tenant code is baked into the plaintext. That makes the prefix self-identifying: skim a log, see rsm_KT50_…, and you immediately know which tenant the request was scoped to. The 48-hex suffix is generated from crypto.randomBytes(24), so the keyspace is 192 bits.

Where to store it

A password manager, a GitHub Actions secret, a Fly.io secret, or whatever your team uses — anywhere except a checked-in file.

Revoke a token

In the same Tokens table, every non-revoked row has a Revoke button. Revocation is immediate and one-way: the token row stays in the table for audit, but any call presenting that token will fail with 401.

If you lose a token, revoke it and generate a new one. There is no recovery path.

Security model summary

Next

Loading member data →