---
title: "Send broadcast"
method: POST
path: "/v1/broadcasts/{broadcastId}/send"
---

# Send broadcast

`POST /v1/broadcasts/{broadcastId}/send`

## Request

- Base URL: `https://api.zavu.dev`
- URL: `https://api.zavu.dev/v1/broadcasts/{broadcastId}/send`
- Auth: HTTP bearer

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.

## Path parameters

- `broadcastId` string, required

## Request body

- BroadcastSendRequest
  - `scheduledAt` string, date-time: Schedule for future delivery. Omit to send immediately.

## Response `202`

Broadcast started or scheduled.

- BroadcastResponse
  - `broadcast` Broadcast, required
    - `id` string, required
    - `name` string, required
    - `status` 'draft' | 'pending_review' | 'pending_admin_review' | 'approved' | 'rejected' | 'escalated' | 'rejected_final' | 'scheduled' | 'sending' | 'paused' | 'completed' | 'cancelled' | 'failed', 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.
    - `channel` 'smart' | 'sms' | 'sms_oneway' | 'whatsapp' | 'telegram' | 'email', required: Broadcast delivery channel. Use 'smart' for per-contact intelligent routing.
    - `messageType` 'text' | 'image' | 'video' | 'audio' | 'document' | 'template', required: Type of message for broadcast.
    - `text` string
    - `content` BroadcastContent: 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.
      - `templateButtonVariables` object: Default button variables for dynamic URL/OTP buttons. Keys are the button index (0, 1, 2). Per-contact values override these.
      - `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.
    - `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
    - `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).

## Other responses

- `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.
- `401`: Unauthorized.
- `402`: Insufficient balance (`insufficient_balance`), or an email broadcast on a plan without email broadcasts (`paid_plan_required`).
- `404`: Broadcast not found.

## Changes

> 80 revisions in range; 1 not diffed.

- **2026-08-07** `c3d44d443adb`: 1 info
  - added the non-success response with the status `403`
- **2026-07-07** `f467a4da6cd2`: 3 info
  - removed the `instagram` enum value from the `broadcast/channel` response property for the response status `202`
  - removed the `messenger` enum value from the `broadcast/channel` response property for the response status `202`
  - removed the `voice` enum value from the `broadcast/channel` response property for the response status `202`
- **2026-06-18** `a817a073a07f`: 1 warning
  - added the new `messenger` enum value to the `broadcast/channel` response property for the response status `202`
- **2026-05-28** `fe72e5565564`: 1 info
  - added the optional property `broadcast/content/templateHeaderVariables` to the response with the `202` status
- **2026-05-15** `3e45958691da`: 1 info
  - added the optional property `broadcast/content/templateButtonVariables` to the response with the `202` status

[Operation history](https://skmtc.dev/zavudev/apis/zavu-unified-messaging-layer-api/changes/v1/broadcasts/:broadcastId/send/post.md)

---

[API](https://skmtc.dev/zavudev/apis/zavu-unified-messaging-layer-api.md) - [All operations](https://skmtc.dev/zavudev/apis/zavu-unified-messaging-layer-api/llms.txt) - [OpenAPI document](https://skmtc.dev/zavudev/apis/zavu-unified-messaging-layer-api/revisions/75bc777b0ffb?raw)
