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.

The Titan API is a RESTful HTTP API that lets you connect WhatsApp accounts, send and receive messages, manage groups and contacts, and receive real-time events via webhooks. Every request uses JSON, and every response wraps its data in a consistent envelope so you can handle success and errors the same way throughout your application.

Base URL

If you are on Titan Cloud, your base URL is provided in your dashboard. If you are self-hosting, use your own instance URL:
https://api.example.com
An interactive API explorer (Scalar) is available at your base URL + /docs.

Authentication

All API requests require a bearer token in the Authorization header:
Authorization: Bearer titan_...
You create API keys from your account dashboard or via the admin API (self-hosted). Each key carries a set of permission scopes that restrict which endpoints it can call. The key is shown only once at creation — store it securely.
Never expose your server API key in client-side code or public repositories. Use client tokens for browser-based integrations.

Request format

Send all request bodies as JSON with the Content-Type: application/json header:
curl -X POST https://api.example.com/api/sessions \
  -H "Authorization: Bearer titan_..." \
  -H "Content-Type: application/json" \
  -d '{"name": "default", "start": true}'

Response format

Successful responses wrap the result in a data envelope:
{
  "data": {
    "name": "default",
    "status": "CONNECTING"
  }
}
List endpoints return an array inside data:
{
  "data": [
    { "name": "default", "status": "CONNECTED" },
    { "name": "support", "status": "DISCONNECTED" }
  ]
}

Error format

Errors return an error string and, where applicable, a docs link to the relevant documentation:
{
  "error": "missing required field: chatId",
  "docs": "https://docs.titan.whiskey.so/api/messages/send"
}

HTTP status codes

CodeMeaning
200Success
201Created
202Accepted (async mode — see below)
400Bad request — invalid input
401Unauthorized — missing or invalid API key
403Forbidden — insufficient scope
404Not found
409Conflict — resource already exists
429Too many requests — rate limit exceeded
500Internal server error
502Bad gateway — runner or media worker unreachable
503Service unavailable — rate limiter overload or dependency failure

Rate limiting

Titan uses a sliding-window rate limiter scoped to your API key. Every response includes these headers:
HeaderDescription
X-RateLimit-LimitMaximum requests allowed in the window
X-RateLimit-RemainingRequests remaining in the current window
Retry-AfterSeconds to wait before retrying (present on 429)
When you receive a 429, wait the number of seconds in Retry-After before retrying.

Async mode

Any endpoint that forwards a command to the WhatsApp runner supports async mode. Add the Prefer: respond-async header to get an immediate 202 Accepted instead of waiting for the result:
curl -X POST https://api.example.com/api/messages/send \
  -H "Authorization: Bearer titan_..." \
  -H "Content-Type: application/json" \
  -H "Prefer: respond-async" \
  -d '{"session": "default", "chatId": "[email protected]", "type": "text", "text": "Hello"}'
The 202 response includes a requestId. When the operation completes, Titan fires a command.result webhook event with that same requestId and the result payload. This is useful for high-throughput workloads where you do not want to block on each request.

JID reference format

WhatsApp uses JIDs (Jabber IDs) to address chats and participants. The API exposes JIDs through a JIDRef object that normalizes both phone-number and linked-device-ID addressing: Individual contact:
{
  "phoneNumber": "+5511999999999",
  "lid": "12345678901234567890@lid",
  "mode": "pn"
}
Group:
{
  "id": "[email protected]"
}
When sending messages, the chatId field expects a JID string directly:
  • Individual: {e164_number_without_plus}@s.whatsapp.net — for example, [email protected]
  • Group: {group_id}@g.us — for example, [email protected]
  • Status broadcast: status@broadcast

Pagination

Endpoints that return lists include a cursor field in the response when more results are available. Pass the cursor value as a cursor query parameter to fetch the next page.

Permission scopes

Every API key is issued with one or more scopes that restrict its access. The available scopes are: * sessions:read sessions:manage messages:write chats:read chats:manage contacts:read contacts:manage groups:read groups:manage channels:read channels:manage status:write presence:read presence:write labels:read labels:manage profile:read profile:write webhooks:manage media:read media:manage If your key lacks the required scope for an endpoint, the API returns 403 Forbidden with a message indicating which scope is needed.