Skip to content
WaveSenda
Start free
Docs / Errors & limits

Failure is the interesting part

Integrating a WhatsApp API is mostly handling the number that dropped its connection, the recipient who is not on WhatsApp, and the rate limit. Every failure carries a stable code so you never have to branch on prose.

The envelope

every error, without exception
{
  "error": {
    "code": "session_not_connected",
    "message": "Session 'support' is not connected.",
    "detail": { "session": "support", "status": "logged_out" },
    "request_id": "a1b2c3d4e5f6"
  }
}

Branch on code. The message is written for a human reading a log and changes with copy edits. detail carries field-level messages for a validation failure, and request_id is what turns a support conversation into a one-minute lookup — include it when you write in.

Codes worth handling

CodeHTTPWhat to do
validation_error400A malformed request. detail holds the per-field messages. Fix and resend.
authentication_failed401Missing, revoked or expired key. Not retryable.
forbidden403The key is valid but lacks the scope, or is pinned to other sessions or IPs.
not_found404No such resource in this organisation.
session_not_connected409The number is not linked. Reconnect it — sending will not start working on its own if it was logged out.
recipient_not_on_whatsapp422No WhatsApp account on that number. Never retry. Check in bulk with /v1/contacts/check/ first.
quota_exceeded402A plan limit — numbers, seats, AI credits. Upgrade or free something up.
sending_paused423The deliverability engine halted sending to protect the number. Not a rate limit; see below.
throttled429Too many requests. Back off and retry; honour Retry-After.
gateway_unavailable503The session gateway is unreachable. Your message was queued, not lost.

423 is not 429

sending_paused means stop, not slow down
A 429 means you are asking too fast — back off and carry on. A 423 means the health engine judged the number to be at genuine risk of a ban and deliberately stopped sending. Retrying through it defeats the only mechanism protecting the number. Read /v1/sessions/{id}/health/, fix what the reasons say, and resume from the console.

What is safe to retry

SituationRetry?
429, 500, 502, 503, 504Yes — exponential backoff with jitter.
gateway_unavailableNot needed. The message is already queued and will go when the socket returns.
session_not_connectedOnly after the session reports connected again.
sending_pausedNo. Fix the underlying health problem.
400, 401, 403, 404, 422No. These fail identically forever.

The official SDKs retry 5xx, 429 and a disconnected session twice by default, with backoff. Every retry of a send should carry the same idempotency_key — on WhatsApp a duplicate is not a tidy-up job, the recipient has already been notified twice.

TypeScript
const wa = new WaveSenda({
  apiKey: process.env.WAVESENDA_API_KEY!,
  maxRetries: 3,
  timeoutMs: 20_000,
})

Rate limits

ScopeLimit
/v1/600 requests per minute, per API key
Unauthenticated30 requests per minute, per IP
Login and register10 requests per minute
Per-key overrideA lower ceiling can be set on any individual key

These are API limits. They are not the limit on how fast a number may send — that is set by the sending policy and the warm-up plan, and it is a far smaller number. The API will happily accept sends that the deliverability engine then paces out over hours.

Pagination

Every list is cursor-paginated. Follow next until it is null rather than calculating offsets — the underlying data shifts while you page, and offsets silently skip rows.

shape
{
  "data": [ ... ],
  "next": "https://api.wavesenda.com/api/v1/messages/?cursor=cD0yMDI2...",
  "previous": null,
  "limit": 50
}
Python
for message in wa.messages.iterate(session="support"):
    process(message)
Errors & limits · WaveSenda Docs