Skip to content
PaalChat Docs

Build and operate

Errors and status codes

One error shape for every endpoint, and what to do about each code.

.md

In a nutshell

Every error is {"error": {"code", "message"}}. Branch on error.code - it is stable - and show error.message to people. Validation errors also list the failing fields.

The error envelope

JSON
{"error": {"code": "outside_service_window", "message": "The customer has not messaged in the last 24 hours. Send an approved template instead."}}

Validation errors add the failing fields, keyed in dot notation:

JSON
{
  "error": {"code": "validation_failed", "message": "The to field must be an international phone number (digits, optional leading +). (and 2 more errors)"},
  "errors": {
    "to": ["The to field must be an international phone number (digits, optional leading +)."],
    "text": ["The text field is required when type is text."],
    "text.body": ["The text.body field is required when type is text."]
  }
}

Note

Messages may be reworded; codes will not change within v1. Never parse the message.

Request IDs

Every response has an X-Request-ID header, and error bodies repeat it as error.request_id. Send your own X-Request-ID (8-128 characters: letters, digits, . _ : -) to tie PaalChat's logs to yours; otherwise PaalChat makes one. Log it with failed calls and quote it when you contact PaalTech support - it identifies the request, and the send it queued, in PaalChat's logs.

Codes

HTTP error.code Meaning Retry?
401 unauthenticated Missing, wrong, revoked or expired token No - fix the token
403 missing_ability The token lacks the ability for this endpoint No
403 product_suspended Your product is suspended on PaalChat No - contact PaalTech
403 product_token_required Not a product token No
403 forbidden Not allowed for another reason No
404 not_found Business, WhatsApp account or message not found - or not yours No
404 unknown_phone_number phone_number_id is not connected for this business No
405 method_not_allowed Wrong HTTP method No
403 sandbox_only A simulation called with a live key With a test key
409 sandbox_not_connected The sandbox business has no connected (simulated) WhatsApp yet After connecting it
409 sandbox_not_sent Only sent outgoing messages get simulated statuses No
422 invalid_idempotency_key The Idempotency-Key header is not 1-255 printable characters With a valid key
409 idempotency_key_reused This Idempotency-Key was used for a different request With a new key
409 idempotency_in_progress The first request with this key is still running Yes, shortly, same key
429 business_limit_reached The business reached its daily message limit Tomorrow
422 recipient_suppressed The number is on the business's suppression list After removing it
422 recipient_opted_out The contact opted out of this category (or marketing needs an opt-in) After they opt in
422 recipient_preference_off The contact turned WhatsApp or this topic off No
403 urgent_not_allowed urgent needs the messages.urgent ability With such a key, or without urgent
422 invalid_template_parameters The template's variables, header media or button value are missing, extra or invalid (the message lists them) With the right parameters
409 not_cancellable The scheduled message is already being sent No
409 campaign_not_allowed The campaign cannot do that in its state, or its template is gone After fixing it
409 transfer_not_pending The account transfer is no longer waiting for an answer No
409 channel_not_enabled The business has not set up SMS or email After Set up SMS or email
403 account_not_verified A self-serve account sent a template before verifying its phone number in the dashboard After verifying
429 sending_limit_reached A new self-serve account reached its daily limit of business-initiated messages (it rises as the account builds a good record) Tomorrow
422 channel_not_allowed A sender ID, from address or provider PaalChat cannot use With an allowed one
422 invalid_provider_credentials Arkesel does not accept the business's own API key With a working key
503 provider_unavailable Arkesel could not be reached to check the business's own key Shortly
402 plan_limit_reached The business's PaalChat plan allows no more (members, contacts) After upgrading the plan
402 plan_feature_missing The plan does not include this (inbox, campaigns, automations) After upgrading the plan
503 payment_unavailable Online payment is not set up, or Paystack did not answer Later
409 business_suspended The business is suspended on PaalChat No
409 not_connected No connected WhatsApp number After reconnecting
409 connection_paused PaalChat operators paused sending for this WhatsApp account Later, when resumed
413 payload_too_large Request body too large No - shorten it
422 validation_failed Fields invalid - see errors No - fix the request
403 feature_disabled Media is not enabled for this business No - ask PaalTech to enable it
422 unknown_member No active inbox member with that external_id After signing them in to the inbox
404 unknown_media No such media for this business After uploading the file
409 media_not_ready The media is still being fetched, failed or was deleted When media.updated says stored
422 media_type_mismatch The file does not suit the message type (e.g. a PDF as image) With the right type
422 unsupported_media WhatsApp cannot send this kind of file With a supported file
422 media_too_large Over WhatsApp's size limit for the type With a smaller file
422 outside_service_window Free-form text outside 24 hours Send a template
422 unknown_template No such template in that language No
422 template_not_approved The template is not APPROVED When approved
422 phone_number_required Several numbers - pass phone_number_id With the field
422 template_rejected Meta refused the template (the message gives Meta's reason) After fixing the template
422 waba_required Several WhatsApp accounts - pass waba_id With the field
503 meta_unavailable Meta did not answer normally Yes, later
422 return_url_not_allowed The connect link's return_url origin is not registered for your product After PaalTech registers it
429 rate_limited Over 300 requests per minute After Retry-After seconds
500 server_error A PaalChat problem Yes, with backoff

Delivery failures

A message accepted with 202 can still fail at Meta. That is not an HTTP error: it arrives as a message.status callback with status: failed and error: {code, message}. Common codes:

error.code Meaning
131026 Undeliverable - the number is not on WhatsApp or uses an old app
131047 More than 24 hours since the customer's last message
131049 Meta limited marketing messages to this user
131050 The user stopped marketing messages
132000 Template parameter count does not match
132001 Template missing or not approved at Meta
130429, 131056 Meta rate limits
connection_unavailable The WhatsApp account was disconnected before the message was sent
no_message_id Meta accepted the message but returned no ID

Other numeric codes are Meta's error codes.

Handling strategy

  • 4xx except 429: do not retry; fix the cause or show the message.
  • 429 and 5xx: retry with backoff - see Safe retries.
  • Network errors on a send: retry with the same reference.