Skip to main content

Rate limiting

Each API key is subject to a limit of 100 requests per minute. The limit is counted using a 60-second sliding window, per key.

Control headers

Every response includes headers that report the current state of your limit:
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 87
X-RateLimit-Reset: 1745078400
HeaderDescription
X-RateLimit-LimitTotal limit for the current window
X-RateLimit-RemainingRequests remaining in the window
X-RateLimit-ResetUnix timestamp when the counter resets

When the limit is reached

The API returns 429 Too Many Requests with a Retry-After header indicating how many seconds to wait:
HTTP/1.1 429 Too Many Requests
Retry-After: 12
Content-Type: application/json

{
  "error": {
    "code": "RATE_LIMIT_EXCEEDED",
    "message": "Limit of 100 requests per minute reached. Wait 12 seconds.",
    "status": 429
  }
}

Implementing retry with backoff

async function requestWithRetry(url, options, maxAttempts = 3) {
  for (let attempt = 1; attempt <= maxAttempts; attempt++) {
    const res = await fetch(url, options);

    if (res.status !== 429) return res;

    const retryAfter = parseInt(res.headers.get("Retry-After") ?? "5", 10);
    console.log(`Rate limited. Waiting ${retryAfter}s (attempt ${attempt}/${maxAttempts})`);
    await new Promise(r => setTimeout(r, retryAfter * 1000));
  }
  throw new Error("Maximum number of attempts reached");
}
If you operate at high volumes and hit the limit frequently, consider distributing the load across multiple workspaces or contact us at contato@timelyai.com.br to discuss custom limits on an Enterprise plan.

Pagination

All listing routes support pagination via query params:
GET /v1/conversations?page=3&per_page=50
ParameterDefaultMaximumDescription
page1Page number
per_page20100Items per page
The response includes a meta envelope with the total record count:
{
  "data": [ ... ],
  "meta": {
    "page": 3,
    "per_page": 50,
    "total": 347,
    "total_pages": 7
  }
}
Use total_pages to know when to stop paginating. When page > total_pages, the data field returns an empty array.

Error codes

The API uses semantic HTTP statuses. All errors follow the same envelope format:
{
  "error": {
    "code": "ERROR_CODE",
    "message": "Human-readable description of the problem.",
    "status": 400
  }
}

Error table

StatusWhen it occursWhat to do
400 Bad RequestInvalid payload, missing required field, incorrect formatRead error.message — it specifies the problematic field
401 Unauthorizedx-api-key header missing, key invalid, or revokedCheck the key under Settings → API Keys
403 ForbiddenValid key, but missing the required scope for the operationAdd the missing scope to the key or create a new one
404 Not FoundResource does not exist or does not belong to your workspaceVerify the ID and the active workspace
409 ConflictResource already exists (e.g., channel with the same name, duplicate webhook)Adjust the payload or update the existing resource
429 Too Many RequestsLimit of 100 req/min reachedUse the Retry-After header to wait
500 Internal Server ErrorUnexpected error on the Timely.ai serverTry again. If it persists, open a ticket at contato@timelyai.com.br

Internal error codes (error.code)

In addition to the HTTP status, the code field identifies the exact cause:
CodeDescription
MISSING_API_KEYx-api-key header was not sent
INVALID_API_KEYKey does not exist or has been revoked
INSUFFICIENT_SCOPERequired scope is not on the key
WORKSPACE_ACCESS_DENIEDKey does not have access to the specified workspace
CodeDescription
AGENT_NOT_FOUNDAgent does not exist in this workspace
CONVERSATION_NOT_FOUNDConversation not found
CONTACT_NOT_FOUNDContact not found
CHANNEL_NOT_FOUNDChannel does not exist or is not active
WEBHOOK_NOT_FOUNDWebhook endpoint not found
CodeDescription
VALIDATION_ERROROne or more fields have an invalid format
MISSING_REQUIRED_FIELDRequired field missing from the payload
INVALID_PHONE_FORMATPhone number not in E.164 format
PAYLOAD_TOO_LARGERequest body exceeds the 5 MB limit
CodeDescription
RATE_LIMIT_EXCEEDED100 req/min reached
DUPLICATE_WEBHOOK_URLWebhook URL already registered in this workspace
CHANNEL_ALREADY_CONNECTEDChannel already connected to another agent
PLAN_LIMIT_REACHEDAgent or channel limit for the plan reached

Next steps

Production checklist

Review everything before going live with real customers.

Webhooks

Receive real-time events without polling.