Errors
Errors use RFC 9457 problem details with Content-Type: application/problem+json, plus a stable machine-readable code:
{ "type": "https://developers.waasl.io/errors#window_closed", "status": 409, "code": "window_closed", "title": "The 24-hour window has closed", "detail": "Send an approved template to reopen the conversation.", "request_id": "req_01HZX4"}Branch on code — title and detail are human-readable and may change or be localised (Arabic or English, following Accept-Language). Include request_id when you contact support; it’s also returned in the X-Request-Id header of every response.
Validation errors list each bad field:
{ "status": 422, "code": "validation_failed", "title": "Request body is invalid", "errors": [{ "field": "to", "code": "invalid_phone", "message": "Not a valid E.164 number" }] }Status codes
Section titled “Status codes”| Status | Meaning |
|---|---|
200 / 201 / 202 / 204 |
Success · created · accepted for async processing · no content |
400 |
Malformed JSON or headers |
401 |
Missing or invalid API key |
403 |
Key lacks the scope, or the plan lacks the feature |
404 |
Not found in this workspace |
409 |
The resource’s state doesn’t allow this (see codes below) |
413 |
Upload too large |
422 |
Validation failed |
429 |
Rate limited — see Retry-After |
5xx |
Something went wrong on our side — safe to retry with the same Idempotency-Key |
Error codes
Section titled “Error codes”code |
Status | Meaning |
|---|---|---|
unauthorized |
401 | Missing, invalid or revoked key |
insufficient_scope |
403 | The key doesn’t have the required scope |
plan_required |
403 | Feature not in the workspace’s plan |
not_found |
404 | Resource doesn’t exist in this workspace |
validation_failed |
422 | See errors[] |
invalid_cursor |
422 | Pagination cursor is malformed or expired |
window_closed |
409 | Outside the 24-hour window — send a template |
conversation_closed |
409 | Reopen the conversation first |
contact_blocked |
409 | The contact is blocked |
bot_in_control |
409 | An AI agent or workflow owns the conversation |
idempotency_conflict |
409 | Key reused with a different request |
template_not_found |
422 | No approved template with that name and language |
media_not_found |
422 | Unknown media_id |
channel_not_connected |
409 | The channel is disconnected or in error |
insufficient_balance |
402 | Messaging wallet is empty |
rate_limited |
429 | Slow down — see Rate limits |
internal_error |
500 | Retry with backoff |