> ## 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.

# Broadcasts API

> Send template messages to multiple recipients programmatically

Send WhatsApp template messages to hundreds or thousands of recipients with full tracking and statistics.

<Info>
  **Example repo:** [github.com/gokapso/whatsapp-broadcasts-example](https://github.com/gokapso/whatsapp-broadcasts-example)
</Info>

## Complete workflow

```typescript theme={null}
// Step 1: Create broadcast
const createResponse = await fetch('https://api.kapso.ai/platform/v1/whatsapp/broadcasts', {
  method: 'POST',
  headers: {
    'X-API-Key': 'your-api-key',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    whatsapp_broadcast: {
      name: 'July promo',
      phone_number_id: '1234567890',
      whatsapp_template_id: '7a8b9c0d-1e2f-3a4b-5c6d-7e8f9a0b1c2d'
    }
  })
});

const { data: broadcast } = await createResponse.json();
const broadcastId = broadcast.id;

// Step 2: Add recipients (repeat for batches > 1000)
await fetch(`https://api.kapso.ai/platform/v1/whatsapp/broadcasts/${broadcastId}/recipients`, {
  method: 'POST',
  headers: {
    'X-API-Key': 'your-api-key',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    whatsapp_broadcast: {
      recipients: [
        {
          phone_number: '+14155550123',
          components: [
            {
              type: 'body',
              parameters: [
                { type: 'text', parameter_name: 'first_name', text: 'John' },
                { type: 'text', parameter_name: 'discount', text: '50%' }
              ]
            }
          ]
        }
      ]
    }
  })
});

// Step 3: Send broadcast
await fetch(`https://api.kapso.ai/platform/v1/whatsapp/broadcasts/${broadcastId}/send`, {
  method: 'POST',
  headers: { 'X-API-Key': 'your-api-key' }
});

// Step 4: Poll for progress
async function waitForCompletion(broadcastId) {
  while (true) {
    const statusResponse = await fetch(
      `https://api.kapso.ai/platform/v1/whatsapp/broadcasts/${broadcastId}`,
      { headers: { 'X-API-Key': 'your-api-key' } }
    );

    const { data } = await statusResponse.json();

    if (data.completed_at || data.stopped_at) {
      console.log(`Broadcast complete: ${data.sent_count}/${data.total_recipients} sent`);
      break;
    }

    console.log(`Progress: ${data.sent_count}/${data.total_recipients}`);
    await new Promise(resolve => setTimeout(resolve, 5000)); // Wait 5s
  }
}

await waitForCompletion(broadcastId);
```

***

## Step 1: Create broadcast

```typescript theme={null}
const response = await fetch('https://api.kapso.ai/platform/v1/whatsapp/broadcasts', {
  method: 'POST',
  headers: {
    'X-API-Key': 'your-api-key',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    whatsapp_broadcast: {
      name: 'July promo',
      phone_number_id: '1234567890',
      whatsapp_template_id: '7a8b9c0d-1e2f-3a4b-5c6d-7e8f9a0b1c2d'
    }
  })
});

const { data } = await response.json();
// data.id = broadcast ID for next steps
// data.status = 'draft'
```

Requirements:

* Phone number must be production type (not sandbox)
* Template must be approved

## Step 2: Add recipients

Add up to 1,000 recipients per request. Repeat for batches over 1,000.

Recipients use Meta's component syntax to populate template variables.

### Body parameters

For templates with body text variables:

```typescript theme={null}
await fetch(`https://api.kapso.ai/platform/v1/whatsapp/broadcasts/${broadcastId}/recipients`, {
  method: 'POST',
  headers: {
    'X-API-Key': 'your-api-key',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    whatsapp_broadcast: {
      recipients: [
        {
          phone_number: '+14155550123',
          components: [
            {
              type: 'body',
              parameters: [
                { type: 'text', parameter_name: 'first_name', text: 'John' },
                { type: 'text', parameter_name: 'discount', text: '50%' }
              ]
            }
          ]
        },
        {
          phone_number: '+14155550124',
          components: [
            {
              type: 'body',
              parameters: [
                { type: 'text', parameter_name: 'first_name', text: 'Jane' },
                { type: 'text', parameter_name: 'discount', text: '40%' }
              ]
            }
          ]
        }
      ]
    }
  })
});
```

### Button parameters

For templates with dynamic button URLs:

```typescript theme={null}
await fetch(`https://api.kapso.ai/platform/v1/whatsapp/broadcasts/${broadcastId}/recipients`, {
  method: 'POST',
  headers: {
    'X-API-Key': 'your-api-key',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    whatsapp_broadcast: {
      recipients: [
        {
          phone_number: '+14155550123',
          components: [
            {
              type: 'body',
              parameters: [
                { type: 'text', parameter_name: 'first_name', text: 'Alicia' },
                { type: 'text', parameter_name: 'discount_code', text: 'JULY25' }
              ]
            },
            {
              type: 'button',
              sub_type: 'url',
              index: 0,
              parameters: [
                { type: 'text', text: 'promo-code-12345' }
              ]
            }
          ]
        }
      ]
    }
  })
});
```

### Media headers

For templates with image/video/document headers:

```typescript theme={null}
await fetch(`https://api.kapso.ai/platform/v1/whatsapp/broadcasts/${broadcastId}/recipients`, {
  method: 'POST',
  headers: {
    'X-API-Key': 'your-api-key',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    whatsapp_broadcast: {
      recipients: [
        {
          phone_number: '+14155550123',
          components: [
            {
              type: 'header',
              parameters: [
                {
                  type: 'image',
                  image: {
                    link: 'https://example.com/promo.jpg'
                  }
                }
              ]
            },
            {
              type: 'body',
              parameters: [
                { type: 'text', parameter_name: 'first_name', text: 'Alicia' },
                { type: 'text', parameter_name: 'discount_code', text: 'JULY25' }
              ]
            }
          ]
        }
      ]
    }
  })
});
```

### Response format

```json theme={null}
{
  "data": {
    "added": 495,
    "duplicates": 5,
    "errors": [
      "Recipient 3: template parameters invalid - Template requires 2 parameters but 1 provided",
      "Recipient 7: invalid phone number format"
    ]
  }
}
```

## Step 3: Send broadcast

Trigger async send job:

```typescript theme={null}
const response = await fetch(
  `https://api.kapso.ai/platform/v1/whatsapp/broadcasts/${broadcastId}/send`,
  {
    method: 'POST',
    headers: {
      'X-API-Key': 'your-api-key'
    }
  }
);

const { data } = await response.json();
// data.status = 'sending'
// data.started_at = timestamp
```

The broadcast processes asynchronously in the background. Poll for progress.

## Step 4: Track progress

```typescript theme={null}
const response = await fetch(
  `https://api.kapso.ai/platform/v1/whatsapp/broadcasts/${broadcastId}`,
  {
    headers: {
      'X-API-Key': 'your-api-key'
    }
  }
);

const { data } = await response.json();
```

### Response metrics

```json theme={null}
{
  "data": {
    "id": "5f6a7b8c-9d0e-1f2a-3b4c-5d6e7f8a9b0c",
    "name": "July promo",
    "status": "sending",
    "total_recipients": 1000,
    "sent_count": 650,
    "failed_count": 50,
    "delivered_count": 600,
    "read_count": 320,
    "responded_count": 45,
    "pending_count": 300,
    "response_rate": 6.9,
    "started_at": "2025-07-15T10:00:00Z",
    "stopped_at": null,
    "completed_at": null
  }
}
```

### Status transitions

* `draft` → `sending` → `completed`, `failed`, or `stopped`
* `draft` → `scheduled` → `sending`
* Poll every 5-10 seconds during send
* Check `status`, `completed_at`, and `stopped_at` for terminal states

### Stop a broadcast

Stop a broadcast that is currently sending:

```typescript theme={null}
const response = await fetch(
  `https://api.kapso.ai/platform/v1/whatsapp/broadcasts/${broadcastId}`,
  {
    method: 'PATCH',
    headers: {
      'X-API-Key': 'your-api-key',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      whatsapp_broadcast: {
        status: 'stopped'
      }
    })
  }
);

const { data } = await response.json();
// data.status = 'stopped'
// data.stopped_at = timestamp
```

Pending recipients stay pending. Kapso does not start new sends after the broadcast is stopped.

***

## Additional features

### Clear recipients

Remove all recipients from a draft or scheduled broadcast:

```typescript theme={null}
await fetch(`https://api.kapso.ai/platform/v1/whatsapp/broadcasts/${broadcastId}/recipients`, {
  method: 'DELETE',
  headers: {
    'X-API-Key': 'your-api-key'
  }
});
```

If the broadcast is scheduled, Kapso returns it to `draft` and clears `scheduled_at`.

### List individual recipients

Get detailed per-recipient status:

```typescript theme={null}
const response = await fetch(
  `https://api.kapso.ai/platform/v1/whatsapp/broadcasts/${broadcastId}/recipients?page=1&per_page=20`,
  {
    headers: {
      'X-API-Key': 'your-api-key'
    }
  }
);

const { data, meta } = await response.json();
```

### Recipient fields

```json theme={null}
{
  "id": "8c9d0e1f-2a3b-4c5d-6e7f-8a9b0c1d2e3f",
  "phone_number": "14155550123",
  "status": "sent",
  "sent_at": "2025-07-15T10:05:23Z",
  "delivered_at": "2025-07-15T10:05:30Z",
  "read_at": "2025-07-15T10:12:45Z",
  "responded_at": "2025-07-15T10:15:00Z",
  "error_message": null,
  "template_components": [
    {
      "type": "body",
      "parameters": [
        { "type": "text", "parameter_name": "first_name", "text": "John" },
        { "type": "text", "parameter_name": "discount", "text": "50%" }
      ]
    }
  ]
}
```

### Batch processing (large campaigns)

For campaigns with 1,000+ recipients:

```typescript theme={null}
// Split recipients into chunks of 1000
const chunkSize = 1000;
for (let i = 0; i < allRecipients.length; i += chunkSize) {
  const chunk = allRecipients.slice(i, i + chunkSize);

  await fetch(`https://api.kapso.ai/platform/v1/whatsapp/broadcasts/${broadcastId}/recipients`, {
    method: 'POST',
    headers: {
      'X-API-Key': 'your-api-key',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({ whatsapp_broadcast: { recipients: chunk } })
  });

  // Optional: small delay between batches
  await new Promise(resolve => setTimeout(resolve, 100));
}
```
