Errors & rate limits

HTTP status codes, retries, and idempotency.

The API uses conventional HTTP status codes and returns a JSON error body:

{
  "error": "contact_opt_in_required",
  "message": "An active WhatsApp opt-in record is required before sending to this contact."
}

Status codes

CodeMeaning
200Success.
400Invalid request (missing/!malformed fields).
401Missing or invalid API key.
403Key lacks the required scope.
404Resource not found.
409Conflict (e.g. duplicate idempotency key).
422Valid shape but not allowed (e.g. outside the messaging window).
429Rate limited — back off and retry.
5xxTransient server error — safe to retry.

Retries & idempotency

Retry 429 and 5xx responses with exponential backoff. To make retries safe, send an Idempotency-Key header on writes — Wabery returns the original result for a repeated key instead of sending twice:

await wabery.messages.send({
	channelId: "channel_...",
	conversationId: "conversation_...",
	text: "Hi",
	idempotencyKey: "7c3f-order-2291",
});
curl https://api.wabery.com/v1/messages \
  -H "Authorization: Bearer $WABERY_API_KEY" \
  -H "Idempotency-Key: 7c3f-order-2291" \
  -H "Content-Type: application/json" \
  -d '{ "channel_id": "channel_...", "conversation_id": "conversation_...", "text": "Hi" }'

Rate limits

Limits scale with your plan. When you exceed them you get 429 with a Retry-After header (seconds) — respect it before retrying.

Webhook deliveries are retried automatically with backoff on non-2xx responses, so a brief outage on your endpoint won't drop events.

Errors & rate limits | Wabery Docs | Wabery