kenari.dev

Errors#

You can get an error from one of two places:

  1. 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.
  2. 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:

json
{  "error": {    "message": "Invalid or missing API key.",    "type": "KenariAuthException",    "code": 1001,    "fbtrace_id": "req_Xq3v9mK2pL0aB7cD1eF4gH"  }}
FieldMeaning
messageA readable explanation. Don't match on it: the wording can change.
typeThe error class, from the table below.
codeA stable number for the error class. Codes are never renumbered.
fbtrace_idkenari'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#

codetypeHTTP statusMeaningWhat to do
1001KenariAuthException401The 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.
1002KenariBillingException402The 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.
1003KenariRoutingException404The 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=.
1004KenariPayloadTooLargeException413The request body is larger than 100 MB.Send a smaller file.
1005KenariNotConnectedException422The number or its WABA can't be used right now. message gives the reason (see below).Fix the connection in the dashboard, then retry.
1006KenariThrottleException429The number or WABA is over its kenari rate limit.Wait Retry-After seconds, then retry. See Rate limits.
1007KenariUpstreamException502kenari couldn't reach Meta (for example, the connection failed).Retry with backoff. For sends, check first that the message wasn't delivered.
1007KenariUpstreamException503Meta didn't answer in time (30 s, or 120 s for media).Same as 502.

Messages you may see#

Statusmessage
401Invalid or missing API key.
401Test keys only work with sandbox numbers.
402This account has no active subscription.
402Subscription payment is overdue.
402This account is suspended.
404Unknown route or object.
413Request body exceeds 100 MB.
422WABA token revoked.
422WABA disconnected.
422Number disconnected., Number restricted. or Number flagged.
422Number not registered.
429Rate limit reached for this number.
502Meta could not be reached.
503Meta 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:

  1. Path shape and method → 404
  2. API key → 401
  3. Billing → 402
  4. Allow-list and ownership → 404
  5. Test key on a number that isn't a sandbox number → 401
  6. Number and WABA state → 422
  7. Declared body size → 413
  8. Rate limit → 429
  9. 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.codeWhat kenari recordsWhat your next requests get
190The WABA's access token is revoked422 WABA token revoked. for every number on that WABA
131031The number is restricted422 Number restricted.
133010The number isn't registered422 Number not registered.
368The number is temporarily blocked422 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.