Error codes
Every 4xx / 5xx response from the ingest and Partner API endpoints shares the same envelope. Branch on the HTTP status and the keys of the errors object; show the messages to humans.
01Error envelope
Consistent shape across all endpoints.
{
"errors": {
"deviceId": ["Invalid format: \"abc\" is not a valid UUID"]
}
}Each key is the field that failed, such as deviceId, or _general when the request as a whole is wrong - a bad token, a malformed body, an unknown project. On /sdk/ingest with the sdk source, a missing sessionId, or a sessionId or replayId that is not a UUID, is also reported under _general. Each key holds a list of messages. Problems with single events in a /sdk/ingest batch don't fail the request: it answers 200 and lists them in skipped and warnings - see Server-side ingest.
02Error catalog
Messages the ingest and Partner API endpoints return, by HTTP status.
| Status | Message | When |
|---|---|---|
| 400 | Invalid JSON body | The body of a POST /sdk/* request is not valid JSON. |
| 400 | projectId required | The body has no projectId, or it is not a string. |
| 400 | Invalid project | No project has this projectId. |
| 400 | deviceId is required | The body has no deviceId. A deviceId that is not a UUID returns Invalid format: "…" is not a valid UUID under the same key. |
| 400 | deviceId and sessionId are required for SDK source | POST /sdk/ingest with source omitted or sdk and no sessionId. Server-side senders set their own source, e.g. backend. |
| 400 | All IDs must be valid UUIDs | POST /sdk/ingest with the sdk source and a sessionId or replayId that is not a UUID. With any other source the message is sessionId must be a valid UUID if provided (or replayId …). |
| 400 | Session <id> already exists | POST /sdk/sessions/import with a sessionId that is already stored. |
| 401 | Valid API token required. Use Authorization: Bearer sumi_xxx | Partner API: the Authorization header is missing or does not start with Bearer sumi_. |
| 401 | Invalid or revoked API token | Partner API: the token is unknown or has been revoked. Create a new one. |
| 409 | Session <id> belongs to another project | POST /sdk/sessions with a sessionId that another project already uses. |
| 500 | Internal Server Error | Something failed on our side. Also returned today when projectId is not a UUID or a /sdk/ingest body is larger than 64 MB - fix the request instead of retrying it. |
03Retry strategy
How to recover - by status class.
- 4xx - do not retry. Fix the request.
- 200 with
"status": "quota_exceeded"- the workspace has used its monthly session quota and nothing was stored. Retrying won't help until next month or a plan upgrade. - 5xx - retry with backoff (start 1s, double up to 60s). If it persists past 5 minutes, contact Support.
04Error Impact report
Which captured errors block purchases - ranked in the dashboard.
Browser errors captured by the SDK feed the Error Impact report. It splits the sessions where each error group appeared into bought vs. didn't buy, compares each group's conversion against your site baseline, and ranks groups by the estimated purchases lost - so the most revenue-damaging bugs surface first. Groups seen in fewer than 20 sessions are held below a reliability threshold rather than ranked, and the errors-vs-sales correlation shown on the chart is a prioritization indicator, not proof of cause. Matching purchases to sessions requires the session link on conversion events: Sumidata.purchase() attaches it in the browser, and orders your server sends must pass sessionId themselves - see Conversions.
