Skip to main content
Every FaceMode session uses two credentials: Both are secrets. Neither belongs in browser code, mobile apps, or logs.

REST API keys

Sending the key

Pass the key in the x-api-key header or in Authorization with the Bearer, ApiKey, or Api-Key scheme:
Keys that do not start with fm_ are rejected. Only the key’s SHA-256 hash is stored - FaceMode never keeps the plaintext key.

Creating a key

Create keys in the FaceMode console, or programmatically with POST /api/keys (requires the keys:write scope):
The raw key is returned exactly once, in apiKey.key. Store it immediately - it cannot be retrieved again. Up to 5 keys per account; expiresAt is optional (omit for no expiry).

Scopes

Each key carries a set of scopes. A call without the required scope fails with 403 and code AUTH_INSUFFICIENT_SCOPE. Default scopes for a new key: sessions:create, sessions:read, sessions:end, avatars:read, usage:read. Request additional scopes at key creation; grant only what your backend needs.

Key errors

Session WebSocket tokens

POST /api/sessions (and /reconnect) returns ingestion.wsToken - a signed JWT that authorizes exactly one WebSocket connection to the session’s ingestion endpoint.

Connecting

Send the token as a WebSocket subprotocol with the facemode. prefix:
On the wire this becomes Sec-WebSocket-Protocol: facemode.<wsToken>; the server echoes the same subprotocol back on accept. Clients that cannot set subprotocols (some browsers, embedded SDKs) may pass the same JWT as a query parameter instead:
Only the facemode. subprotocol prefix is accepted. Other prefixes are rejected before the handshake completes.

Token rules

  • 15-minute expiry. The JWT is signed with exp 15 minutes from issue.
  • Single use. A successful handshake consumes the token. Never reconnect with a consumed token - it will be rejected.
  • Fresh token on reconnect. POST /api/sessions/:id/reconnect returns a new ingestion.wsToken each call. Reconnect as many times as needed.
  • Scoped to one session. A token only opens the WebSocket URL issued with it; it cannot be reused across sessions.

Security rules

  • Keep the API key and wsToken on your server. The browser only ever receives the room URL and a separate viewer token you mint for that user - never the publisher roomToken FaceMode uses to publish.
  • Never log tokens. API keys, room tokens, wsToken JWTs, and the ?token= query string must be redacted in logs, error reports, and analytics.
  • Treat a wsToken like a password until it is consumed or expires: anyone holding it can open the session’s audio channel.
  • Rotate API keys if one may have leaked; revoke unused keys with DELETE /api/keys/:id (keys:delete scope).

Error envelope

Failed REST calls return a consistent shape:
Server-side failures arrive over the WebSocket as {"type": "error", "code": "...", "message": "...", "fatal": bool}. A fatal error closes the connection; reconnect with a fresh wsToken.