{ "statusCode": 409, "error": "Conflict", "message": "This number has not messaged you in the last 24 hours.", "code": "window_expired", "details": {}}
Telling one error from another
code is the field that names what went wrong, and it is the one to check. The HTTP status is too
coarse on its own: several different errors share a single status, so a 409 alone does not tell
you whether a name was taken or a template was frozen.
if (error.code === "window_expired") return sendTemplate();
The request id
Every response carries X-Request-Id, and every SDK error exposes it as requestId. It is the key
into our request log. A support ticket with it gets answered; one without it starts with us asking
for it.
The catalogue
Authentication
Code
Status
Meaning
invalid_api_key
401
Missing, malformed, expired or revoked.
insufficient_scope
403
Valid key, wrong permissions for this route.
Limits and quotas
These four look similar and are fixed in four different places.
Code
Status
Fix
rate_limited
429
Slow down. Clears in seconds; carries Retry-After.
key_limit_reached
403
This key's monthly cap. Raise the key's limit.
quota_exceeded
403
Your plan's cap. Upgrade, or free something up.
spend_cap_reached
403
This key's Meta spend ceiling for the cycle.
Only rate_limited is worth retrying — see Rate limits & quotas.
The other three do not refill by waiting.
Delivery
Code
Status
Meaning
window_expired
409
Outside the 24-hour window. Send a template.
template_not_approved
409
Meta has not approved it, or has paused it.
template_category_not_allowed
409
Marketing templates cannot be sent through the API.
no_sender
409
No active sending number on the account.
verify_not_configured
409
No Verify template or sender set up yet.
whatsapp_not_connected
400
The WhatsApp connection needs reconnecting.
Bad input
Code
Status
Meaning
invalid_request
400
Generic. message says what is wrong.
not_found
404
No such id on this account.
media_too_large
400
Over WhatsApp's limit for that file type.
unsupported_media_type
400
WhatsApp will not carry that type.
template_name_taken
409
That name is in use. Meta reserves a deleted name for ~30 days.
template_not_editable
409
Approved or in review — Meta freezes content in both.
Idempotency
Code
Status
Meaning
idempotency_conflict
409
The key was reused for a different body, or the first request is still running.
The message tells you which: a first request still running is worth retrying with the same key, a
key already used for a different body never is.
Server errors
Code
Status
Meaning
meta_error
502
Meta failed the operation. details has metaErrorCode and fbtraceId.
service_unavailable
503
Briefly unavailable. Retry; carries Retry-After.
Sandbox
Code
Status
Meaning
test_key_not_allowed
403
That write reaches Meta permanently, so a test key cannot do it.