What you will build
Prerequisites
- Your deduplicated recipient list, with an email or phone for each
Run a bulk job
Create the job with the notification and any shared data, ingest recipients into it, then run it once and poll for progress. Ingestion is open-ended and the job does not expire while you fill it. Running is a one-way door.1
Create the job
defines the job with an Returns You can also pass
event and any global data that applies to everyone. The required event is either a or a custom event ID mapped to a notification.201 Created with the job ID you use for every call that follows:brand, locale, and override. To send something other than the notification attached to the event, add template. event stays required.2
Ingest your recipients
adds recipients to the job. Identify each one in Returns Each recipient accepts four fields:
to, and put their personal variables in data, which merges into the job’s global message.data.200 OK, where total is the running count for the whole job rather than the current call:to.user_id, who they areprofile, inline contact datadata, per-recipient variablespreferences, per-recipient overrides
502 instead of a validation error, so split big lists across several calls.3
Run the job
Once everyone is in, triggers the send. Courier fans out and delivers to each recipient.Returns
202 Accepted with an empty body, and the job starts processing in the background.4
Track progress
returns the job’s counts and overall status.
Watch for either, or a failed job leaves you polling forever.
received: recipients ingested.enqueued: messages that reached the delivery pipeline.failures: errors hit while processing.status:CREATED,PROCESSING,COMPLETED, orERROR.
COMPLETED and ERROR are both terminal.Watch for either, or a failed job leaves you polling forever.
Verify
1
Confirm the counts line up
Poll the job until it reaches
COMPLETED, then check that enqueued matches received and failures is zero.2
Spot-check a recipient
Page through the job’s users with
client.bulk.listUsers. Leave cursor off the first request, then keep passing paging.cursor back while paging.more is true. Each entry carries a recipient, a status of PENDING, ENQUEUED, or ERROR, and a messageId once enqueued.3
Trace one message end to end
A
messageId is the same ID a regular send returns, so look one up in and confirm it delivered.message:updated, which fires on every status change for every message the job produced.