Error Envelope
Every error response uses the same three-key envelope as success responses, withresponseType: "error" and data: null. The HTTP status code carries the error type; the message is a short human-readable description (safe to log, not stable enough to branch on).
422 Unprocessable Entity errors (request validation failures) flatten Pydantic field errors into a single message string of the form field.path: error description; field.path: error description. The HTTP status remains 422.
Status Codes
400 — Bad Request
Returned when the request itself is malformed. Common causes:- The uploaded selfie file is empty (multipart endpoints).
request_idwas provided but is not a valid UUID.- Path or query parameters fail Pydantic validation (for example,
page=0orpage_size > max). - Missing or malformed JSON body on POST endpoints that require it.
401 — Unauthorized
Returned when theX-API-Key header is missing entirely. Add the header and retry. See Authentication.
403 — Forbidden
Returned for any of the following:- The API key is unknown, inactive, or has been deleted.
- The
org_idin the URL does not belong to the API key. - The
event_idin the URL does not belong to theorg_id. - The request originated from a host that is not on the allowlist (see Host Validation).
- The endpoint requires an event-level feature flag (
bib_search,selfie_search,video_search,video_selfie_search) that is currentlyfalsefor this event. Check the flags from Event Details before calling search endpoints.
404 — Not Found
Returned when:- The event does not exist or its memories configuration is missing.
- A
request_id-scoped GET is called with an unknown UUID. This typically means noPOSThas been made for that UUID, or the search record was rotated out. - A BIB number does not exist for the event. (Some endpoints return a
200with an emptyimages[]array instead — see the endpoint page for which behaviour applies.)
422 — Unprocessable Entity
Returned when the request body or query parameters fail Pydantic schema validation. Common causes:- Unknown value for an enum field (for example,
method: "qr"on Download Original Photos, which only accepts"bib"or"selfie"). - A required field is missing from the JSON body.
- A field is the wrong type (for example,
identifiersent as a number instead of a string).
message flattens all per-field errors into a single string. Fix the request and resend.
429 — Too Many Requests
Returned when API Gateway throttling kicks in. The 9Pic API is fronted by an AWS API Gateway stage with a sustained-rate limit and a burst capacity applied across the entire/api/v1/ext/... surface — every client, every key, and every endpoint share the same token bucket.
Exact rate and burst limits are tuned over time and are not published here. Contact support at hello@9pic.ai if you need the current numbers or want them raised for a specific event or campaign.
429 responses are returned by API Gateway before the request reaches the application layer. The body therefore does not match the unified { responseType, message, data } envelope. Expect a minimal payload such as:
- Treat
429as transient and always retryable. - Use exponential backoff with jitter (for example, start at 500 ms, double up to a cap of 30 s, add ±25% jitter).
- Reuse the same
request_idon selfie-driven endpoints. Successful retries resolve to the cached result, so you do not pay for the same search twice — see request_id idempotency. - If you sustain bursts above the platform limit (for example, opening the search to large simultaneous audiences), reach out to support so we can review the throttle profile for your integration.
500 — Internal Server Error
Returned when the API could not record the request or start an async job. Examples:- Database write failed before the request could be persisted.
- An async pipeline (for example, video clipping) could not be enqueued.
200 with data.status: "failed" and data.error: "<reason>". The selfie record is marked failed, and a fresh POST is the safest retry path. See retry guidance.

