Start Here

Handling Errors

Transmit uses conventional HTTP status codes. 2xx means it worked, 4xx means something in the request needs fixing, and 5xx means something went wrong on our side.

The error shape

Every failure has the same body: a machine-readable code and a human-readable message meant for your logs.

{
  "error": {
    "message": "otp_id: Invalid OTP ID",
    "code": "VALIDATION_ERROR"
  }
}

Error codes

400VALIDATION_ERROR

The body failed validation. The message names each failing field, e.g. "phone: phone is required when channel is \"sms\"".

401UNAUTHORIZED

Missing, malformed, unknown or revoked API key.

404NOT_FOUND

No such record, a record belonging to another workspace, or an unknown route. The first two are indistinguishable on purpose.

409CONFLICT

An Idempotency-Key was reused with a different body or on a different route.

409IDEMPOTENCY_CONFLICT

A request with the same Idempotency-Key is still being processed. Comes with Retry-After: 2.

422UNSUPPORTED_DESTINATION

SMS is not available for the number’s country yet — send on the email channel. A broadcast gets this only when no number in the list is SMS-routable; otherwise those numbers are left out of totalCount.

429QUOTA_EXCEEDED

A broadcast would exceed your workspace's daily or in-flight recipient quota. The message says how much room is left. No Retry-After.

429RATE_LIMIT_ERROR

A rate limit was hit, or an OTP ran out of verify attempts. Comes with Retry-After when a budget was exceeded.

500INTERNAL_ERROR

Something failed on our side. In production the message is generic; the detail stays in our logs.

503SERVICE_UNAVAILABLE

We could not check your Idempotency-Key, so nothing was done.

What to retry

Retry 429 RATE_LIMIT_ERROR, 409 IDEMPOTENCY_CONFLICT, 500 and 503 — after the Retry-After header when one is present, with backoff otherwise. Retry 429 QUOTA_EXCEEDED only once earlier broadcasts have drained or the 24-hour window has moved on. Do not retry other 4xx responses unchanged; they will fail the same way.

Always retry a send with the same Idempotency-Key you used the first time. That is what makes a retry after a timeout safe — see Idempotency.