Errors
This is the canonical reference for the &Open API error model. Every endpoint reports failures the same way, so once you handle errors here you handle them everywhere. Each endpoint's reference page lists the specific failures you can expect from that call and links back to this page for the shared contract.
The error model
The API uses conventional HTTP status codes to signal the broad outcome of a request:
2xx: the request succeeded.4xx: the request failed because of something in the request: a missing field, an invalid value, an unknown resource, or a permission problem. The body tells you exactly what to fix.5xx: something failed on our side. These are rare.
Every non-2xx response also carries a structured JSON body so failures are
machine-readable, not just a status code.
Response body
All error responses share one shape: a top-level errors array, always an
array, even when there is a single error. Validation failures return every
problem at once, so a client can surface them together rather than one
round-trip at a time.
{
"errors": [
{
"type": "validation_error",
"code": "required",
"message": "is required",
"param": "recipient.email"
},
{
"type": "validation_error",
"code": "invalid_reference",
"message": "does not exist",
"param": "campaign_id"
}
]
}
Each object in the array describes one problem:
| Field | Type | Description |
|---|---|---|
type | string | The error category, one of the closed set below. |
code | string | A machine-readable code scoped to the type, in snake_case. An open enum (see Error codes). |
message | string | A human-readable explanation of this specific occurrence. For logs and developers, not end users. |
param | string | The request field that caused the error, in dot notation (for example recipient.email). Present only for field-level errors. |
Every response, success or error, also carries a Request-Id header. Include
it when contacting support; it lets us find the exact request in our logs.
Status codes and categories
Every error has an HTTP status code and a type. Each type maps to one or
more statuses, shown below. The table is the full set of error statuses the API
returns, plus the closed list of type values, both taken directly from the
API contract:
| Status | Meaning |
|---|---|
| 400 | The request is malformed or violates a precondition. Typical triggers are a missing or unsupported `AndOpen-API-Version` header, a request body that is not valid JSON, or pagination parameters that fail server-side validation (`limit` non-numeric or non-positive, `after` referencing a record that does not exist). |
| 401 | Authentication failed: missing or invalid bearer token. |
| 403 | Authorized but not permitted to access this resource. |
| 404 | The requested resource does not exist. |
| 409 | An identical request under the same idempotency key is still being processed. Retry after the interval in the Retry-After header. |
| 422 | Validation error: the request was parseable but contains invalid data. All validation errors are returned at once. |
| 429 | Too many requests. Rate limit exceeded. |
| 500 | Internal server error. |
| 503 | Service unavailable. The account may be under maintenance. Check the `Retry-After` header. |
Every error object carries a type from this closed set: validation_error, authentication_error, authorization_error, not_found_error, rate_limit_error, api_error.
type is a closed enum: it will not grow without a new API version, so it
is safe to switch on exhaustively. code is open; see below.
Error codes
code is an open enum: it gives a specific, stable reason within the
type, but new codes may be added under an existing type without a version
bump. Match the codes you know; for any you don't, fall back to the type or
message. Codes are always snake_case.
The codes below are the ones in use today, grouped by their type.
validation_error (400, 422)
The request was well-formed but a value failed validation. All validation
problems for a request are returned together, each with the param it applies
to.
A body that fails validation returns 422. A query parameter that fails
validation returns 400, because the request is rejected before it reaches the
resource. Both carry type: "validation_error", so branch on the status when
you need to tell them apart. These are the 400 cases:
limitthat is not a positive integer (invalid_format)sortnaming an unsupported field (invalid_format)owner=meorsender=mesent under service authentication, which has no connecting user (invalid_format)- a malformed
created_atrange operator or timestamp (invalid_format) - an
aftercursor referencing no existing record (invalid_reference)
Each names the offending parameter in param. Only unsupported_api_version
and malformed_request return 400 as an api_error.
The codes:
required: a required field was missing or empty.invalid: the value is not acceptable for the field, in a way the more specific codes here don't cover.invalid_format: the value is the right kind of thing but malformed. For example an email that isn't a valid address, or a malformed UUID.invalid_reference: the value is a well-formed identifier, but no such record exists or it isn't reachable in this context. An unknowncampaign_idon Create a gift request returns this, as does anaftercursor that references no record.not_unique: the value duplicates one that must be unique.out_of_stock: a requested line item cannot be fulfilled because the variant has no available stock. Theparampoints at the offending line item.idempotency_key_mismatch: theIdempotency-Keyon the request was used in the last 24 hours with a different body. See Create a gift request.idempotency_conflict: a request sent without anIdempotency-Keyreuses the identifying details of a recent request but carries a different body. Supply a key to make the two distinct.
authentication_error (401)
The request could not be authenticated. See Authentication for how to present a token, and Environments for the regional base URLs; a token is only valid in the region it was issued for.
unauthorized: theAuthorizationheader is missing, or the token in it is unrecognized, expired, or presented to the wrong region. The API returns one code for all of these, so a401never tells an unauthenticated caller which of them it was.
authorization_error (403)
The request was authenticated, but the token is not allowed to perform it.
forbidden: your token isn't allowed to access this resource.insufficient_scope: the token is valid but lacks the scope this operation requires.
not_found_error (404)
not_found: the resource named in the path does not exist, or is not visible to your account. The API does not distinguish "absent" from "not yours"; both returnnot_found.
rate_limit_error (429)
rate_limited: you have exceeded the rate limit. The response carriesRateLimit-Limit,RateLimit-Remaining, andRateLimit-Resetheaders, plus aRetry-Afterheader telling you how long to wait before retrying.
api_error (400, 409, 500, 503)
A request-level problem that doesn't fit the categories above, or a fault on our side.
unsupported_api_version: theAndOpen-API-Versionheader is missing or not supported. Returned as a400, before authentication.malformed_request: the request could not be parsed at all, typically a body that is not valid JSON. Returned as a400.request_in_progress: an identical write is still being processed, so this one was neither run nor rejected. Returned as a409; wait the number of seconds in theRetry-Afterheader and send it again.internal_error: an unexpected error on our side. Returned as a500; rare and usually transient, so retry after a short delay.service_unavailable: the service is temporarily unavailable. Returned as a503; honor theRetry-Afterheader before retrying.
Handling errors
Handle errors in this order:
- Check the status code. Retry
5xx,429, and409unchanged, backing off usingRetry-Afterwhere it is present. Change the request before you retry any other4xx; it will fail the same way. - Branch on
typeto handle the category. - Refine on
codewhere you need specific handling. - Use
paramto attach validation messages to the right field in your UI. - Log the
Request-Idso a failure can be traced if you contact support.