Channels
Meta Cloud API JSON webhook signed with X-Hub-Signature-256. HMAC fail-closes without app_secret. Subscribe handshake is GET hub.mode=subscribe on the same HTTP front.
Self-host
In Meta Developer Console, add WhatsApp, copy the access token, phone number ID, and app secret, set a verify token, point the callback at a public HTTPS URL, subscribe the messages field.
export WHATSAPP_ACCESS_TOKEN='…'
export WHATSAPP_PHONE_NUMBER_ID='…'
export WHATSAPP_APP_SECRET='…'
export WHATSAPP_VERIFY_TOKEN='…'
export PORT=8080cx.channels.add(
"whatsapp",
via="self-host",
access_token=access_token,
phone_number_id=phone_number_id,
app_secret=app_secret,
bot_token="local",
)
# POST -> cx.handle("whatsapp", body, headers)
# GET hub.mode=subscribe on the same HTTP front (not handle())await cx.channels.add("whatsapp", {
via: "self-host",
access_token,
phone_number_id,
app_secret,
bot_token: "local",
})
// POST → await cx.handle("whatsapp", body, headers)
// GET hub.mode=subscribe on the same HTTP front (not handle())What it can do
Plans Post (including a button menu), Reply, SendMedia, and React. No pin, typing, edit, or delete. Delivery receipts are not core Events — parse returns [].