Error Format
Every error response replaces the success envelope’s data field with a structured error object, designed to be actionable by both humans and automated/agent clients — not just an HTTP status code:
{ "success": false, "error": { "code": "survey_not_found", "message": "No survey with id mlb8i9f2UZLhXwJA.", "suggestion": "Call listSurveys to discover valid ids.", "retryable": false, "details": { "survey_id": "mlb8i9f2UZLhXwJA" } }, "meta": { "timestamp": "2026-07-23T12:00:00Z", "requestId": "..." }}| Field | Meaning |
|---|---|
code |
A stable, snake_case domain code. Branch your error handling on this, not on the HTTP status or the human-readable message. |
message |
Human-readable description. Safe to log or display, not guaranteed to stay word-for-word identical across API versions. |
suggestion |
An imperative hint at how to recover — often naming the exact endpoint to call next. |
retryable |
Whether re-sending the same request might succeed without any change on your end (a transient condition), as opposed to a client error that will keep failing until you change the request. |
details |
Structured, code-specific context (e.g. the offending field, or the resource ID that wasn’t found). |
Common codes
Section titled “Common codes”| Code | HTTP status | Retryable |
|---|---|---|
validation_failed |
400 | No |
insufficient_scope |
403 | No |
survey_not_found |
404 | No |
survey_not_published |
409 | No |
confirmation_required |
409 | No |
dependency_not_ready |
409 | Yes — poll and retry, typically for async operations like exports |
rate_limited |
429 | Yes — back off and retry (see Rate Limits) |
This isn’t the full list — new domain codes are added as the API surface grows. Always check retryable rather than assuming based on the code name alone.
Idempotency and retries
Section titled “Idempotency and retries”For any non-GET request that includes an Idempotency-Key header, retrying the exact same request (same key, same body) is always safe — the API returns the original result rather than re-applying the write. Without that header, only retry requests where error.retryable is true.
The confirmation gate
Section titled “The confirmation gate”A small number of high-stakes, hard-to-reverse actions (for example, anonymizing a contact, or exporting a dataset containing full PII) require an extra confirmation step rather than executing immediately:
- Call the action normally. Instead of executing, the API responds with
409 confirmation_requiredand a one-timeconfirmation_tokeninerror.details, describing the action’s impact. - Re-send the identical request with an
X-Confirmation-Tokenheader carrying that token. The action now executes.
The token is single-use, expires after a few minutes, and is bound to the exact request payload — it can’t be reused for a different action or a modified body.