Documentation / Complete
The full error catalog
Every code /v1 emits, with its HTTP status and what to do. They are stable: from the first integrator they are NOT renamed (that would break your switch). English only, on purpose (the code is the contract, the message is for pasting into a log and googling).
| code | HTTP | message | action |
|---|---|---|---|
API_KEY_MISSING | 401 | The Authorization header is missing or malformed | Bug in your integration — send Authorization: Bearer wc_live_… |
API_KEY_INVALID | 401 | The API key is invalid or has been revoked | Check / rotate the key in the panel |
ACCOUNT_SUSPENDED | 403 | Account is suspended or cancelled | Resolve billing / contact support |
RATE_LIMITED | 429 | Per-key rate limit exceeded | Back off and retry (limit 600/min per key) |
IDEMPOTENCY_KEY_REQUIRED | 400 | The Idempotency-Key header is required | Send a unique UUID in Idempotency-Key |
INVALID_TYPE | 400 | type must be text, template, image, document, audio or video | Fix type |
INVALID_BODY | 400 | text.body (or template.name) is required | Fix the message body |
INVALID_RECIPIENT | 400 | to must be a plausible E.164 number (8–15 digits) | Fix to |
MEDIA_LINK_OR_ID_REQUIRED | 400 | A <type>.link (https URL) or <type>.id (Meta media id) is required | Send one of them under the media object |
MEDIA_LINK_AND_ID | 400 | Provide EITHER link or id, not both | Send only one |
MEDIA_LINK_INVALID | 400 | <type>.link must be a well-formed https URL | Use a public https URL (Meta fetches it) |
AUDIO_CAPTION_NOT_ALLOWED | 400 | type audio does not accept a caption | Remove audio.caption |
CONNECTION_REQUIRED | 400 | Provide connectionId (conn_…) or from (phoneNumberId) | Send one of them |
CONNECTION_NOT_FOUND | 404 | No connection matches connectionId/from for this account | Check the connection id (a number of ANOTHER account is also reported as not found) |
CONNECTION_NOT_READY | 409 | The number exists but is not connected yet (details.status = its real state) | Wait for it to become connected, or refresh its status — do NOT change your payload |
MESSAGE_NOT_FOUND | 404 | No message with that id for this account | Check the msg_… id |
QUOTA_EXCEEDED | 429 | Plan message quota exceeded (policy block) | Upgrade plan or wait for the period to renew |
MEDIA_ID_REQUIRED | 400 | A media id is required | Include the media id in the path |
MEDIA_NOT_FOUND | 404 | No media with that id for this account (or expired at Meta) | Only fetch media ids from your own inbound events |
MEDIA_TOO_LARGE | 413 | Media exceeds the size limit | Do not proxy files above the limit |
MEDIA_UPSTREAM | 502 | Could not resolve/download the media from Meta | Retry; the media may have expired |
INTERNAL | 500 | Internal server error | Retry; if it persists, contact support |
APIKEY_NAME_REQUIRED | 400 | A non-empty name is required to create an API key | Send a name |
APIKEY_NOT_FOUND | 404 | No API key with that id for this account | Check the key id |
WEBHOOK_URL_REQUIRED | 400 | A url string is required | Send a url |
WEBHOOK_URL_UNSAFE | 400 | URL must be https to a public host (private/loopback/link-local rejected) | Use a public https URL |
WEBHOOK_EVENTS_INVALID | 400 | events must be known event types | Use the subscribable event types (see the event catalog) |
WEBHOOK_NOT_FOUND | 404 | No webhook endpoint with that id for this account | Check the wh_… id |
WEBHOOK_STATIC_HEADER_INVALID | 400 | The static header name is invalid or reserved | Use a valid header name; never Authorization/Cookie/Host/Content-* |
WEBHOOK_CREATE_FAILED | 500 | Could not create the webhook endpoint | Retry |
ALERT_NOT_FOUND | 404 | No alert with that id for this account | Check the alert id |
CONNECTION_QUOTA_EXCEEDED | 429 | This number's monthly message limit is exhausted | Raise the limit for THIS connection (≠ upgrading the plan) |
CONNECTION_EXTERNAL_ID_TAKEN | 409 | Another connection in this account already uses that externalId | Pick a different externalId (unique within an account) |
CONNECTION_LIMIT_INVALID | 400 | monthlyMessageLimit must be a non-negative integer or null | Fix the value |
INVALID_DATE | 400 | from/to must be YYYY-MM-DD | Fix the date |
INVALID_PERIOD | 400 | period must be YYYY-MM | Fix the period |
WEBHOOK_CONNECTION_INVALID | 400 | connectionId is not a valid connection id | Send a numeric connection id or omit for the account default |
WEBHOOK_CONNECTION_NOT_FOUND | 404 | No connection with that id for this account | Check the connection id |
ONBOARDING_MODE_INVALID | 400 | mode must be cloud_api, coexistence, or omitted | Fix mode |
ONBOARDING_RETURN_ORIGIN_INVALID | 400 | returnOrigin must be an exact https origin (public, no path) | Send https://host (SSRF-guarded) |
ONBOARDING_REDIRECT_URL_INVALID | 400 | redirectUrl must be a public https URL | Send an https URL (SSRF-guarded) |
ONBOARDING_LINK_NOT_FOUND | 404 | No onboarding link with that id | Check the onb_… id |
ONBOARDING_LINK_INVALID | 404 | This onboarding link is not valid | The token is wrong/unknown |
ONBOARDING_LINK_USED | 410 | The link was already used | Issue a new link |
ONBOARDING_LINK_EXPIRED | 410 | The link expired | Issue a new link |
ONBOARDING_LINK_REVOKED | 410 | The link was revoked | Issue a new link |
ONBOARDING_LINK_ALREADY_USED | 410 | This onboarding link was already used | Issue a new link (single use) |
BRAND_LOGO_URL_INVALID | 400 | brandLogoUrl must be a public https URL | Use a public https image URL (SSRF-guarded) |
BRAND_COLOR_INVALID | 400 | brandColor must be a #RRGGBB hex color | Fix the color |
BRAND_EMAIL_INVALID | 400 | brandSupportEmail must be a valid email | Fix the email |
BRAND_WEBSITE_INVALID | 400 | brandWebsite must be an https URL | Fix the URL |