> ## Documentation Index
> Fetch the complete documentation index at: https://docs.kapso.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Sending & receiving

> Send WhatsApp Flows and receive responses via webhooks

## As interactive message

Send a flow in a user-initiated conversation (within the 24-hour window).

<CodeGroup>
  ```typescript TypeScript SDK icon="square-js" theme={null}
  import { WhatsAppClient } from '@kapso/whatsapp-cloud-api';

  const client = new WhatsAppClient({
    baseUrl: 'https://api.kapso.ai/meta/whatsapp',
    kapsoApiKey: process.env.KAPSO_API_KEY!
  });

  await client.messages.sendInteractiveFlow({
    phoneNumberId: '647015955153740',
    to: '15551234567',
    bodyText: 'Book your appointment',
    parameters: {
      flowId: '1197715005513101',
      flowCta: 'Book now',
      flowAction: 'navigate',
      flowActionPayload: {
        screen: 'BOOKING',
        data: { available_dates: ['2024-01-15', '2024-01-16'] }
      }
    }
  });
  ```

  ```bash REST API icon="code" theme={null}
  curl -X POST 'https://api.kapso.ai/meta/whatsapp/v24.0/647015955153740/messages' \
    -H 'X-API-Key: YOUR_API_KEY' \
    -H 'Content-Type: application/json' \
    -d '{
      "messaging_product": "whatsapp",
      "to": "15551234567",
      "type": "interactive",
      "interactive": {
        "type": "flow",
        "body": {
          "text": "Book your appointment"
        },
        "action": {
          "name": "flow",
          "parameters": {
            "flow_message_version": "3",
            "flow_id": "1197715005513101",
            "flow_cta": "Book now",
            "flow_action": "navigate",
            "flow_action_payload": {
              "screen": "BOOKING",
              "data": {
                "available_dates": ["2024-01-15", "2024-01-16"]
              }
            }
          }
        }
      }
    }'
  ```
</CodeGroup>

## As template message

Send a flow outside the 24-hour window using a message template with a FLOW button.

### Create template

<CodeGroup>
  ```typescript TypeScript SDK icon="square-js" theme={null}
  await client.templates.create({
    businessAccountId: '123456789',
    name: 'booking_flow',
    category: 'UTILITY',
    language: 'en_US',
    components: [
      {
        type: 'BODY',
        text: 'Ready to book your appointment?'
      },
      {
        type: 'BUTTONS',
        buttons: [
          {
            type: 'FLOW',
            text: 'Book now',
            flowId: '1197715005513101',
            flowAction: 'navigate',
            navigateScreen: 'BOOKING'
          }
        ]
      }
    ]
  });
  ```

  ```bash REST API icon="code" theme={null}
  curl -X POST 'https://api.kapso.ai/meta/whatsapp/v24.0/123456789/message_templates' \
    -H 'X-API-Key: YOUR_API_KEY' \
    -H 'Content-Type: application/json' \
    -d '{
      "name": "booking_flow",
      "category": "UTILITY",
      "language": "en_US",
      "components": [
        {
          "type": "BODY",
          "text": "Ready to book your appointment?"
        },
        {
          "type": "BUTTONS",
          "buttons": [
            {
              "type": "FLOW",
              "text": "Book now",
              "flow_id": "1197715005513101",
              "flow_action": "navigate",
              "navigate_screen": "BOOKING"
            }
          ]
        }
      ]
    }'
  ```
</CodeGroup>

### Send template

<CodeGroup>
  ```typescript TypeScript SDK icon="square-js" theme={null}
  await client.messages.sendTemplate({
    phoneNumberId: '647015955153740',
    to: '15551234567',
    template: {
      name: 'booking_flow',
      language: { code: 'en_US' },
      components: [
        {
          type: 'button',
          subType: 'flow',
          index: '0',
          parameters: [
            {
              type: 'action',
              action: {
                flowToken: 'user_123_booking',
                flowActionData: {
                  available_dates: ['2024-01-15', '2024-01-16']
                }
              }
            }
          ]
        }
      ]
    }
  });
  ```

  ```bash REST API icon="code" theme={null}
  curl -X POST 'https://api.kapso.ai/meta/whatsapp/v24.0/647015955153740/messages' \
    -H 'X-API-Key: YOUR_API_KEY' \
    -H 'Content-Type: application/json' \
    -d '{
      "messaging_product": "whatsapp",
      "to": "15551234567",
      "type": "template",
      "template": {
        "name": "booking_flow",
        "language": { "code": "en_US" },
        "components": [
          {
            "type": "button",
            "sub_type": "flow",
            "index": "0",
            "parameters": [
              {
                "type": "action",
                "action": {
                  "flow_token": "user_123_booking",
                  "flow_action_data": {
                    "available_dates": ["2024-01-15", "2024-01-16"]
                  }
                }
              }
            ]
          }
        ]
      }
    }'
  ```
</CodeGroup>

## Parameters

| Parameter           | Description                                  |
| ------------------- | -------------------------------------------- |
| `flowId`            | The unique ID of your published flow         |
| `flowCta`           | Button text (1-20 characters)                |
| `flowAction`        | `navigate` (default) or `data_exchange`      |
| `flowActionPayload` | Initial screen and data to pass to the flow  |
| `flowToken`         | Identifier for this flow session - see below |

## Flow token

The `flowToken` is a correlation ID. Meta sends it back with every data endpoint request and when the user completes the flow.

**Default behavior:** If not provided, Kapso uses the `flowId` as the token.

Custom tokens are safe to use. Kapso links a flow response to its flow through the outbound message the reply replies to, not through the token value, so response collection keeps working with any `flowToken`. This applies to flows sent as interactive messages and to flows sent through a template's `FLOW` button.

Responses are stored even when the flow can't be identified — for example when the reply carries no reference to the originating message, or when the project has more than one flow matching the same name.

**When to customize:**

* You're using a data endpoint and need to pass context (e.g., user ID, order ID)
* You're handling response tracking yourself
* The token is available in every data endpoint request via `data_exchange.flow_token`

## Receiving responses

When a user completes a flow, you receive a `whatsapp.message.received` webhook. The message has `type: interactive` with `interactive.type: nfm_reply`.

```json theme={null}
{
  "message": {
    "id": "wamid.ABC123...",
    "from": "15551234567",
    "timestamp": "1704067200",
    "type": "interactive",
    "interactive": {
      "type": "nfm_reply",
      "nfm_reply": {
        "name": "flow",
        "body": "Sent",
        "response_json": "{\"flow_token\":\"1197715005513101\",\"appointment_date\":\"2024-01-15\",\"appointment_time\":\"10:00\"}"
      }
    },
    "kapso": {
      "flow_response": {
        "flow_token": "1197715005513101",
        "appointment_date": "2024-01-15",
        "appointment_time": "10:00"
      },
      "flow_token": "1197715005513101",
      "flow_name": "flow"
    }
  }
}
```

The `interactive.nfm_reply.response_json` contains the raw JSON string from the flow's final screen. Kapso parses this and adds:

| Field                 | Description                                  |
| --------------------- | -------------------------------------------- |
| `kapso.flow_response` | Parsed response data from the flow           |
| `kapso.flow_token`    | The flow token (matches `flowId` by default) |
| `kapso.flow_name`     | Always `"flow"` for WhatsApp Flows           |

To receive flow responses, subscribe to the `whatsapp.message.received` webhook event and filter for `interactive.type === "nfm_reply"`.
