Platform API · Ingest API
Ingest API errors
The Ingest API uses standard HTTP status codes plus a partial-success body for batched writes. This page explains each code and how to retry safely.
Every response carries a meaningful HTTP status code. A 2xx means the batch was accepted for processing; anything else signals a problem your client should handle explicitly. Error bodies, when present, are JSON.
Success shape
Batched writes (POST /stream/contacts, POST /stream/events) return 202 Accepted when at least one item is accepted. 202 means queued, not yet stored: accepted items are stored shortly after the response, usually within a few seconds. Items that fail validation are reported in the same body, so partial failures do not block the rest of the batch:
{
"success": true,
"status": 202,
"errors": [
{
"position": 1,
"error": "_user_id not found at item #1 (ORDER-988): USER-456 Contact with that id must be created prior sending any events",
"item": { "_user_id": "USER-456", "_event_id": "ORDER-988", "_event_type": "purchase" }
}
],
"accepted": [
{
"position": 0,
"item": { "_user_id": "USER-123", "_event_id": "ORDER-987", "_event_type": "purchase" }
}
],
"entitiesSuccess": 1,
"entitiesFailures": 1
}Each entry in errors[] gives the item's position in the array you sent, the error message and the item itself; accepted[] lists the items that were queued. entitiesSuccess and entitiesFailures count both. The body also carries the project, datasource and stream identifiers and usage counters (items above are trimmed; full schema in the API Reference).
Inspect errors[] before assuming the whole batch landed. Failed items are safe to retry once fixed.
Status codes
202 Accepted
At least one item was accepted and queued; it is stored shortly after, usually within a few seconds. A write that depends on it and is sent immediately afterwards, such as an event for a contact you just sent, may not find it yet. Check the body's errors[] for items that were rejected.
400 Bad Request
Every item in the request was rejected, so nothing was queued. The body carries the first item's message in error:
{
"success": false,
"status": 400,
"error": "_user_id not found at item #0 (ORDER-987): USER-123 Contact with that id must be created prior sending any events",
"entitiesSuccess": 0,
"entitiesFailures": 1
}Most messages mean an item is wrong (a missing or invalid field, an unsupported event type or parameter): fix the items and resend. Two messages call for a specific response:
Contact with that id must be created prior sending any events— the event refers to a_user_idthat is not stored yet: the contact does not exist, or it was sent toPOST /stream/contactsmoments ago and is still being processed. Send the event with the contact embedded in_user_data, or retry it after a short wait (for example 1, 2 and 4 seconds). See Sending a new contact and its event together._event_id already exists— an event with this_event_idand_event_typeis already stored. It was not duplicated; treat it as delivered.
In a batch where other items were accepted, the same messages appear in errors[] of a 202 instead.
401 Unauthorized
The token is missing, revoked or malformed. Not retryable with the same token — check the Authentication guide.
404 Not Found
The project or datasource in the URL does not exist, or the token is not authorized to write to it.
422 Unprocessable Entity
The request as a whole cannot be processed: the body is empty or holds more than 100 items. Nothing was queued, and the reason is in error. Not retryable as-is — fix the payload first.
429 Too Many Requests
You hit the rate-limit window. Retry after X-RateLimit-Reset. See Rate limits.
500 Internal Server Error
Something broke on our side. Retry with exponential backoff; if the failure persists, contact support with the request id.
Retry policy
What's next
- Rate limits — how the
X-RateLimit-*headers work. - API Reference — per-endpoint responses and schemas.