Send Bulk Messages
Send a message to every lead in a stored audience via WhatsApp or email. The tool iterates through all pages of the audience, sends the message to each lead, and tracks individual delivery status.
Leads missing the required contact field (phone for WhatsApp, email for email) are automatically skipped. Already-sent leads are not re-sent, so the tool is safe to retry.
Input Schema
| Parameter | Type | Required | Description |
|---|---|---|---|
| audience_id | string | Yes | Audience UUID to send messages to. |
| channel | string | Yes | Delivery channel. Enum: whatsapp, email |
| message | string | Yes | Message text (plain text or HTML for email). |
| subject | string | Email subject (required when channel is email). | |
| from | string | No | Sender display name. |
| audience_email_mode | string | No | Email only: mail (default) or newsletter (immediate send, open/click tracking, no HTML signature). |
| content_id | string | No | Optional content UUID. Reads metadata.placeholders.when_unresolved unless placeholder_policy is set. |
| placeholder_policy | string | No | strip_tokens (default) or skip_recipient for unknown {{...}} tokens. |
Merge fields / placeholders
Use double braces only: {{lead.name}}, {{lead.first_name}}, {{lead.email}}, {{lead.phone}}, {{lead.position}}, {{lead.company}}, {{lead.notes}}, {{lead.metadata.<path>}}, {{site.name}}. The engine normalizes common aliases (e.g. {{lead.full_name}}, {{lead.correo}}). Do not use [Name] or {name}.
- mail mode (email): subject and body are personalized per lead before queuing.
- newsletter mode (email): same personalization; emails are sent without the usual agent HTML signature.
- WhatsApp: the tool creates (or reuses) a single Twilio Content Template per campaign whose body carries numeric placeholders (
{{1}},{{2}}, …) mapped from your merge tokens. Each lead is queued with its ownContentVariables, so one approved template serves the whole audience — you do NOT need one template per recipient. The response includestemplate_sid,template_status, andplaceholder_map.
MCP Usage
Available as the sendBulkMessages tool via the MCP JSON-RPC endpoint.
WhatsApp example:
{
"method": "tools/call",
"params": {
"name": "sendBulkMessages",
"arguments": {
"audience_id": "AUDIENCE_UUID",
"channel": "whatsapp",
"message": "Hi! We have a special offer for you this week."
}
}
}Email example:
{
"method": "tools/call",
"params": {
"name": "sendBulkMessages",
"arguments": {
"audience_id": "AUDIENCE_UUID",
"channel": "email",
"subject": "Special Offer This Week",
"message": "<h1>Hello!</h1><p>We have a special offer for you.</p>",
"from": "Marketing Team"
}
}
}Response:
{
"success": true,
"audience_id": "...",
"channel": "whatsapp",
"template_sid": "HX...",
"template_status": "pending",
"placeholder_map": ["lead.first_name", "site.name"],
"total_sent": 120,
"total_failed": 5,
"total_skipped": 25,
"total_remaining": 0,
"total_in_audience": 150
}For the WhatsApp path, template_sid is the single Twilio Content Template used for the campaign, placeholder_map lists the canonical merge tokens in the order they map to {{1}}, {{2}}, …, and template_status is either approved (template reused) or pending (freshly created — the delivery worker re-checks before sending).
Workflow
- First create an audience using the
audiencetool. - Optionally review the audience leads with
audiencegetaction. - Call
sendBulkMessageswith theaudience_idand desired channel. - Check the response summary for delivery results.
- If some messages failed, you can re-run the tool — only
pendingleads will be retried.
Status Tracking
Each lead in the audience has a send_status:
| Status | Meaning |
|---|---|
pending | Not yet attempted |
sent | Message delivered successfully |
failed | Send attempt failed (error stored) |
skipped | Lead missing required contact field |