kenari.dev

Introduction#

kenari is a proxy that sits in front of Meta's WhatsApp Cloud API. You connect a WhatsApp number once in the kenari dashboard. After that, your code sends the same Cloud API requests it would send to Meta, but to https://api.kenari.dev and with a kenari API key.

You don't need a Meta app, a system user or a long-lived Meta access token in your code. kenari keeps the Meta credentials for each connected WhatsApp Business account (WABA), sealed at rest, and attaches them to your request on the way out.

What kenari is#

  • A proxy for the Cloud API. Paths and JSON bodies are Meta's own: POST /v23.0/{phone-number-id}/messages with messaging_product, to, type and so on. If Meta's reference documents a field on a supported endpoint, you send it through kenari unchanged.
  • One key for every number on your account. A kenari API key (kn_live_… or kn_test_…) authenticates every request. kenari checks that the phone number or WABA in the path belongs to your account before it forwards anything.
  • A webhook relay. Meta sends events to kenari. kenari signs them and delivers them to the endpoints you register in the dashboard.

What kenari isn't#

  • Not a new messaging API. kenari doesn't wrap the Cloud API in its own SDK or payload format. Meta's documentation stays the reference for message payloads.
  • Not a full Graph API gateway. Only an allow-list of WhatsApp endpoints is forwarded (messages, media, message templates, the business profile, and reading a phone number). Anything else returns 404 with KenariRoutingException. See Supported endpoints.
  • Not a way around Meta's rules. Meta's messaging policies, template approval, quality ratings and per-number throughput still apply. kenari passes Meta's own errors back to you as they are.

How a request flows#

text
your app ──► api.kenari.dev ──► graph.facebook.com
          kenari key        Meta token (added by kenari)

For every request kenari:

  1. Matches the path to /{version}/{id} or /{version}/{id}/{edge}. Anything else is a 404.
  2. Checks the Authorization: Bearer header against your API keys. A missing, unknown or revoked key is a 401.
  3. Checks that your account can send: a suspended account or one without an active subscription gets a 402.
  4. Checks that the ID in the path is a number, WABA or media object that belongs to your account, and that the method and edge are on the allow-list. If not, 404.
  5. Checks that the number is still connected and registered with Meta. If not, 422.
  6. Applies rate limits (429 when you're over).
  7. Forwards the request to Meta with the Meta token for that WABA and streams Meta's response back to you.

Meta's status code and JSON body come back to you unchanged. Errors kenari raises itself use the Kenari*Exception types described in Errors.

What's different from calling Meta#

Meta directThrough kenari
Hosthttps://graph.facebook.comhttps://api.kenari.dev
Path/v23.0/{id}/messagesSame
Request bodyCloud API JSONSame
Auth headerAuthorization: Bearer <Meta token>Authorization: Bearer <kenari key>
Meta app, system user, token renewalYours to manageHandled by kenari
WebhooksMeta calls your serverMeta calls kenari; kenari calls your registered endpoints
EndpointsThe whole Graph APIWhatsApp allow-list only
Request tracingx-fb-trace-idx-fb-trace-id plus X-Kenari-Request-Id

Next steps#