Opt-in WhatsApp Cloud API integration via Kapso — channel adapter, webhook router, HMAC verification, and Kapso-curated agent skills.
The @app/messaging-whatsapp package wraps the official WhatsApp Cloud
API behind a provider-agnostic ChannelAdapter port and ships a
production-ready Kapso adapter so you can send and receive messages
without dealing with Meta Business verification yourself.
It is opt-in. Don't install it if your app doesn't need WhatsApp.
Kapso handles WABA provisioning, the phone number,
and Meta Business Verification for you. You get an API key, a phone
number id, and a webhook secret — and the same Cloud API request shapes
you'd use against Meta directly. Migrating to Meta later is a swap of
the ChannelAdapter implementation; the rest of the codebase only sees
IncomingMessage / OutgoingMessage.
The package's port is provider-agnostic. The Kapso adapter is the only
implementation today — implement another for direct Meta or any other
Cloud-API-compatible vendor.
The CLI prints a secret_key — save it as KAPSO_WEBHOOK_SECRET.
Generate a project API key (Dashboard → Settings → API keys); save it
as KAPSO_API_KEY.
The repo ships three Kapso-curated agent skills under .claude/skills/
(integrate-whatsapp, automate-whatsapp, observe-whatsapp) with
operational scripts and references for templates, flows, debugging, and
webhook workflows. Future Claude Code sessions in this repo pick them up
automatically.
The package's IncomingMessage slots cleanly into the @app/assistant
turn loop. Build a ConversationTurn[] from your conversation history,
hand it to runAssistantTurn, send the reply back via
adapter.sendMessage. The two packages don't depend on each other —
the glue lives in your consumer code.
Kapso signs every webhook with HMAC-SHA256 over the raw body, sent in
the X-Webhook-Signature header. The router rejects malformed or
mismatched signatures with 401 before parsing JSON. Bring the secret
from kapso whatsapp webhooks new — there's no way to recover it after
creation, so capture it on the spot.
Implement a new ChannelAdapter (e.g. MetaChannelAdapter) for the
provider you're moving to, swap the wiring, redeploy. The webhook
payload shape and the Cloud API request shape are mostly the same;
adjust parseIncoming and the URL/auth shape in your http client.