Errors
The error response shape, HTTP statuses and the stable error codes returned by the public API.
Updated 24 Oct 2026 5 min read
Error shape
A failed request returns a non-2xx status and the standard envelope:
{
"requestId": "0b1c6f2e-6a1d-4c58-9f47-2b7d6d1f8a10",
"message": "This key lacks the required scope.",
"code": "INSUFFICIENT_SCOPE"
}
- Branch on
code. Codes are stable and are never renamed. message can be reworded at any time.
- For validation failures,
message can be a list of problems.
- Some errors add details in
data, for example data.missing on TRANSACTIONAL_VARIABLES_MISSING.
- Quote
requestId when you contact support.
The /sdk/* endpoints return the same code values but do not use the envelope. See SDK ingest.
HTTP statuses
| Status |
Meaning |
Retry? |
| 400, 422 |
The request is invalid. |
No. Fix the request. |
| 401 |
Missing or wrong credentials. |
No. Fix the credentials. |
| 403 |
The key is valid but not allowed to do this. |
No. |
| 404 |
The thing you named does not exist in this environment. |
No. |
| 409 |
A conflict with the current state, or a throttle. |
Only after the state changes or the window passes. |
| 413 |
The payload is too large. |
Split it, then retry. |
| 429 |
Rate limited. |
Yes, after Retry-After seconds. |
| 5xx |
A problem on our side. |
Yes, with exponential backoff. Keep the same messageId or idempotencyKey. |
The status for a given code can vary by endpoint, so the table below lists the usual one.
Authentication and keys
| Code |
Usual status |
Meaning |
API_KEY_REQUIRED |
401 |
The endpoint needs an API key and none was sent. |
INVALID_API_KEY |
401 |
The key or secret is wrong. |
API_KEY_SECRET_REQUIRED |
401 |
The key needs a secret. |
API_KEY_REVOKED |
401 |
The key was revoked. |
API_KEY_EXPIRED |
401 |
The key has expired. |
KEY_KIND_NOT_ALLOWED |
403 |
This kind of key cannot call this endpoint. |
INSUFFICIENT_SCOPE |
403 |
The key lacks the scope the endpoint needs. |
IP_NOT_ALLOWED |
403 |
The key may not be used from this address. |
ORIGIN_NOT_ALLOWED |
403 |
The key may not be used from this origin. |
FORBIDDEN |
403 |
You do not have permission to do this. |
Validation
| Code |
Usual status |
Meaning |
VALIDATION_ERROR |
422 |
The request failed validation. |
VALIDATION_FAILED |
400 |
The request body failed validation. |
BAD_REQUEST |
400 |
The request could not be understood. |
Events and SDK ingest
These codes can appear per item in errors[].
| Code |
Meaning |
BATCH_TOO_LARGE |
Split the batch in half and retry both halves. |
EVENT_TOO_LARGE |
The event payload exceeds the maximum size (32 KB). |
EVENT_NAME_REQUIRED |
An event must carry a name. |
IDENTIFIER_REQUIRED |
Give one of externalId, email or phone. |
EVENT_RESERVED |
That event name is reserved and cannot be sent by your app or server. |
EVENT_BLOCKED |
The event is blocked for this workspace. |
ATTRIBUTE_RESERVED |
The attribute is reserved. Use the typed setter, such as setEmail. |
DEVICE_PAYLOAD_EMPTY |
A device item must carry a push token or a notifications flag. |
Transactional, flows and identity
| Code |
Usual status |
Meaning |
TRANSACTIONAL_ENDPOINT_NOT_FOUND |
404 |
No transactional endpoint with that slug. |
TRANSACTIONAL_VARIABLES_MISSING |
422 |
A required variable is missing. |
USER_NOT_FOUND |
404 |
No profile matches that user. |
IDENTITY_PROMOTION_BUSY |
409 |
Another promotion of this identity is running. Retry shortly. |
FLOW_NOT_FOUND |
404 |
The flow does not exist. |
FLOW_STATE_INVALID |
409 |
The action is not allowed in the flow's current state, for example it is not running. |
FLOW_ENTRY_INVALID |
422 |
The flow does not use API entry. |
BUSINESS_EVENT_NOT_FOUND |
404 |
The business event does not exist. |
BUSINESS_EVENT_THROTTLED |
429 |
Activation limit reached (5 per hour, 20 per day). |
Privacy and erasure
| Code |
Usual status |
Meaning |
USER_ERASED |
410 |
The person was erased. |
ERASURE_CONFIRMATION_REQUIRED |
400 |
Send confirm: true. |
ERASURE_REASON_REQUIRED |
400 |
Give a reason of 5 to 500 characters. |
ERASURE_RATE_LIMITED |
429 |
Too many erasures this hour. Nothing was erased. |
PRIVACY_REQUEST_NOT_FOUND |
404 |
No erasure request with that id. |
PRIVACY_SUBJECT_INVALID, PRIVACY_SUBJECT_AMBIGUOUS |
422 |
The subject is invalid, or matches too many profiles. |
IDEMPOTENCY_KEY_REUSED |
422 |
The key was used for a different person. |
PRIVACY_NOT_CONFIGURED |
503 |
Erasure is not set up on this server. |
See Erasure API.
Rate limits and idempotency
| Code |
Usual status |
Meaning |
RATE_LIMITED |
429 |
Too many requests. Wait for Retry-After seconds. |
REQUEST_IN_PROGRESS |
409 |
A request with this idempotency key is still running. |
PAYLOAD_TOO_LARGE |
413 |
The request payload is too large. |
General
| Code |
Usual status |
Meaning |
NOT_FOUND |
404 |
Not found. |
CONFLICT |
409 |
The request conflicts with the current state. |
ALREADY_EXISTS |
409 |
A record with these values already exists. |
RELATED_RECORD_MISSING |
409 or 422 |
A referenced record does not exist. |
DATABASE_UNAVAILABLE |
503 |
A dependency is unreachable. Retry with backoff. |
DATABASE_ERROR, UNHANDLED_ERROR |
500 |
An unexpected error. Retry with backoff, and contact support with the requestId if it persists. |
Handling errors well
- Retry only 429 and 5xx, with backoff. Retrying a 4xx never succeeds.
- Send idempotency keys so retries cannot duplicate work. See the API overview.
- Log
requestId and code on every failure.
Was this page helpful?