Skip to content

Errors

Failures use one shape on every endpoint. Messages are written for people; branch on the code.

{
  "ok": false,
  "error": { "code": "not_found", "message": "Contact not found." },
  "timestamp": "2026-10-27T10:15:00.000Z"
}
StatusCodeMeaning
400invalid_requestA field is missing or malformed.
401unauthorizedMissing, revoked or malformed token.
402payment_requiredThe workspace trial or subscription has ended, so writes are refused until a plan is chosen. Reads keep working.
403forbiddenThe token has none of the scopes this endpoint accepts, or the workspace is suspended.
404not_foundNo such record in your workspace.
409conflictThe request clashes with current state, for example a duplicate contact or a closed 24-hour window.
413payload_too_largeThe body exceeds 64 KB.
422unprocessableUnderstood but refused, for example the contact opted out or has no phone number.
429rate_limitedToo many requests; wait for Retry-After seconds.
500internal_errorSomething failed on our side. Safe to retry reads.

Cases worth handling

  • 400 invalid_request when a list asks for more than 10,000 records through paging (page_number x page_size above 10,000). The message says so; narrow the query with filters instead. There are no cursors yet.
  • 422 unprocessable when a local_message_id you already used is sent again with a different body. Nothing is sent. Use a new id for a new message, or resend the original body to get the original result back.
  • 409 conflict when a send with the same local_message_id is still being recorded. Wait a few seconds and retry with the same id.
  • 401 unauthorized when the token was revoked, including automatically when its creator left the workspace or was disabled.
  • 403 forbidden with a message about suspension when the workspace is suspended; the token works again once it is reinstated.

Template sends to several recipients answer 200 even if some are refused; check each item's errors in the recipients array and the top-level success flag.