Documentation Index Fetch the complete documentation index at: https://docs.zavu.dev/llms.txt
Use this file to discover all available pages before exploring further.
Add contacts to your broadcast before sending. Contacts can include personalization variables for customized messages.
TypeScript
Python
Ruby
Go
PHP
cURL
const result = await zavu . broadcasts . addContacts ( broadcast . id , {
contacts: [
{ recipient: "+14155551234" },
{ recipient: "+14155555678" },
{ recipient: "+14155559012" },
],
});
console . log ( `Added: ${ result . added } ` );
console . log ( `Duplicates: ${ result . duplicates } ` );
console . log ( `Invalid: ${ result . invalid } ` );
Response
{
"added" : 3 ,
"duplicates" : 0 ,
"invalid" : 0 ,
"errors" : []
}
With Personalization
Add template variables for each contact to personalize messages:
await zavu . broadcasts . addContacts ( broadcast . id , {
contacts: [
{
recipient: "+14155551234" ,
templateVariables: {
name: "John Smith" ,
order_id: "ORD-12345" ,
delivery_date: "January 20th" ,
},
},
{
recipient: "+14155555678" ,
templateVariables: {
name: "Jane Doe" ,
order_id: "ORD-12346" ,
delivery_date: "January 21st" ,
},
},
],
});
The message template Hi {{name}}, your order #{{order_id}} arrives {{delivery_date}}! becomes:
John: “Hi John Smith, your order #ORD-12345 arrives January 20th!”
Jane: “Hi Jane Doe, your order #ORD-12346 arrives January 21st!”
If the template has a dynamic URL button (e.g., https://example.com/orders/{{1}}), supply each contact’s value via templateButtonVariables. Keys are the button index in the template’s buttons array ("0", "1", "2").
await zavu . broadcasts . addContacts ( broadcast . id , {
contacts: [
{
recipient: "+14155551234" ,
templateVariables: { "1" : "John Smith" },
templateButtonVariables: { "0" : "ORD-12345" },
},
{
recipient: "+14155555678" ,
templateVariables: { "1" : "Jane Doe" },
templateButtonVariables: { "0" : "ORD-12346" },
},
],
});
When a contact omits templateButtonVariables, the broadcast falls back to the defaults defined on the broadcast itself.
Batch Processing
Add contacts in batches of up to 1,000 per request. For larger lists, make multiple requests:
const BATCH_SIZE = 1000 ;
async function addAllContacts ( broadcastId : string , allContacts : Contact []) {
let totalAdded = 0 ;
for ( let i = 0 ; i < allContacts . length ; i += BATCH_SIZE ) {
const batch = allContacts . slice ( i , i + BATCH_SIZE );
const result = await zavu . broadcasts . addContacts ( broadcastId , {
contacts: batch . map ( c => ({
recipient: c . phone ,
templateVariables: { name: c . name },
})),
});
totalAdded += result . added ;
console . log ( `Batch ${ Math . floor ( i / BATCH_SIZE ) + 1 } : Added ${ result . added } contacts` );
}
return totalAdded ;
}
Channel Format Example SMS E.164 phone +14155551234WhatsApp E.164 phone +14155551234Email Email address user@example.com
Phone numbers must be in E.164 format (starting with + and country code). Invalid formats will be rejected.
Handling Duplicates
The API automatically deduplicates contacts:
Within request : If the same recipient appears twice in one request, only one is added
Across requests : If a recipient is already in the broadcast, they won’t be added again
{
"added" : 8 ,
"duplicates" : 2 ,
"invalid" : 0 ,
"errors" : []
}
Invalid contacts are rejected with detailed errors:
{
"added" : 7 ,
"duplicates" : 0 ,
"invalid" : 3 ,
"errors" : [
{ "recipient" : "invalid-phone" , "reason" : "Invalid phone number format" },
{ "recipient" : "+1234" , "reason" : "Phone number too short" },
{ "recipient" : "not-an-email" , "reason" : "Invalid email format" }
]
}
Validate phone numbers before adding them to avoid high rejection rates. Use E.164 format: +[country code][number] with no spaces or dashes.
View contacts in a broadcast:
TypeScript
Python
Ruby
Go
PHP
cURL
const contacts = await zavu . broadcasts . listContacts ( broadcast . id , {
limit: 50 ,
});
for ( const contact of contacts . items ) {
console . log ( ` ${ contact . recipient } : ${ contact . status } ` );
}
// Paginate through all contacts
if ( contacts . nextCursor ) {
const nextPage = await zavu . broadcasts . listContacts ( broadcast . id , {
cursor: contacts . nextCursor ,
});
}
Response
{
"items" : [
{
"id" : "bc_abc123" ,
"recipient" : "+14155551234" ,
"recipientType" : "phone" ,
"status" : "pending" ,
"templateVariables" : { "name" : "John" },
"createdAt" : "2024-01-15T10:30:00.000Z"
},
{
"id" : "bc_def456" ,
"recipient" : "+14155555678" ,
"recipientType" : "phone" ,
"status" : "pending" ,
"templateVariables" : { "name" : "Jane" },
"createdAt" : "2024-01-15T10:30:00.000Z"
}
],
"nextCursor" : "eyJpZCI6ImJjX2RlZjQ1NiJ9"
}
Filtering by Status
Filter contacts by delivery status:
curl "https://api.zavu.dev/v1/broadcasts/{broadcastId}/contacts?status=failed" \
-H "Authorization: Bearer $ZAVU_API_KEY "
Status Description pendingNot yet sent queuedMessage created, waiting to send sendingCurrently being sent deliveredSuccessfully delivered failedDelivery failed skippedSkipped (broadcast cancelled)
Remove a contact before the broadcast is sent:
await zavu . broadcasts . removeContact ( broadcast . id , contact . id );
Contacts can only be removed while the broadcast is in draft status. Once sending begins, contacts cannot be removed.
Limits
Limit Value Notes Contacts per request 1,000 Make multiple requests for larger lists Contacts per broadcast 1,000 (default) Contact support to increase this limit Template variable size 1,024 chars Per variable
Next Steps
Sending & Scheduling Send your broadcast or schedule it for later