eComms

Search the documentation

Search every page of the documentation and jump to a result.

Errors

The shape of an API error and the closed set of codes it can carry.

Error shape

The body is flat — nothing nests under an error key:

JSON
{
  "code": "validation_failed",
  "message": "The request does not match the contract",
  "details": {
    "issues": [
      {
        "path": ["content", "subject"],
        "code": "too_small"
      }
    ]
  },
  "requestId": "01a0ba31-3fe4-7cc4-a1c6-64bdaaa5d99c"
}

Response attributes

codestringRequired

From the closed set in the table below.

messagestringRequired

Readable, but not meant for an end user — we never translate it.

detailsfree-form map | nullRequired

null unless the code has something structured to add, like the list of fields that failed validation.

requestIdstringRequired

The same id that arrives in the x-request-id header of every response — error or not — so you can capture it even when your client never reads the body.

Codes this surface can answer with

Of the codes the system carries, these are the ones a /v1 caller can actually receive:

Code HTTP status When it shows up
bad_request 400 A rule the schema alone cannot express — POST /v1/email with no address across to, cc and bcc.
unauthorized 401 The bearer token is missing, or does not match any active key.
api_key_expired 401 The bearer token names a key that is past its own expiration. The key stays revocable and visible in the panel; it just no longer authenticates.
payment_required 402 The organization is over its plan’s sending limit.
forbidden 403 The key is valid, but does not carry the permission this action needs.
not_found 404 The resource does not exist, or does not exist for this organization — the response never reveals which.
conflict 409 The idempotencyKey was already used with a different body, or the referenced template is not active.
validation_failed 422 The body does not match the schema — an unrecognized field, a wrong type, more than 50 addresses in one field.
rate_limited 429 This key exceeded its per-second request limit.
internal 500 Something failed on our side.

The full set is longer — the rest are codes for flows /v1 does not expose, like an expired invitation — but any client can safely treat a code it does not recognize as a generic error.