Docs
API · errors

Errors

Drin uses conventional HTTP status codes and returns a consistent JSON envelope on any non-2xx response. Switch on error.type — it's stable and machine-readable; never parse the message.

01 The envelope

Every non-2xx response carries the same shape:

Error response
{
  "error": {
    "type": "validation_error",
    "message": "`to` must contain at least one recipient.",
    "param": "to"
  }
}
FieldDescription
typeMachine-readable category — switch on this. One of the values in the table below.
messageHuman-readable explanation. Safe to log; don't parse it — wording may change.
codeOptional finer-grained code, when present.
paramOptional offending request field, when the error is about input.

02 Error types

Each type maps to a status range. The status tells you how to react; the type tells you why.

typeStatusMeaning
validation_error400 / 422The request was malformed or failed validation — param points at the field.
authentication_error401Missing, malformed, or revoked API key.
permission_error403The key is valid but not allowed to do this — wrong project, sandbox restriction, or plan limit.
not_found404No such resource for this account.
conflict409Conflicts with current state — an idempotency replay with a different body, or deleting a domain with sending history.
suppressed409Every recipient is on this project's suppression list, so nothing was sent.
rate_limited429Too many requests — back off and retry. See Rate limits.
internal_error5xxSomething went wrong on our side. Safe to retry idempotently.

03 Request IDs

Every response echoes a request id in the X-Request-Id header. Include it when you contact support — it lets us find the exact request in our logs.

Retrying safelyThe SDK auto-retries 429 and 5xx with exponential backoff and full jitter. A POST is only retried when you pass an Idempotency-Key, so a send is never duplicated. If you build your own client, do the same — never blindly retry a bare POST.

Working in TypeScript? Each type is also a typed error subclass (DrinValidationError, DrinRateLimitError, DrinSuppressedError, …), so you can branch with instanceof. See the Errors guide and the TypeScript SDK.