# Send WhatsApp Broadcasts

> Send one approved WhatsApp template to many numbers with the Mojeeb Public API, with values for each recipient, and follow every message's delivery until the broadcast is done.

A broadcast sends one approved template from one of your WhatsApp numbers to many people at once, as the dashboard's [WhatsApp Broadcasts](/docs/channels/whatsapp-broadcasts) page does. With the Public API your systems can send one, then follow each message until it's delivered or read. Broadcasts are on plans that include them.

## How do I send a broadcast?

`POST` the template, the WhatsApp number's connection `id` and the recipients:

```bash
curl -X POST https://api.mojeeb.app/v1/agents/YOUR_AGENT_ID/broadcasts \
  -H "Authorization: Bearer mk_live_YOUR_KEY_HERE" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: eid-offer-2026" \
  -d '{
    "name": "Eid offer",
    "connection_id": "YOUR_CONNECTION_ID",
    "template": { "name": "eid_offer", "language": "ar" },
    "parameters": { "2": "EID20" },
    "recipients": [
      { "phone": "+201001234567", "name": "Sara", "parameters": { "1": "Sara" } },
      { "phone": "+201001234568", "name": "Omar", "parameters": { "1": "Omar" } }
    ]
  }'
```

The answer is `201` with the broadcast, `status: sending`, and Mojeeb sends the messages in the background. Send an `Idempotency-Key` so a retry after a timeout never sends the broadcast twice; see [Idempotency](../idempotency). Every field is in the [Send a broadcast reference](../api-reference/send-broadcast).

## How do I give each recipient their own values?

`parameters` fills the template's body variables for everyone, keyed as the template's `body.parameters` in [List WhatsApp Templates](./list-templates). A recipient's own `parameters` go over them for that recipient, so a shared code and a personal name can sit in one message. Every recipient needs every body value, from one or the other.

## Which templates can be broadcast?

An approved template whose header has no variable and whose buttons need no value per send. A broadcast fills only the body: the header keeps the image, video or document it was approved with, and links and quick replies stay as they are. A template that needs more is refused with `422 template_not_broadcastable`; send those one by one with [Send a WhatsApp Template](./send-template). A template with a location header is refused too, because Mojeeb can't send one yet.

## How do I follow a broadcast?

Read it with `GET` on its `id` ([Get a broadcast](../api-reference/get-broadcast)). Its counts follow each message as WhatsApp reports it: `sent_count` includes the delivered and read messages, and `delivered_count` includes the read ones. When nothing is left to send, `status` becomes `completed`. For each recipient's message, list the [recipients](../api-reference/list-broadcast-recipients); `?status=failed` lists the failed ones, with the reason in `failure_detail`, usually Meta's own sentence. Its wording may change, so show it to a person but never branch on it.

## How do I resend the failed messages?

`POST` to the broadcast's `retry` once it has finished, and Mojeeb sends the template again to the recipients whose message failed. A broadcast still sending answers `409 broadcast_still_sending`: wait until its `status` changes, then retry. One cut off by a restart can stay `sending`; contact support then. The template is checked again, so one paused or changed since the send is refused with `422` before anything is sent. Retrying a `paused` broadcast also sends to the recipients it hadn't reached. If messages failed because the customer blocked the number or isn't on WhatsApp, a retry fails again. See the [Retry reference](../api-reference/retry-broadcast).

## What can go wrong?

- `403 feature_not_available`: your plan doesn't include broadcasts.
- `404 not_found`: the `connection_id` isn't one of the agent's WhatsApp numbers, or the broadcast isn't the agent's.
- `422 template_not_found` (with `available_templates`, the number's template names), `template_not_found_for_language` (with `available_languages`), `template_not_approved` or `template_not_broadcastable`: pick another template.
- `409 broadcast_still_sending`: a retry before the broadcast finished.
- `422 invalid_request`: a recipient lacks a body value (`param` names it), or the audience is larger than the number's WhatsApp daily messaging limit. Split the list, or wait for Meta to raise the limit.
- `422 invalid_request_body`: a number isn't in E.164 format, such as `+201001234567`.

[Errors](../errors) lists every code.

## Common questions

### Does a broadcast reach people who never wrote to me?

Yes, as any template does: a template can be sent at any time, inside or outside the 24-hour window. Send only to people who agreed to hear from you; Meta lowers a number's quality and limits when recipients block or report it.

### Where do the customers' replies go?

Into their conversation with the agent, which the broadcast starts if they have none, so the AI answers them like any other message.

### What does `paused` mean?

Mojeeb stopped sending mid-way, for example during a restart, and the recipients it hadn't reached are still `pending`. If some messages failed, a retry sends to those and to the `pending` ones. With no failed message a paused broadcast can't be retried, so contact support to resume it.

### Can an AI assistant send broadcasts?

Yes. Through the [MCP server](../mcp) an assistant can send one and read broadcasts and their recipients. A single call can reach thousands of people, so use a client that asks you before running it, and read the recipients and the template before you approve.

### Which scopes do these calls need?

`broadcasts:write` to send and retry, and `broadcasts:read` to read. Every key holds both today; see [Authentication](../authentication).
