Blue Reacher
Errors and status codes10 / 50

Errors and status codes

The error envelope, every error_code the API returns, and which failures are worth retrying.

The envelope

Every error returns JSON with a human message and a stable machine-readable code, sometimes with a hint:

{
  "error": "No contact with this phone in the workspace",
  "error_code": "contact_not_found",
  "help": "Create the contact first with POST /v1/contacts"
}

Rate-limit errors add timing:

{
  "error": "Rate limit exceeded",
  "error_code": "rate_limited",
  "retryAfter": 12,
  "resetAt": "2026-08-31T09:20:00Z"
}

Branch on error_code, never on the message text.

Retry rules

StatusRetry?
400, 401, 403, 404, 422No. The same request fails again
409Usually no; the work is done or in flight
429Yes, after retryAfter seconds
5xx, 502 upstream_unavailableYes, with exponential backoff

Always send an Idempotency-Key on POST /v1/messages before adding retries; then a retry after a timeout can never double-send.

Code reference

StatusCodeMeaning
400invalid_requestA required field is missing or malformed
400effect_requires_instantmessage_effect on a drip send
400group_requires_instantGroup target on a drip send
401invalid_api_keyKey missing, malformed, revoked, or wrong prefix
403device_not_ownedThe device_id is not a line in this key's workspace
403sandbox_key_not_supported_hereTest key on conversation history, the one read the simulator does not cover
404not_foundUnknown endpoint or resource outside your scope
404message_not_foundNo queue item or message with that id in your scope
404contact_not_foundNo contact with that phone; opt-out and bot writes never auto-create
404group_not_foundgroup_chat_id not in this key's workspace
409no_online_deviceInstant send with no eligible online line
409idempotency_conflictSame Idempotency-Key still in flight
422not_deliverableUnderstood but cannot be delivered as asked
422audio_url_unreachableVoice memo URL did not fetch as audio
422invalid_statusBad enum value on a state change
400resubscribe_confirmation_requiredopted_out: false without confirm_resubscribe: true
400always_on_confirmation_requiredstatus: active_always without confirm_always_on: true
429rate_limitedOver an API rate limit; wait retryAfter
502upstream_unavailableTransient infrastructure failure; retry shortly

New codes can appear; treat an unrecognised code on a 4xx as non-retryable and on a 5xx as retryable.

The two confirmations, and why they exist

Two writes are deliberately harder than the rest. Re-subscribing an opted-out contact requires confirm_resubscribe: true, and switching the AI assistant to 24/7 replies requires confirm_always_on: true. Both actions can reach a person who asked not to be reached, or at 3am; the extra flag makes them impossible to trigger by accident from a generic client.

On this page