Developer API errors and request limits

Last updated: 11 November 2026 · 6 min read

The API returns 2xx on success and 4xx or 5xx on errors. Every response has an X-Request-Id header: when you write to support ([email protected]), send this value, and we find the request in the log quickly.

Steps

  1. 1

    Error shape

    Token, scope, limit and path errors share one shape:

    {
      "error": {
        "code": "insufficient_scope",
        "message": "This action needs the messages:send permission.",
        "required_scopes": ["messages:send"],
        "request_id": "3f9c2a1e-8b7d-4c6a-9e15-2d4b7a0c9f31"
      }
    }

    code is stable: check it in your code. message is for people and can change. It comes in English with Accept-Language: en. A 403 response also carries a WWW-Authenticate header. An endpoint's own checks (a required field, a wrong value) still use the older shape, usually with 422: { "error": "..." } or { "message": "...", "attributes": [...] }. /oauth/* errors follow the OAuth shape: { "error": "invalid_client" }.

  2. 2

    Token and permission errors

    • 401 invalid_token: the token is missing, unknown or revoked. Check the header: Authorization: Bearer clomni_pat_xxx.
    • 401 token_expired: the token has expired. A personal access token works for 30-365 days, an app token for 1 hour.
    • 403 insufficient_scope: the token does not have the scope. Read required_scopes, add the scope to the app and send it for review, and after approval create a new token and choose that scope.
    • 403 endpoint_not_available: this endpoint is not open to developer tokens and is not in the API reference.
    • 403 app_not_approved: the app has no approved scope left.
    • 403 app_suspended: Clomni suspended the app, or the app is archived. Read the reason in the email.
    • 403 app_owner_not_admin: the app owner is no longer an administrator in the workspace. It works again once the role is given back.
    • 403 installation_owner_not_admin: the person who connected the public app is no longer an administrator, and the app has to be connected again.
    • 403 account_suspended: the workspace is suspended, and only workspace:read works.
  3. 3

    Other errors

    • 400 invalid_request: the path or a parameter is wrong (for example limit is outside 1-100).
    • 402 ai_credit_spent: the workspace's AI credit has run out (POST /ai_agents/{ai_agent_id}/ask). Do not retry automatically.
    • 404 not_found: the object does not exist or belongs to another workspace. 404 test_channel_missing: no test channel has been created.
    • 403 test_channel_webhook: a test channel cannot have a webhook address. 403 sandbox_restricted: sending outside is blocked in an old sandbox.
    • 409 conflict: a second export at the same time. 409 idempotency_key_reused: the same Idempotency-Key came with a different body. 409 idempotency_key_in_progress: a request with the same key is still running.
    • 422: the endpoint's own check, for example a second contact with the same email. Fix the body.
    • 500 internal_error: an error on our side. Try again a little later. If it repeats, write to us with the request_id.

    Sending a message is asynchronous: when the 24-hour window on WhatsApp is closed or the channel is not connected, the request is accepted and then the message becomes failed. The reason is in the message's content_attributes.external_error field. When WhatsApp QR returns the new chat restriction (463), do not send again: each attempt makes the restriction longer.

  4. 4

    When you can retry

    • 400, 401, 403, 404, 422: do not retry, fix the cause first.
    • 429: wait as many seconds as the Retry-After header says.
    • 500, 502, 503, 504 and network errors: with growing pauses (1, 2, 4, 8 seconds plus a random extra), at most 5 times.

    When you retry a POST, send an Idempotency-Key so that the message does not go twice.

  5. 5

    Request limits

    • General: 300 requests a minute per token.
    • All tokens of an app together: 600 requests a minute. Creating more tokens does not raise the limit.
    • GET /sync/*: 60 a minute per token.
    • POST /conversations/{conversation_id}/messages: 60 a minute per token.
    • POST /oauth/token: 20 a minute per client_id and IP.
    • POST /exports: 1 job at a time per workspace, 6 a day.

    Every /v1 response except /v1/me and /v1/oauth/* carries the RateLimit-Limit, RateLimit-Remaining and RateLimit-Reset (seconds) headers. Slow down when RateLimit-Remaining gets close to zero.

  6. 6

    When you get 429

    When a limit is exceeded, the response is 429 rate_limited with a Retry-After header. Do not send requests with the same token until that time has passed. If the header is missing, wait with growing pauses. Do not fetch the list again every minute: get changes through webhooks and catch what you missed with updated_since. Refresh an app token when it expires, not before every request. If you need a higher limit, write to [email protected] with the app, the endpoint, the expected volume and the reason.

    The API limit does not lift a channel's own limit: a WhatsApp Business API number has a daily limit and a quality rating set by Meta, and a WhatsApp QR number can be blocked for too many or unwanted messages.

Document