Call flow

  1. Meta webhook – WhatsApp sends a calls webhook to Kapso when a voice session starts. Kapso verifies the signature, identifies the WhatsApp configuration, and loads the primary enabled voice agent assignment for that number.
  2. Session launch – Kapso calls Pipecat Cloud POST /public/{agent_name}/start using your Pipecat public API key. The request body includes:
    • kind: "whatsapp_connect"
    • the raw webhook payload
    • the short-lived WhatsApp Graph API token (whatsapp_token)
    • the WhatsApp phone number id (phone_number_id)
    • a context block with Kapso-rendered metadata (see below)
  3. Pipecat handles audio – Your bot.py uses Pipecat’s WhatsAppClient.handle_webhook_request helper to pre-accept and accept the call, connects WebRTC audio, and runs STT → LLM → TTS.
  4. Lifecycle tracking – Kapso persists connect, status, and terminate events in WhatsappCall records, updates contact/conversation links, and issues a terminate request back to Meta when the call ends.
  5. Downstream hooks – Any configured Kapso jobs (webhook forwarding, analytics syncs) continue asynchronously after Kapso responds 200 OK to Meta.

Session payload breakdown

Kapso’s request to Pipecat Cloud contains all the data your agent might need to personalize the call.
{
  "kind": "whatsapp_connect",
  "webhook": { "...": "Raw Meta payload" },
  "whatsapp_token": "EAAG...",
  "phone_number_id": "1234567890",
  "context": {
    "project": {
      "id": "proj-uuid",
      "name": "Demo",
      "slug": "demo"
    },
    "config": {
      "id": "config-uuid",
      "name": "Support Line",
      "phone_number_id": "1234567890",
      "calls_enabled": true,
      "business_account_id": "waba-uuid",
      "is_coexistence": false
    },
    "call": {
      "id": "call-uuid",
      "call_id": "wa-call-abc",
      "direction": "inbound",
      "status": "connected",
      "started_at": "2025-09-30T17:01:23Z"
    },
    "contact": {
      "id": "contact-uuid",
      "wa_id": "56912345678",
      "profile_name": "Alex",
      "notes": []
    },
    "conversation": {
      "id": "conversation-uuid",
      "messages": [
        {
          "id": "msg-uuid",
          "message_type": "text",
          "direction": "inbound",
          "content": "Hi Kapso",
          "created_at": "2025-09-30T16:59:01Z"
        }
      ]
    },
    "call_permission": {
      "allowed": true,
      "status": "granted",
      "expires_at": "2025-09-30T18:12:00Z"
    }
  }
}

Field reference

  • whatsapp_token – use with Pipecat’s WhatsApp client helpers to pre-accept, accept, and terminate the call. Tokens are short-lived, so read them directly from the payload.
  • webhook – the exact body Meta sent to Kapso in case you need raw fields (e.g., call direction, capabilities).
  • context.project – project metadata rendered from ProjectBlueprint to help you call other Kapso APIs using the correct project id.
  • context.config – WhatsApp configuration identifiers, display phone number, WhatsApp Business Account id, and feature flags.
  • context.call – Kapso call record id, WhatsApp call id, direction, status, timestamps, and duration (when available).
  • context.contact – caller profile and notes so you can tailor the conversation.
  • context.conversation.messages – full message history (rendered with WhatsappMessageBlueprint#view(:external)), ordered chronologically.
  • context.call_permission – the latest opt-in/opt-out decision gathered for this contact, if your flows capture outbound dialing consent.
If Kapso cannot resolve a contact or conversation (e.g., brand-new caller), those keys are simply omitted. Sandbox calls also skip the context block entirely.