Errors, n8n and limits

Errors come in one envelope { error, description, data }. The main codes:

  • channel_not_found (404) — no such channel_id (or it is not yours, not selected for the key, or inactive).
  • not_found (404) — no such send, subscription or delivery.
  • forbidden (403) — the key lacks the permission for this action (see "Key permissions").
  • line_license_expired (402) — the line licence has expired; renew the line.
  • idempotency_conflict (409) — the client_msg_id was already used for a different send.
  • replay_unavailable (409) — only a failed delivery with access still in place can be replayed.
  • outside_24h_window (422) — the 24-hour window is closed, plain text will not go out (send a template).
  • invalid_message (422) — the channel refused the content, the template is not found / not APPROVED, note / voice do not fit the file type, or chat_type / reply_to contradict the channel or the conversation.
  • template_error (422) — Meta refused the template create or edit; reason in description, codes in data.
  • invalid_request (400) — the body, query params or a header failed validation (including a media_url not from POST /media/ and a missing Idempotency-Key); per-field detail in data.fields.
  • invalid_webhook_url (400) — the URL is not https or is a private address.
  • storage_quota_exceeded (413) — the file storage quota is used up.
  • unauthorized (401) — the key is missing, malformed or revoked.
  • rate_limited (429) — rate limit exceeded; how long to wait is in data.retry_after_seconds and in the Retry-After header.
  • method_not_allowed (405) — that HTTP method is not supported on this endpoint.
  • internal_error (500) — a failure on our side; retrying is safe, a send repeated with the same client_msg_id will not be delivered twice.

Rate limits are counted per minute, as a rolling window, separately for each kind of request. The values below are the defaults; they can be raised for your project.

Kind of requestPer keyAll keys of a tenant
Reads: channels, history, templates, /allowed/, send outcome12006000
Sending: POST /messages/6003000
Provider calls: POST /media/, template create, edit and delete, template health60300
Management: webhook, secret rotation, subscriptions, catch-up and replay30150

Each key has its own budget, and the tenant ceiling stops new keys from multiplying throughput. Template health checks run at most two at a time per key. Over the limit you get a 429 in the same envelope plus a Retry-After header — respect it instead of retrying blindly.

n8n. There is no ready-made node yet, but the integration comes together from built-ins: a Webhook node receives inbound (enable raw / binary body, otherwise you cannot verify the HMAC), and an HTTP Request node sends replies with an Authorization: Bearer header.

  1. Webhook node: enable raw / binary body and verify X-Wahub-Signature-V2 against the raw body.
  2. HTTP Request node: POST to /messages/ with an Authorization: Bearer gw_… header.

Limits worth keeping in mind while designing your integration:

  • Creating templates through Gateway API: text header/body/footer only; no buttons or media headers.
  • No exclusivity or handoff: a bot and a live operator may both reply (double replies).
  • Several consumers may subscribe to one channel — all of them receive the event.
  • Media is served as a path on our host and needs the same key; there is no public link.