Broadcasts
A broadcast sends one email to every contact in a segment, personalised per recipient.
This is a different path from POST /v1/send, on purpose. A single send builds one MIME message addressed to all of its recipients, which means it cannot carry a per-recipient body or a per-recipient unsubscribe link. A broadcast fans out instead: one message row and one send job per recipient.
That also means a broadcast of N recipients costs N quota units.
Lifecycle
draft ──▶ queued ──▶ sending ──▶ sentA fan-out that fails lands in failed instead. There is no way back to draft.
Create it as a draft, then send:
curl -X POST http://api.localhost/v1/broadcasts \
-H "X-API-Key: $NOTIFYZR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "name": "March update", "segment_id": "…", "template_id": "…" }'
curl -X POST http://api.localhost/v1/broadcasts/$ID/send \
-H "X-API-Key: $NOTIFYZR_API_KEY"/send returns as soon as the fan-out is queued. Nothing is mailed synchronously.
Things worth knowing
The audience is resolved when the worker runs, not when you press send. A segment is a live filter, and freezing tens of thousands of addresses into a queue message would be both enormous and already stale by the time it ran.
Suppressed addresses are excluded during fan-out, so a mostly-opted-out segment does not produce runs of empty batches.
Quota is re-checked per recipient. A long fan-out can cross the ceiling partway through. That is not a failure: what was sent was sent, the rest are counted in skipped_count, and the broadcast completes.
There is no pause. Stopping midway would leave an audience half-mailed, which is worse than either outcome.
Edit and delete are draft-only. Once queued, the content is partly out the door — and a sent broadcast's message rows would be orphaned by a delete.
Checking on one
curl http://api.localhost/v1/broadcasts/$ID -H "X-API-Key: $NOTIFYZR_API_KEY"recipient_count is the audience measured when the fan-out claimed the broadcast, queued_count how many of them actually got a message row, and skipped_count the difference — normally an opt-out or the monthly message quota running out partway.
Those three describe the fan-out. The stats object beside them describes what became of the messages it wrote, read from messages:
"stats": { "total": 1204, "delivered": 1187, "failed": 9, "pending": 8 }pending covers both queued and processing, so the three outcome buckets always add up to total. Every broadcast carries stats, including a draft, where it is all zeros.
To see the individual messages, filter the message list by the broadcast:
curl "http://api.localhost/v1/messages?broadcast_id=$ID" \
-H "X-API-Key: $NOTIFYZR_API_KEY"last_error tells you why a fan-out stopped. A failed fan-out is not retried — retrying after a partial fan-out would re-mail everyone it had already reached, so the error is recorded for an operator instead.