# Send broadcast

> Start sending the broadcast immediately or schedule for later.

`POST https://api.zavu.dev/v1/broadcasts/{broadcastId}/send`

Start sending the broadcast immediately or schedule for later.

**Sending a broadcast needs no account verification.** Identity and business verification raise daily ceilings; neither is a permission to broadcast, on any channel. What stands in front of a broadcast is the content review below, and it applies to every send path — dashboard, API and CLI. Drafts can be created, edited and kept freely.

**Email broadcasts need a paid plan.** On Free, sending or scheduling a broadcast on the `email` channel is refused with `402` and code `paid_plan_required`; drafts can still be created and edited. A `smart` broadcast is not refused: its email recipients fail individually with `errorCode` `PAID_PLAN_REQUIRED` and the others are sent. Teams created before August 1, 2026 keep their earlier terms.

**Daily ceilings apply per recipient.** Each message a broadcast sends counts against the channel's daily ceiling (see `POST /v1/messages`). Once the ceiling is reached, the remaining recipients are marked `failed` with `errorCode` `DAILY_LIMIT_EXCEEDED`; they are not retried the next day.

**Review depends on the channel, and cannot be bypassed.** A draft is submitted to automated content review here; it does not go straight out. A WhatsApp broadcast built on a Meta-approved template skips review (Meta already vetted the content) and begins sending. An email broadcast sends as soon as the review passes it, unless the review asks for a person. Every other channel moves to `pending_admin_review` and waits for a person. A broadcast the review refuses lands on `rejected`: use PATCH to edit the content then call POST /retry-review, or escalate it for a manual review.

A broadcast is read once, on its own text, rather than per recipient. While an account's sending is suspended its recipients fail individually with `errorCode` `SENDING_SUSPENDED`; see `POST /v1/messages`.

Calling this on a broadcast that is already `approved` or `scheduled` sends or reschedules it directly, since it has already been reviewed. Reserves the estimated cost from your balance.

## Parameters

- `broadcastId` (path, string, required)

## Body

- `scheduledAt` (string<date-time>): Schedule for future delivery. Omit to send immediately.

## Responses

### 202

Broadcast started or scheduled.

- `broadcast` (object, required)
  - `id` (string, required)
  - `name` (string, required)
  - `status` (string, required): Current status of the broadcast. `pending_review`: in the automated content review. `pending_admin_review`: the automated review passed and it waits for a person, which is where every channel but a WhatsApp broadcast on an approved template goes. `rejected`: the review refused it; edit it and retry the review, or escalate. `scheduled` and `sending` follow approval. One of: `draft`, `pending_review`, `pending_admin_review`, `approved`, `rejected`, `escalated`, `rejected_final`, `scheduled`, `sending`, `paused`, `completed`, `cancelled`, `failed`.
  - `channel` (string, required): Broadcast delivery channel. Use 'smart' for per-contact intelligent routing. One of: `smart`, `sms`, `sms_oneway`, `whatsapp`, `telegram`, `email`.
  - `messageType` (string, required): Type of message for broadcast. One of: `text`, `image`, `video`, `audio`, `document`, `template`.
  - `text` (string)
  - `content` (object): Content for non-text broadcast message types.
    - `mediaUrl` (string): URL of the media file.
    - `mediaId` (string): Media ID if already uploaded.
    - `mimeType` (string): MIME type of the media.
    - `filename` (string): Filename for documents.
    - `templateId` (string): Template ID for template messages.
    - `templateVariables` (object): Default body variables (can be overridden per contact). Key them to match the template body: by position (`1`, `2`, ...) for positional templates, or by name (e.g. `customer_name`) for named templates. Zavu detects the template's format and sends the correct payload to Meta. Do not mix positional and named keys.
      - `{key}` (string)
    - `templateButtonVariables` (object): Default button variables for dynamic URL/OTP buttons. Keys are the button index (0, 1, 2). Per-contact values override these.
      - `{key}` (string)
    - `templateHeaderVariables` (object): Default value for a text-header variable, keyed by `1` (can be overridden per contact). If omitted, Zavu resolves the header from `templateVariables` by the header placeholder's name.
      - `{key}` (string)
  - `senderId` (string)
  - `emailSubject` (string)
  - `totalContacts` (integer, required): Total number of contacts in the broadcast.
  - `pendingCount` (integer)
  - `sendingCount` (integer)
  - `sentCount` (integer): Recipients whose message the provider accepted, without a confirmed delivery yet. Channels that never report delivery keep their recipients here.
  - `deliveredCount` (integer): Recipients with confirmed delivery to the device.
  - `failedCount` (integer)
  - `estimatedCost` (number, nullable): Estimated total cost in USD.
  - `reservedAmount` (number, nullable): Amount reserved from balance in USD.
  - `actualCost` (number, nullable): Actual cost so far in USD.
  - `scheduledAt` (string<date-time>)
  - `startedAt` (string<date-time>)
  - `completedAt` (string<date-time>)
  - `metadata` (object)
    - `{key}` (string)
  - `createdAt` (string<date-time>, required)
  - `updatedAt` (string<date-time>)
  - `reviewResult` (object, nullable): AI content review result.
    - `score` (number): Content safety score from 0.0 to 1.0, where 1.0 is completely safe.
    - `categories` (string[]): Policy categories violated, if any.
    - `reasoning` (string): Explanation of the review decision.
    - `reviewedAt` (string<date-time>)
    - `flaggedContent` (string[], nullable): Problematic text fragments, if any.
  - `reviewAttempts` (integer, nullable): Number of review attempts (max 3).

### 400

Invalid request, no contacts, or broadcast not in valid status.

A broadcast whose sender was deleted after it was created is refused here with code `sender_not_found`, before any balance is reserved. Create a new broadcast with another sender.

A WhatsApp broadcast whose template Meta has not approved yet is refused here with code `template_not_approved`. Because a WhatsApp broadcast needs no account verification, this is the only review it passes through: retry once the template is approved.

- `code` (string, required)
- `message` (string, required)
- `details` (object)

### 401

Unauthorized.

- `code` (string, required)
- `message` (string, required)
- `details` (object)

### 402

Insufficient balance (`insufficient_balance`), or an email broadcast on a plan without email broadcasts (`paid_plan_required`).

- `code` (string, required)
- `message` (string, required)
- `details` (object)

### 404

Broadcast not found.

- `code` (string, required)
- `message` (string, required)
- `details` (object)

## Example

```bash
curl -X POST "https://api.zavu.dev/v1/broadcasts/broadcast_abc123/send" \
  -H "Authorization: Bearer $ZAVUDEV_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'
```

```typescript
import Zavudev from "@zavudev/sdk";

const zavu = new Zavudev({ apiKey: process.env.ZAVUDEV_API_KEY });

const result = await zavu.broadcasts.send("broadcast_abc123");

console.log(result);
```
