Client tokens are short-lived JWTs that let you safely expose Titan API access in browser environments, serverless functions, and embedded widgets — without putting your server API key in client-side code. You mint a token on your server and pass it to the client. The token carries zero permissions on its own; all access control is enforced server-side through rules you configure per session. Client tokens use the sameDocumentation Index
Fetch the complete documentation index at: https://docs.usetitan.app/llms.txt
Use this file to discover all available pages before exploring further.
Authorization: Bearer {token} header as server keys. The API detects the titan_ct_ prefix and applies the client token rules for that session.
Client tokens require the
sessions:manage scope on your server API key. Tokens themselves cannot mint new tokens, read rules, or access management endpoints.How client tokens work
- You configure rules for a session (
PUT /api/sessions/{session}/client-rules) defining what actions are allowed, rate limits, and recipient restrictions. - Your server mints a token for a specific user or browser session (
POST /api/client-tokens), scoping it to a session and a developer-providedephemeralId. - Your client receives the token and uses it as a bearer token. The API enforces the rules on every request.
- After the token expires (default 15 minutes), your server mints a new one.
Allowed actions
Client tokens can only call these routes, subject to the configuredallowedActions:
| Action | Routes |
|---|---|
send_message | POST /{session}/messages/send |
send_reaction | POST /{session}/messages/react |
send_typing | POST /{session}/messages/typing |
send_seen | POST /{session}/messages/seen |
read_presence | GET /{session}/presence, GET /{session}/presence/{chatId} |
subscribe_presence | POST /{session}/presence/{chatId}/subscribe |
read_contact | GET /{session}/contacts, GET /{session}/contacts/{id}, GET /{session}/contacts/{id}/picture, POST /{session}/contacts/check |
Recipient modes
TherecipientMode rule controls who a client token can send messages to:
| Mode | Behavior |
|---|---|
none | Sending is disabled. Only read actions work. |
conversation | Can only reply to JIDs that have already messaged the session. Prevents initiating new conversations. |
any | Can message any JID. |
verified | Reserved for future use. |
Mint a client token
POST /api/client-tokens
Mints a new client token scoped to a session. Call this from your server — never from the client.
The WhatsApp session the token is scoped to. A token minted for session
A cannot access session B.A developer-provided identifier for rate limiting and correlation. Use a value that uniquely identifies the browser, user, or tab (e.g.
user-123-tab-1). This ID is used to enforce per-ephemeral-ID rate limits.Token lifetime in seconds. Minimum
1. Maximum set by the CLIENT_TOKEN_MAX_TTL environment variable (default 900).The client token string (
titan_ct_...). Pass this to the client.ISO 8601 timestamp when the token expires.
Get client rules
GET /api/sessions/{session}/client-rules
Returns the current client token rules for the session. Returns 404 if no rules are configured.
Session name.
Set client rules
PUT /api/sessions/{session}/client-rules
Creates or replaces client token rules for the session. Changes take effect immediately on the next request.
Session name.
Controls who client tokens can send messages to:
none, conversation, any, or verified.Whether client tokens are accepted for this session. Set to
false to deny all client token requests immediately.Comma-separated list of permitted actions. Example:
"send_message,send_reaction,send_typing,send_seen". Omit to deny all actions.Maximum requests per minute per
ephemeralId. Uses a sliding window. 0 means unlimited.Maximum send actions (messages and reactions) per day per
ephemeralId. 0 means unlimited.Comma-separated list of allowed CORS origins (e.g.
"https://myapp.com,https://staging.myapp.com"). Leave empty to skip origin checking.Delete client rules
DELETE /api/sessions/{session}/client-rules
Deletes all client token rules for the session. Any existing client tokens for this session are immediately denied — there is no grace period.
Session name.
SDK example
Here is a complete example using the TypeScript SDK to set up client tokens for a support widget:Error responses
| Status | Condition |
|---|---|
400 | Invalid body, missing required fields, TTL out of range, invalid recipientMode |
401 | Invalid or expired token, bad signature, no rules configured for the session |
403 | Denied route, session mismatch, action not in allowedActions, recipient not in conversation list, origin not allowed |
429 | Per-minute rate limit or daily cap exceeded |