Skip to main content
POST /v1/messages/send-bulk-template sends an approved WhatsApp template to a list of contacts at once. Because they’re templates, these sends work outside the 24-hour window: that’s the way to start a conversation with someone who hasn’t talked to you recently. Scope: messages:create.
The template must be approved on Meta beforehand. This call triggers an existing template; it doesn’t create or submit templates for approval.

Request fields

phone needs the country code, with no symbols: 5511999999999. name can’t be empty.

Send to a list of contacts

cURL
For large lists, send a file instead of the array: multipart/form-data with the CSV or XLSX in the file field and the remaining fields in the form. The file needs the name and phone columns:
Combining a file with dynamic components parameters is a case worth testing with a few contacts before using it in production. If the parameters aren’t applied as expected, contact support.

Template parameters

An approved template has placeholders ({{1}}, {{2}}) and blocks: header, body, and buttons. You fill this in via components, and the number and type of parameters must match exactly with the approved template, otherwise Meta rejects the send. Parameter types:
Image, video, and document go in the header via a public HTTPS URL. You don’t need to upload a file or prepare anything beforehand. The URL just needs to be reachable by Meta.

Examples by template type

Template: image header + Hello {{1}}! Check out our {{2}} sale.
Template: Your order #{{1}} has been confirmed. + a button pointing to .../track/{{1}}.The button’s index is a string and starts at "0":
Template: document header + Hello {{1}}, here's your invoice.
Template: Your {{1}} invoice for {{2}} is due on {{3}}.
The final formatting (R$ 150.50, 01/31/2026) is done by WhatsApp, based on the recipient’s device language.
Carousel templates aren’t accepted on this endpoint. Use the individual template send instead.

The response is partial

Processing is synchronous and an error on one contact doesn’t stop the others. The response carries the consolidated result:
A 200 does not mean everyone received it. Always read errorCount and errors. If you ignore this block, send failures go unnoticed. row points to the file’s row or the index in the contacts array.
Resending to those who failed is your integration’s responsibility: there’s no automatic retry.

Limits worth knowing

  • WhatsApp account tier: Meta limits the number of unique conversations started per day (1,000, 10,000, or 100,000, depending on your account’s tier). The send respects this cap: above it, sends start to fail.
  • Media size: image up to 5 MB (JPG, PNG), video up to 16 MB (MP4, 3GPP), document up to 100 MB (PDF, DOC/DOCX, XLS/XLSX, PPT/PPTX, TXT), audio up to 16 MB.
  • Media links: must be public HTTPS URLs, reachable by Meta. A URL behind a login or an internal network fails.
  • Batch size: send in batches of up to 1,000 contacts per request.

Best practices

1

Test with a single contact

Send it to your own number first and check the result on the device. A parameter out of order only shows up in the final message.
2

Normalize phone numbers beforehand

Use the international format with no symbols (5511999999999). An invalid number becomes a row in errors, not an exception.
3

Save the conversationId values

sentContacts returns the conversation created for each contact: that’s how you track the reply, via webhooks or GET /v1/messages/conversation/{id}.
4

Treat errors as a reprocessing queue

Resend only the rows in errors, after fixing the cause.

Next steps

Webhooks

Receive the replies from those reached by the send.

API reference

The full contract for this endpoint and the other sends.