Batches
Broadcast one template to a list of recipients over a dedicated queue.
Create a batch
Request body
| Field | Type | Notes |
|---|---|---|
| No fields. | ||
Response
| Field | Type | Notes |
|---|---|---|
idrequired | string | |
objectrequired | "message_batch" | |
statusrequired | "pending" | "enqueuing" | "sending" | "paused" | "completed" | "failed" | "cancelled" | |
environmentrequired | "sandbox" | "production" | |
namerequired | string | null | |
template_namerequired | string | null | |
recipient_countrequired | integer | range 0..9007199254740991 |
pacingrequired | object | null | Accept-time forecast of how this batch will be paced against WhatsApp’s daily NEW-recipient allowance for the sending number. Returned on the create response. Null means "no estimate", never "no pacing" — either the forecast could not be made (the sending number could not be resolved, or its allowance is not a finite number to divide by, or the number has no finite cap at all), or you are reading the batch back later: the forecast is an accept-time snapshot that Tyxter neither stores nor recomputes, so retrieve and list always report null here. For live progress read enqueued_count / sent_count, and for the per-message reason read status_reason on the batch’s messages. |
enqueued_countrequired | integer | range 0..9007199254740991 |
sent_countrequired | integer | range 0..9007199254740991 |
failed_countrequired | integer | range 0..9007199254740991 |
error_messagerequired | string | null | |
trace_idrequired | string | |
scheduled_forrequired | string<ISO-8601> | null | |
started_atrequired | string<ISO-8601> | null | |
completed_atrequired | string<ISO-8601> | null | |
created_atrequired | string<ISO-8601> | pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z|([+-](?:[01]\d|2[0-3]):[0-5]\d)))$ |
updated_atrequired | string<ISO-8601> | pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z|([+-](?:[01]\d|2[0-3]):[0-5]\d)))$ |
Before a batch is accepted, Tyxter resolves the approved template version. Inline recipient variablescan satisfy modeled BODY values in the approved version's format: exact numeric keys for POSITIONAL or exact parameter-name keys for NAMED. Shared template.header_media can satisfy a modeled media header. A required text-HEADER or dynamic URL-button parameter has no batch request source, so it returns 400 template_param_mismatch with param: template. The audience and audience_id shapes have no per-recipient variable source in either format and likewise cannot supply BODY, text-HEADER, or dynamic URL-button parameters, although shared template.header_media remains available for a modeled media header. A mismatch returns 400 template_param_mismatch with a corrective param such as recipients.0.variables, template.header_media, or template. No batch was accepted, billed, queued, or sent to Meta. A later approval change or unmodeled Meta behavior can still fail an accepted recipient asynchronously with the same code.
The create response carries a pacingforecast when Tyxter can make one: how many recipients are expected to wait for WhatsApp’s daily NEW-recipient allowance on the sending number, and roughly how many daily windows the batch will span. A batch spanning more than one window is normal and not an error — the waiting recipients stay queued and send by themselves as allowance frees up. Both numbers are estimates: they move as other traffic on the same number consumes allowance, and recipients already inside an open conversation window cost nothing against it.
Retrieve a batch
Response
| Field | Type | Notes |
|---|---|---|
idrequired | string | |
objectrequired | "message_batch" | |
statusrequired | "pending" | "enqueuing" | "sending" | "paused" | "completed" | "failed" | "cancelled" | |
environmentrequired | "sandbox" | "production" | |
namerequired | string | null | |
template_namerequired | string | null | |
recipient_countrequired | integer | range 0..9007199254740991 |
pacingrequired | object | null | Accept-time forecast of how this batch will be paced against WhatsApp’s daily NEW-recipient allowance for the sending number. Returned on the create response. Null means "no estimate", never "no pacing" — either the forecast could not be made (the sending number could not be resolved, or its allowance is not a finite number to divide by, or the number has no finite cap at all), or you are reading the batch back later: the forecast is an accept-time snapshot that Tyxter neither stores nor recomputes, so retrieve and list always report null here. For live progress read enqueued_count / sent_count, and for the per-message reason read status_reason on the batch’s messages. |
enqueued_countrequired | integer | range 0..9007199254740991 |
sent_countrequired | integer | range 0..9007199254740991 |
failed_countrequired | integer | range 0..9007199254740991 |
error_messagerequired | string | null | |
trace_idrequired | string | |
scheduled_forrequired | string<ISO-8601> | null | |
started_atrequired | string<ISO-8601> | null | |
completed_atrequired | string<ISO-8601> | null | |
created_atrequired | string<ISO-8601> | pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z|([+-](?:[01]\d|2[0-3]):[0-5]\d)))$ |
updated_atrequired | string<ISO-8601> | pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z|([+-](?:[01]\d|2[0-3]):[0-5]\d)))$ |
pacing is always null here. The forecast is an accept-time snapshot that Tyxter neither stores nor recomputes, so read it from the create response. For live progress use enqueued_count and sent_count; for the per-message reason use status_reasonon the batch’s messages.
List batches
Response
| Field | Type | Notes |
|---|---|---|
objectrequired | "list" | |
datarequired | object[] | |
has_morerequired | boolean | |
next_cursorrequired | string | null |
Control a batch
Response
| Field | Type | Notes |
|---|---|---|
idrequired | string | |
objectrequired | "message_batch" | |
statusrequired | "pending" | "enqueuing" | "sending" | "paused" | "completed" | "failed" | "cancelled" | |
environmentrequired | "sandbox" | "production" | |
namerequired | string | null | |
template_namerequired | string | null | |
recipient_countrequired | integer | range 0..9007199254740991 |
pacingrequired | object | null | Accept-time forecast of how this batch will be paced against WhatsApp’s daily NEW-recipient allowance for the sending number. Returned on the create response. Null means "no estimate", never "no pacing" — either the forecast could not be made (the sending number could not be resolved, or its allowance is not a finite number to divide by, or the number has no finite cap at all), or you are reading the batch back later: the forecast is an accept-time snapshot that Tyxter neither stores nor recomputes, so retrieve and list always report null here. For live progress read enqueued_count / sent_count, and for the per-message reason read status_reason on the batch’s messages. |
enqueued_countrequired | integer | range 0..9007199254740991 |
sent_countrequired | integer | range 0..9007199254740991 |
failed_countrequired | integer | range 0..9007199254740991 |
error_messagerequired | string | null | |
trace_idrequired | string | |
scheduled_forrequired | string<ISO-8601> | null | |
started_atrequired | string<ISO-8601> | null | |
completed_atrequired | string<ISO-8601> | null | |
created_atrequired | string<ISO-8601> | pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z|([+-](?:[01]\d|2[0-3]):[0-5]\d)))$ |
updated_atrequired | string<ISO-8601> | pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z|([+-](?:[01]\d|2[0-3]):[0-5]\d)))$ |
Export failures
Response
| Field | Type | Notes |
|---|---|---|
objectrequired | "message_batch_failure_export" | |
batch_idrequired | string | |
generated_atrequired | string<ISO-8601> | pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z|([+-](?:[01]\d|2[0-3]):[0-5]\d)))$ |
rowsrequired | object[] |