skills/integrate-whatsapp/SKILL.md
Connect WhatsApp to your product with Kapso: onboard customers with setup links, detect connections, receive events via webhooks, and send messages/templates/media. Also manage WhatsApp Flows (create/update/publish, data endpoints, encryption). Use when integrating WhatsApp end-to-end.
npx skillsauth add gokapso/kapso-agent-skills integrate-whatsappInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Preferred path:
kapso login)kapso status to confirm project access before onboarding or messagingFallback path: Env vars:
KAPSO_API_BASE_URL (host only, no /platform/v1)KAPSO_API_KEYMETA_GRAPH_VERSION (optional, default v24.0)Auth header (direct API calls):
X-API-Key: <api_key>
Install deps (once):
npm i
Preferred onboarding path (CLI):
kapso setupkapso projects listkapso projects use <project-id>kapso customers listkapso customers new --name "<customer-name>" --external-id <external-id>kapso setup --customer <customer-id>kapso whatsapp numbers list --output jsonkapso whatsapp numbers resolve --phone-number "<display-number>" --output jsonFallback onboarding flow (direct API):
POST /platform/v1/customersPOST /platform/v1/customers/:id/setup_linksphone_number_id to send messages and configure webhooksDetect connection:
whatsapp.phone_number.created (recommended)Recommended Kapso setup-link defaults:
{
"setup_link": {
"allowed_connection_types": ["dedicated"],
"provision_phone_number": true,
"phone_number_country_isos": ["US"]
}
}
Notes:
kapso setup and kapso whatsapp numbers new use dedicated plus provisioning by default.
Keep phone_number_country_isos, phone_number_area_code, language, and redirect URLs as optional overrides.
Platform API base: /platform/v1
Meta proxy base: /meta/whatsapp/v24.0 (messaging, templates, media)
Use phone_number_id as the primary WhatsApp identifier
Use webhooks to receive:
Scope rules:
phone_number_idwhatsapp.message.*, whatsapp.conversation.*) are phone-number onlyCreate a webhook:
node scripts/create.js --scope project --url <https://...> --events <csv>node scripts/create.js --phone-number-id <id> --url <https://...> --events <csv>Common flags for create/update:
--url <https://...> - webhook destination--events <csv|json-array> - event types (Kapso webhooks)--kind <kapso|meta> - Kapso (event-based) vs raw Meta forwarding--payload-version <v1|v2> - payload format (v2 recommended)--buffer-enabled <true|false> - enable buffering for whatsapp.message.received--buffer-window-seconds <n> - 1-60 seconds--max-buffer-size <n> - 1-100--active <true|false> - enable/disableTest delivery:
node scripts/test.js --webhook-id <id>
Always verify signatures. See:
references/webhooks-overview.mdreferences/webhooks-reference.mdTwo Meta IDs are needed for different operations:
| ID | Used for | How to discover |
|----|----------|-----------------|
| business_account_id (WABA) | Template CRUD | kapso whatsapp numbers resolve --phone-number "<display-number>" --output json or node scripts/list-platform-phone-numbers.mjs |
| phone_number_id | Sending messages, media upload | kapso whatsapp numbers resolve --phone-number "<display-number>" --output json or node scripts/list-platform-phone-numbers.mjs |
Common commands:
kapso whatsapp numbers list --output json
kapso whatsapp numbers resolve --phone-number "<display-number>" --output json
kapso whatsapp messages send --phone-number-id <PHONE_NUMBER_ID> --to <wa-id> --text "Hello from Kapso"
kapso whatsapp messages list --phone-number-id <PHONE_NUMBER_ID> --limit 50 --output json
kapso whatsapp messages get <MESSAGE_ID> --phone-number-id <PHONE_NUMBER_ID> --output json
kapso whatsapp conversations list --phone-number-id <PHONE_NUMBER_ID> --output json
kapso whatsapp templates list --phone-number-id <PHONE_NUMBER_ID> --output json
kapso whatsapp templates get <TEMPLATE_ID> --phone-number-id <PHONE_NUMBER_ID> --output json
Install:
npm install @kapso/whatsapp-cloud-api
Create client:
import { WhatsAppClient } from "@kapso/whatsapp-cloud-api";
const client = new WhatsAppClient({
baseUrl: "https://api.kapso.ai/meta/whatsapp",
kapsoApiKey: process.env.KAPSO_API_KEY!
});
Via SDK:
await client.messages.sendText({
phoneNumberId: "<PHONE_NUMBER_ID>",
to: "+15551234567",
body: "Hello from Kapso"
});
node scripts/list-platform-phone-numbers.mjsassets/template-utility-order-status-update.jsonnode scripts/create-template.mjs --business-account-id <WABA_ID> --file <payload.json>node scripts/template-status.mjs --business-account-id <WABA_ID> --name <name>node scripts/send-template.mjs --phone-number-id <ID> --file <send-payload.json>Interactive messages require an active 24-hour session window. For outbound notifications outside the window, use templates.
phone_number_idassets/send-interactive-*.jsonnode scripts/send-interactive.mjs --phone-number-id <ID> --file <payload.json>Preferred path:
kapso whatsapp messages ..., kapso whatsapp conversations ..., kapso whatsapp templates ...Fallback path:
GET /{phone_number_id}/messages, GET /{phone_number_id}/conversationsclient.messages.query(), client.messages.get(), client.conversations.list(), client.conversations.get(), client.templates.get()Use Platform API inbox embeds when the user wants to place Kapso's inbox inside their own app.
Create:
POST /platform/v1/inbox_embedsinbox_embedproject, customer, phone_numberscope_id is blank for project, a customer UUID for customer, and WhatsApp phone_number_id for phone_numbertoken and embed_url once. Store embed_url; list/get/update omit secrets.Example:
{
"inbox_embed": {
"name": "Support inbox",
"scope_type": "phone_number",
"scope_id": "1234567890",
"allowed_origins": ["https://app.example.com"],
"default_mode": "system"
}
}
Manage:
GET /platform/v1/inbox_embedsGET /platform/v1/inbox_embeds/:idPATCH /platform/v1/inbox_embeds/:idDELETE /platform/v1/inbox_embeds/:id (revokes)Creation:
parameter_format: "NAMED" with {{param_name}} (preferred over positional)language (not language_code){{1}}Send-time:
parameter_name in header/body paramsbutton component with sub_type: "url" and indexid or link (never both)Use Flows to build native WhatsApp forms. Read references/whatsapp-flows-spec.md before editing Flow JSON.
node scripts/create-flow.js --phone-number-id <id> --name <name>node scripts/update-flow-json.js --flow-id <id> --json-file <path>node scripts/publish-flow.js --flow-id <id>node scripts/send-test-flow.js --phone-number-id <id> --flow-id <id> --to <phone>node scripts/setup-encryption.js --flow-id <id>node scripts/set-data-endpoint.js --flow-id <id> --code-file <path>node scripts/deploy-data-endpoint.js --flow-id <id>node scripts/register-data-endpoint.js --flow-id <id>Static flows (no data endpoint):
version: "7.3"routing_model and data_api_version are optionalassets/sample-flow.jsonDynamic flows (with data endpoint):
version: "7.3" with data_api_version: "3.0"routing_model is required (defines valid screen transitions)assets/dynamic-flow.jsonHandler signature:
async function handler(request, env) {
const body = await request.json();
// body.data_exchange.action: INIT | data_exchange | BACK
// body.data_exchange.screen: current screen id
// body.data_exchange.data: user inputs
return Response.json({
version: "3.0",
screen: "NEXT_SCREEN_ID",
data: { }
});
}
export or module.exportsscreen: "SUCCESS" with extension_message_response.paramsendpoint_uri or data_channel_uri (Kapso injects these)"flow_token is missing": flow is dynamic without a data endpoint. Attach one and refresh.| Script | Purpose |
|--------|---------|
| list.js | List webhooks |
| get.js | Get webhook details |
| create.js | Create a webhook |
| update.js | Update a webhook |
| delete.js | Delete a webhook |
| test.js | Send a test event |
| Script | Purpose | Required ID |
|--------|---------|-------------|
| list-platform-phone-numbers.mjs | Discover business_account_id + phone_number_id | — |
| list-connected-numbers.mjs | List WABA phone numbers | business_account_id |
| list-templates.mjs | List templates (with filters) | business_account_id |
| template-status.mjs | Check single template status | business_account_id |
| create-template.mjs | Create a template | business_account_id |
| update-template.mjs | Update existing template | business_account_id |
| send-template.mjs | Send template message | phone_number_id |
| send-interactive.mjs | Send interactive message | phone_number_id |
| upload-media.mjs | Upload media for send-time headers | phone_number_id |
| Script | Purpose |
|--------|---------|
| list-flows.js | List all flows |
| create-flow.js | Create a new flow |
| get-flow.js | Get flow details |
| read-flow-json.js | Read flow JSON |
| update-flow-json.js | Update flow JSON (creates new version) |
| publish-flow.js | Publish a flow |
| get-data-endpoint.js | Get data endpoint config |
| set-data-endpoint.js | Create/update data endpoint code |
| deploy-data-endpoint.js | Deploy data endpoint |
| register-data-endpoint.js | Register data endpoint with Meta |
| get-encryption-status.js | Check encryption status |
| setup-encryption.js | Set up flow encryption |
| send-test-flow.js | Send a test flow message |
| delete-flow.js | Delete a flow |
| list-flow-responses.js | List stored flow responses |
| list-function-logs.js | List function logs |
| list-function-invocations.js | List function invocations |
| Script | Purpose |
|--------|---------|
| openapi-explore.mjs | Explore OpenAPI (search/op/schema/where) |
Examples:
node scripts/openapi-explore.mjs --spec whatsapp search "template"
node scripts/openapi-explore.mjs --spec whatsapp op sendMessage
node scripts/openapi-explore.mjs --spec whatsapp schema TemplateMessage
node scripts/openapi-explore.mjs --spec platform ops --tag "WhatsApp Flows"
node scripts/openapi-explore.mjs --spec platform op setupWhatsappFlowEncryption
node scripts/openapi-explore.mjs --spec platform search "setup link"
| File | Description |
|------|-------------|
| template-utility-order-status-update.json | UTILITY template with named params + URL button |
| send-template-order-status-update.json | Send-time payload for order_status_update |
| template-utility-named.json | UTILITY template showing button ordering rules |
| template-marketing-media-header.json | MARKETING template with IMAGE header |
| template-authentication-otp.json | AUTHENTICATION OTP template (COPY_CODE) |
| send-interactive-buttons.json | Interactive button message |
| send-interactive-list.json | Interactive list message |
| send-interactive-cta-url.json | Interactive CTA URL message |
| send-interactive-location-request.json | Location request message |
| send-interactive-catalog-message.json | Catalog message |
| sample-flow.json | Static flow example (no endpoint) |
| dynamic-flow.json | Dynamic flow example (with endpoint) |
| webhooks-example.json | Webhook create/update payload example |
automate-whatsapp - Workflows, agents, and automationsobserve-whatsapp - Debugging, logs, health checks[integrate-whatsapp file map]|root: .
|.:{package.json,SKILL.md}
|assets:{dynamic-flow.json,sample-flow.json,send-interactive-buttons.json,send-interactive-catalog-message.json,send-interactive-cta-url.json,send-interactive-list.json,send-interactive-location-request.json,send-template-order-status-update.json,template-authentication-otp.json,template-marketing-media-header.json,template-utility-named.json,template-utility-order-status-update.json,webhooks-example.json}
|references:{detecting-whatsapp-connection.md,getting-started.md,platform-api-reference.md,setup-links.md,templates-reference.md,webhooks-event-types.md,webhooks-overview.md,webhooks-reference.md,whatsapp-api-reference.md,whatsapp-cloud-api-js.md,whatsapp-flows-spec.md}
|scripts:{create-flow.js,create-function.js,create-template.mjs,create.js,delete-flow.js,delete.js,deploy-data-endpoint.js,deploy-function.js,get-data-endpoint.js,get-encryption-status.js,get-flow.js,get-function.js,get.js,list-connected-numbers.mjs,list-flow-responses.js,list-flows.js,list-function-invocations.js,list-function-logs.js,list-platform-phone-numbers.mjs,list-templates.mjs,list.js,openapi-explore.mjs,publish-flow.js,read-flow-json.js,register-data-endpoint.js,send-interactive.mjs,send-template.mjs,send-test-flow.js,set-data-endpoint.js,setup-encryption.js,submit-template.mjs,template-status.mjs,test.js,update-flow-json.js,update-function.js,update-template.mjs,update.js,upload-media.mjs,upload-template-header-handle.mjs}
|scripts/lib:{args.mjs,cli.js,env.js,env.mjs,http.js,output.js,output.mjs,request.mjs,run.js,whatsapp-flow.js}
|scripts/lib/webhooks:{args.js,kapso-api.js,webhook.js}
<!-- FILEMAP:END -->tools
Build WhatsApp automations with Kapso workflows: configure WhatsApp triggers, edit workflow graphs, manage executions, deploy functions, and debug automation behavior. Use when automating WhatsApp conversations and event handling.
development
Observe and troubleshoot WhatsApp in Kapso: debug message delivery, inspect webhook deliveries/retries, triage API errors, and run health checks. Use when investigating production issues, message failures, or webhook delivery problems.
development
Maintainer-only workflow for handling GitHub Secret Scanning alerts on OpenClaw. Use when Codex needs to triage, redact, clean up, and resolve secret leakage found in issue comments, issue bodies, PR comments, or other GitHub content.
development
Maintainer workflow for OpenClaw releases, prereleases, changelog release notes, and publish validation. Use when Codex needs to prepare or verify stable or beta release steps, align version naming, assemble release notes, check release auth requirements, or validate publish-time commands and artifacts.