Errors#
You can get an error from one of two places:
- kenari itself rejects the request before it reaches Meta (bad key, unpaid account, unknown route, and so on), or can't reach Meta. These errors are listed below.
- Meta answers with an error. kenari passes it through unchanged, with Meta's own status and body.
To tell them apart, look at error.type. kenari's own errors always have a type that starts with Kenari.
Error shape#
kenari's errors use the same envelope as Graph API errors, so code that already parses Meta errors can read them:
{ "error": { "message": "Invalid or missing API key.", "type": "KenariAuthException", "code": 1001, "fbtrace_id": "req_Xq3v9mK2pL0aB7cD1eF4gH" }}| Field | Meaning |
|---|---|
message | A readable explanation. Don't match on it: the wording can change. |
type | The error class, from the table below. |
code | A stable number for the error class. Codes are never renumbered. |
fbtrace_id | kenari's request id. It's the same value as the X-Kenari-Request-Id response header. |
Every response, whether it succeeded or failed, has an X-Kenari-Request-Id header. Include it when you contact support.
kenari error codes#
code | type | HTTP status | Meaning | What to do |
|---|---|---|---|---|
| 1001 | KenariAuthException | 401 | The API key is missing, malformed or revoked, or it's a test key used on a number that isn't a sandbox number. | Send Authorization: Bearer kn_live_… (or kn_test_… for sandbox numbers). Create a new key in the dashboard if this one was revoked. |
| 1002 | KenariBillingException | 402 | The account can't use the proxy: it has no active subscription, its payment is overdue, or it's suspended. | Check the Billing page in the dashboard. |
| 1003 | KenariRoutingException | 404 | The route isn't on the allow-list, the id isn't connected to your account, or a media request has no phone_number_id. | Check the method, path and id. For media GET/DELETE, add ?phone_number_id=. |
| 1004 | KenariPayloadTooLargeException | 413 | The request body is larger than 100 MB. | Send a smaller file. |
| 1005 | KenariNotConnectedException | 422 | The number or its WABA can't be used right now. message gives the reason (see below). | Fix the connection in the dashboard, then retry. |
| 1006 | KenariThrottleException | 429 | The number or WABA is over its kenari rate limit. | Wait Retry-After seconds, then retry. See Rate limits. |
| 1007 | KenariUpstreamException | 502 | kenari couldn't reach Meta (for example, the connection failed). | Retry with backoff. For sends, check first that the message wasn't delivered. |
| 1007 | KenariUpstreamException | 503 | Meta didn't answer in time (30 s, or 120 s for media). | Same as 502. |
Messages you may see#
| Status | message |
|---|---|
| 401 | Invalid or missing API key. |
| 401 | Test keys only work with sandbox numbers. |
| 402 | This account has no active subscription. |
| 402 | Subscription payment is overdue. |
| 402 | This account is suspended. |
| 404 | Unknown route or object. |
| 413 | Request body exceeds 100 MB. |
| 422 | WABA token revoked. |
| 422 | WABA disconnected. |
| 422 | Number disconnected., Number restricted. or Number flagged. |
| 422 | Number not registered. |
| 429 | Rate limit reached for this number. |
| 502 | Meta could not be reached. |
| 503 | Meta request timed out. |
The 429 message says "this number" even when the WABA read budget is what ran out.
A 502 also covers unexpected errors inside kenari that happen while handling a proxied request.
Order of checks#
kenari checks a request in this order and stops at the first failure:
- Path shape and method → 404
- API key → 401
- Billing → 402
- Allow-list and ownership → 404
- Test key on a number that isn't a sandbox number → 401
- Number and WABA state → 422
- Declared body size → 413
- Rate limit → 429
- Forward to Meta → Meta's response, or 502/503
So a request that fails in more than one way gets the error for the earliest check. For example, a request with a bad key and an oversize body gets a 401.
A chunked body with no Content-Length is counted while it streams. If it goes over 100 MB, kenari stops and returns a 413.
Retrying#
kenari never retries anything for you, including sends. A 502 or 503 on POST /messages doesn't prove Meta didn't send the message, so before you resend, check your webhooks or use your own idempotency.
Errors from Meta#
When Meta returns an error, you get Meta's status code and body unchanged. kenari doesn't rewrite, wrap or renumber it. Meta's X-FB-Trace-Id header is passed through too, and so is the real fbtrace_id in Meta's body. Look these codes up in Meta's error code reference.
For a few Meta codes, kenari also updates the state of your connection in the background. The response you receive is still Meta's, untouched. Later requests then get a kenari 422 until the connection is fixed:
Meta error.code | What kenari records | What your next requests get |
|---|---|---|
190 | The WABA's access token is revoked | 422 WABA token revoked. for every number on that WABA |
131031 | The number is restricted | 422 Number restricted. |
133010 | The number isn't registered | 422 Number not registered. |
368 | The number is temporarily blocked | 422 Number flagged. |
For calls made at a WABA id (templates), only 190 changes stored state.
kenari only looks for these codes in JSON error bodies of 64 KB or less. Every other Meta error is passed through with no side effects.