Documentation
Sign inGet started

Errors

Every failed Bird API request returns the same JSON envelope, nested under a top-level error key. This is a real response to a send request with an empty body:
Exemplo de código
{
  "error": {
    "type": "validation_error",
    "code": "E01001",
    "name": "ValidationError",
    "message": "Request has 1 validation error.",
    "doc_url": "https://bird.com/docs/api/errors/E01001",
    "request_id": "req_01ky7q3hckecgv6d7jpq865532",
    "details": [{ "param": "body", "message": "missing properties 'from', 'to'" }]
  }
}
The HTTP status follows from the type. Client errors use 400 for malformed requests, 401 or 403 for access failures, 402 for billing, and 404 for missing resources. They use 409 for conflicts, 412 for unmet preconditions, 422 for validation and business-rule failures, and 429 for rate limits. Bird-side failures use 5xx. The status identifies the category; the envelope explains what happened.

The envelope fields

FieldRole
typeBroad category for coarse branching: validation_error, auth_error, permission_error, not_found_error, conflict_error, rate_limit_error, billing_error, internal_error, and a handful of others. A closed enum that grows rarely.
codeOpaque, stable identifier (E01001). The canonical reference: unique, never renamed, never reused. When an error is retired, its code is permanently reserved.
nameHuman-readable slug (ValidationError) for log readability. Always paired with code, never a replacement for it.
messageHuman-readable description. Not stable: wording changes without notice. Display it, log it, never parse it.
paramFor input-related errors, the offending field. Omitted when not applicable.
doc_urlStable link to the docs page for this code.
request_idAlways present, and also returned as the X-Request-Id response header. Quote it in support requests; it lets Bird trace the exact request.
detailsPer-field validation problems. Present only on validation_error responses.
remediationA human-readable next step to resolve the error. Present when a recovery is known.
nextOperations that resolve the error, in the order to try them. Present for errors with a well-defined recovery, such as unmet preconditions.
vendor_codeVerbatim code from a downstream system (an SMTP response code, a payment decline code). Present only when Bird is surfacing an external system's code you may want to act on.
Branch on type for coarse handling and code for specific handling, never on message. A typical client switches on type (retry on rate_limit_error, surface validation_error to the user, page someone on internal_error) and matches individual code values only for the few errors it handles specially.
Codes such as E04012 are intentionally opaque. Each code links to a documentation page through doc_url, which explains the cause and how to resolve it. The full catalog lives in the error reference.

Validation failures: one code, many details

Field-level validation does not get a separate code per field-and-failure combination. Every validation failure is E01001 ValidationError with a details array listing each field-level problem as {param, message}, the way the captured send failure lists its missing properties. The message strings inside details can change and should only be displayed. Use param to map problems to form fields.

Recovery guidance: remediation and next

Errors with a known fix carry it in the envelope. This is a real response to a webhooks call made with an API key that lacks the required scope:
Exemplo de código
{
  "error": {
    "type": "permission_error",
    "code": "E02035",
    "name": "InsufficientScope",
    "message": "This request requires the \"webhooks:read\" scope, which your credential has not been granted.",
    "param": "webhooks:read",
    "doc_url": "https://bird.com/docs/api/errors/E02035",
    "request_id": "req_01ky7q4665emc9tw1pxkptaqwq",
    "remediation": "Re-authenticate with a credential that has been granted the required scope, then retry."
  }
}
remediation is a sentence for a human or an agent log; next, when present, lists the API operations that resolve the error in the order to try them (verify a domain, then retry the send). Agents and CLIs can execute next directly; interactive clients can show remediation as-is.

Handling errors well

  • Retry 429 and 5xx, nothing else by default. Honor Retry-After on rate limits (see Rate limits), use exponential backoff on 5xx, and send an Idempotency-Key so retries of mutating requests are safe.
  • Log code, name, and request_id together. The code is what you'll search the docs and your own logs for; the request ID is what support needs.
  • Tolerate new codes and types. New error codes ship regularly as products grow, and the type enum occasionally gains a value. Write your handler with a sane default branch rather than an exhaustive match.

Next steps