developers
ES Sign up

Guides

Errors and limits

Every error has the same shape, limits are predictable, and writes can be retried without duplicating anything.

Error format#

Every 4xx or 5xx response carries an error object with a stable code (for your code) and a readable message (for your logs). Some errors add details:

400 Bad Request
{
  "error": {
    "code": "validation_error",
    "message": "Request validation failed",
    "details": {
      "formErrors": [],
      "fieldErrors": { "channel": ["Invalid enum value"] }
    }
  }
}

Status codes#

StatusWhenWhat to do
400Invalid JSON (invalid_json) or failed validation (validation_error, with per-field details).Fix the request. Do not retry it as is.
401The API key is missing, invalid or revoked (unauthorized).Check the header and the key.
401The key expired (api_key_expired, with details.expired_at). A key can have an expiration date; 7 days before, we email the owners and admins.Create a new key or rotate this one before the date.
402A plan limit was reached (plan_limit_exceeded).See details.upgrade_url>.
402The period's messages ran out on Developer Free (message_quota_exceeded). Incoming messages are still stored.Read fix: wait for the next period or upgrade to Developer. See Pricing
403Missing scope, IP not allowed or workspace disabled.Add the scope to the key or check its IPs.
404The resource does not exist in this workspace.Check the id.
409Conflict, such as an Idempotency-Key still in progress.Retry in a few seconds.
422The request is valid but cannot be processed (for example no_channel_connection, or invalid_sms_message and sms_sender_mismatch when sending an SMS).Read message: something usually needs to be set up in the workspace.
429You went over the rate limit (rate_limited).Wait and retry with backoff.
5xxheysteff error.Retry with backoff and the same Idempotency-Key.

Rate limit#

Each API key has a request cap per 60-second window that depends on the workspace plan:

PlanRequests per minute, per key
Developer Free100
Developer2,000
Developer Platform4,000

Every response carries the limit state in three headers:

Past the cap, the API answers 429 rate_limited with Retry-After (seconds) until the next window starts. Retry after that time, with exponential backoff and some jitter (for example 1, 2, 4 and 8 seconds).

Workspace plan limits, such as messages per month, are separate. They answer 402 plan_limit_exceeded and retrying does not help.

Idempotency#

Operations that create something accept the Idempotency-Key header. If you repeat a request with the same key, you get exactly the same response as the first time (same status, same body) and nothing new is created.

EndpointKey
POST /v1/messages, POST /v1/campaigns, POST /v1/automation-flows/{id}/triggerIdempotency-Key header, optional.
POST /v1/charges, POST /v1/refundsIdempotency-Key header, required.
POST /v1/eventsidempotency_key body field.
POST /v1/conversionsexternal_ref body field.

Pagination#

List endpoints return pages. limit goes from 1 to 200 (50 by default).

EndpointHow to move forward
GET /v1/conversations, GET /v1/conversations/{id}/messages, GET /v1/contactsPass cursor=<cursor.next> while cursor.has_more is true.
GET /v1/eventsPass after_seq=<cursor.next_after_seq>.
GET /v1/reviewsUse limit and offset.

Amounts and dates#