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 Admin API is available exclusively on self-hosted Titan instances. It gives you full control over API key lifecycle, instance-wide settings, and license inspection — all authenticated with your master key.
The master key has unrestricted admin access to your Titan instance. Store it in a secrets manager, never hard-code it in application code, and never expose it in client-side or browser environments.
Authentication
Every Admin API request must include the master key as a Bearer token:
Authorization: Bearer {MASTER_KEY}
The master key is the value you set in the MASTER_KEY environment variable when you deployed Titan. All examples below use $MASTER_KEY as a placeholder.
API key management
API keys (titan_ prefix) are what your applications use to authenticate against the Titan REST API. You create and manage them here.
List all keys
curl --request GET \
--url http://localhost:8080/admin/keys \
--header "Authorization: Bearer $MASTER_KEY"
{
"data": [
{
"id": "key_01jz4xkq0000000000000000",
"label": "production-backend",
"scopes": ["messages:write", "sessions:manage"],
"isActive": true,
"createdAt": "2025-05-01T10:00:00Z",
"expiresAt": "2025-07-30T10:00:00Z"
}
]
}
Create a key
curl --request POST \
--url http://localhost:8080/admin/keys \
--header "Authorization: Bearer $MASTER_KEY" \
--header "Content-Type: application/json" \
--data '{
"label": "production-backend",
"lifetimeDays": 90,
"scopes": ["messages:write", "sessions:manage", "webhooks:manage"]
}'
{
"data": {
"id": "key_01jz4xkq0000000000000000",
"key": "titan_AAAB...",
"label": "production-backend",
"scopes": ["messages:write", "sessions:manage", "webhooks:manage"],
"isActive": true,
"createdAt": "2025-05-01T10:00:00Z",
"expiresAt": "2025-07-29T10:00:00Z"
}
}
The key field is returned only on creation. Store it immediately — it cannot be retrieved again.
The scopes array controls what the key can do. Available scopes:
| Scope | Access |
|---|
* | All permissions |
sessions:read | Read session status and info |
sessions:manage | Create, start, stop, and delete sessions |
messages:write | Send messages |
chats:read | Read chat history and metadata |
chats:manage | Archive, delete, and manage chats |
contacts:read | Read contact list and info |
contacts:manage | Block, unblock, and manage contacts |
groups:read | Read group info |
groups:manage | Create, update, and manage groups |
webhooks:manage | Create, update, and delete webhooks |
media:read | Download media |
media:manage | Persist and manage media |
Get a key
curl --request GET \
--url http://localhost:8080/admin/keys/key_01jz4xkq0000000000000000 \
--header "Authorization: Bearer $MASTER_KEY"
{
"data": {
"id": "key_01jz4xkq0000000000000000",
"label": "production-backend",
"scopes": ["messages:write", "sessions:manage"],
"isActive": true,
"createdAt": "2025-05-01T10:00:00Z",
"expiresAt": "2025-07-30T10:00:00Z"
}
}
Update a key
You can rename a key or enable/disable it without rotating the key material:
curl --request PUT \
--url http://localhost:8080/admin/keys/key_01jz4xkq0000000000000000 \
--header "Authorization: Bearer $MASTER_KEY" \
--header "Content-Type: application/json" \
--data '{
"label": "production-backend-v2",
"isActive": true
}'
{
"data": {
"id": "key_01jz4xkq0000000000000000",
"label": "production-backend-v2",
"scopes": ["messages:write", "sessions:manage"],
"isActive": true,
"createdAt": "2025-05-01T10:00:00Z",
"expiresAt": "2025-07-30T10:00:00Z"
}
}
Rotate a key
Rotating a key immediately revokes the old key and issues a new one. The revocation takes effect immediately across all running API instances.
curl --request POST \
--url http://localhost:8080/admin/keys/key_01jz4xkq0000000000000000/rotate \
--header "Authorization: Bearer $MASTER_KEY"
{
"data": {
"id": "key_01jz9ynr0000000000000000",
"key": "titan_BBBC...",
"label": "production-backend-v2",
"scopes": ["messages:write", "sessions:manage"],
"isActive": true,
"createdAt": "2025-05-15T09:00:00Z",
"expiresAt": "2025-08-13T09:00:00Z"
}
}
The old key is revoked immediately. Update any application that uses the old key before calling rotate, or update it immediately after and deploy quickly.
Delete a key
curl --request DELETE \
--url http://localhost:8080/admin/keys/key_01jz4xkq0000000000000000 \
--header "Authorization: Bearer $MASTER_KEY"
Returns 204 No Content on success. Deletion is immediate and permanent.
Instance settings
Get current settings
curl --request GET \
--url http://localhost:8080/admin/settings \
--header "Authorization: Bearer $MASTER_KEY"
{
"data": {
"rateLimit": 100,
"msgRateLimit": 50,
"debugMode": false,
"logLevel": "info"
}
}
Update settings
curl --request PUT \
--url http://localhost:8080/admin/settings \
--header "Authorization: Bearer $MASTER_KEY" \
--header "Content-Type: application/json" \
--data '{
"rateLimit": 200,
"msgRateLimit": 100,
"debugMode": false,
"logLevel": "warn"
}'
{
"data": {
"rateLimit": 200,
"msgRateLimit": 100,
"debugMode": false,
"logLevel": "warn"
}
}
Settings fields:
| Field | Type | Description |
|---|
rateLimit | integer | Maximum API requests per minute across all keys |
msgRateLimit | integer | Maximum message-send requests per minute |
debugMode | boolean | Enable verbose debug logging |
logLevel | string | Log verbosity: debug, info, warn, error |
License info
Inspect the claims embedded in your license file:
curl --request GET \
--url http://localhost:8080/admin/license \
--header "Authorization: Bearer $MASTER_KEY"
{
"data": {
"sessionLimit": 100,
"platform": "kubernetes",
"issuedAt": "2025-01-01T00:00:00Z",
"expiresAt": "2026-01-01T00:00:00Z",
"gracePeriodDays": 14,
"awsAccountId": null,
"isExpired": false,
"isInGracePeriod": false
}
}
| Field | Description |
|---|
sessionLimit | Maximum concurrent WhatsApp sessions allowed by this license |
platform | Platform restriction: aws, gcp, azure, docker, kubernetes, or any |
issuedAt | Date the license was issued |
expiresAt | License expiry date — renew before this date |
gracePeriodDays | Days the instance continues to operate after expiry |
awsAccountId | AWS account ID the license is bound to, or null if unrestricted |
isExpired | true if the license has passed its expiry date |
isInGracePeriod | true if the instance is running on the post-expiry grace period |
Debug mode
Toggle debug logging without updating instance settings:
curl --request POST \
--url http://localhost:8080/admin/debug \
--header "Authorization: Bearer $MASTER_KEY" \
--header "Content-Type: application/json" \
--data '{"enabled": true}'
{
"data": {
"debugMode": true
}
}
Enable debug mode temporarily when diagnosing a specific issue, then disable it once you have captured the logs you need. Debug mode produces significantly more log output and can affect performance under load.