Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.usetitan.app/llms.txt

Use this file to discover all available pages before exploring further.

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 same 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

  1. You configure rules for a session (PUT /api/sessions/{session}/client-rules) defining what actions are allowed, rate limits, and recipient restrictions.
  2. Your server mints a token for a specific user or browser session (POST /api/client-tokens), scoping it to a session and a developer-provided ephemeralId.
  3. Your client receives the token and uses it as a bearer token. The API enforces the rules on every request.
  4. 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 configured allowedActions:
ActionRoutes
send_messagePOST /{session}/messages/send
send_reactionPOST /{session}/messages/react
send_typingPOST /{session}/messages/typing
send_seenPOST /{session}/messages/seen
read_presenceGET /{session}/presence, GET /{session}/presence/{chatId}
subscribe_presencePOST /{session}/presence/{chatId}/subscribe
read_contactGET /{session}/contacts, GET /{session}/contacts/{id}, GET /{session}/contacts/{id}/picture, POST /{session}/contacts/check
All other routes — sessions, webhooks, groups, channels, labels, media, admin — are always denied to client tokens.

Recipient modes

The recipientMode rule controls who a client token can send messages to:
ModeBehavior
noneSending is disabled. Only read actions work.
conversationCan only reply to JIDs that have already messaged the session. Prevents initiating new conversations.
anyCan message any JID.
verifiedReserved for future use.

Mint a client token

curl -X POST https://api.example.com/api/client-tokens \
  -H "Authorization: Bearer titan_..." \
  -H "Content-Type: application/json" \
  -d '{
    "session": "default",
    "ephemeralId": "user-123-browser-1",
    "ttlSeconds": 900
  }'
POST /api/client-tokens Mints a new client token scoped to a session. Call this from your server — never from the client.
session
string
required
The WhatsApp session the token is scoped to. A token minted for session A cannot access session B.
ephemeralId
string
required
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.
ttlSeconds
integer
default:"900"
Token lifetime in seconds. Minimum 1. Maximum set by the CLIENT_TOKEN_MAX_TTL environment variable (default 900).
token
string
The client token string (titan_ct_...). Pass this to the client.
expiresAt
string
ISO 8601 timestamp when the token expires.
{
  "data": {
    "token": "titan_ct_eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
    "expiresAt": "2026-01-15T10:15:00Z"
  }
}

Get client rules

curl https://api.example.com/api/sessions/default/client-rules \
  -H "Authorization: Bearer titan_..."
GET /api/sessions/{session}/client-rules Returns the current client token rules for the session. Returns 404 if no rules are configured.
session
string
required
Session name.
{
  "data": {
    "recipientMode": "conversation",
    "allowedActions": "send_message,send_reaction,send_typing",
    "rateLimit": 5,
    "maxDaily": 100,
    "allowedOrigins": "https://myapp.com",
    "enabled": true
  }
}

Set client rules

curl -X PUT https://api.example.com/api/sessions/default/client-rules \
  -H "Authorization: Bearer titan_..." \
  -H "Content-Type: application/json" \
  -d '{
    "recipientMode": "conversation",
    "allowedActions": "send_message,send_reaction,send_typing",
    "rateLimit": 5,
    "maxDaily": 100,
    "allowedOrigins": "https://myapp.com,https://staging.myapp.com",
    "enabled": true
  }'
PUT /api/sessions/{session}/client-rules Creates or replaces client token rules for the session. Changes take effect immediately on the next request.
session
string
required
Session name.
recipientMode
string
required
Controls who client tokens can send messages to: none, conversation, any, or verified.
enabled
boolean
required
Whether client tokens are accepted for this session. Set to false to deny all client token requests immediately.
allowedActions
string
Comma-separated list of permitted actions. Example: "send_message,send_reaction,send_typing,send_seen". Omit to deny all actions.
rateLimit
integer
Maximum requests per minute per ephemeralId. Uses a sliding window. 0 means unlimited.
maxDaily
integer
Maximum send actions (messages and reactions) per day per ephemeralId. 0 means unlimited.
allowedOrigins
string
Comma-separated list of allowed CORS origins (e.g. "https://myapp.com,https://staging.myapp.com"). Leave empty to skip origin checking.
{
  "data": {
    "recipientMode": "conversation",
    "allowedActions": "send_message,send_reaction,send_typing",
    "rateLimit": 5,
    "maxDaily": 100,
    "allowedOrigins": "https://myapp.com,https://staging.myapp.com",
    "enabled": true
  }
}

Delete client rules

curl -X DELETE https://api.example.com/api/sessions/default/client-rules \
  -H "Authorization: Bearer titan_..."
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
string
required
Session name.
{
  "data": { "success": true, "message": "client rules deleted" }
}

SDK example

Here is a complete example using the TypeScript SDK to set up client tokens for a support widget:
import { TitanClient } from '@titan-api/sdk';

// Server-side: configure rules once
const server = new TitanClient({
  baseUrl: 'https://api.example.com',
  apiKey: 'titan_...',
});

await server.clientTokens.setRules('default', {
  recipientMode: 'conversation',  // Only reply to contacts who messaged first
  allowedActions: 'send_message,send_reaction,send_typing,send_seen',
  rateLimit: 5,    // Max 5 requests/minute per user
  maxDaily: 100,   // Max 100 messages/day per user
  allowedOrigins: 'https://myapp.com',
  enabled: true,
});

// Server-side: mint a token per browser session (e.g. in your API handler)
const { token, expiresAt } = await server.clientTokens.mint({
  session: 'default',
  ephemeralId: `user-${userId}-${tabId}`,
  ttl: 900,
});

// Return the token to the client
res.json({ token, expiresAt });
// Browser-side: use the client token
const browser = new TitanClient({
  baseUrl: 'https://api.example.com',
  clientToken: tokenFromServer,
});

await browser.messages.send('default', {
  chatId: '[email protected]',
  type: 'text',
  text: 'Hello!',
});

Error responses

StatusCondition
400Invalid body, missing required fields, TTL out of range, invalid recipientMode
401Invalid or expired token, bad signature, no rules configured for the session
403Denied route, session mismatch, action not in allowedActions, recipient not in conversation list, origin not allowed
429Per-minute rate limit or daily cap exceeded