Contacts are automatically created when you send messages. Each contact represents a unique recipient (phone number or email) and stores metadata about their messaging preferences and history.
When you send a message to a new recipient, Zavu automatically:
Creates a contact record
Detects the country from the phone number
Determines available messaging channels
Captures the WhatsApp profile name (if available)
// Sending to a new recipient creates a contact
const message = await zavu . messages . send ({
to: "+14155551234" ,
text: "Welcome!" ,
});
// Contact is now available
const contact = await zavu . contacts . getByPhone ( "+14155551234" );
console . log ( contact . id ); // "con_abc123"
Property Description idUnique contact identifier phoneNumberE.164 formatted phone number countryCodeTwo-letter country code (e.g., “US”) profileNameWhatsApp display name (if available) availableChannelsChannels this contact can receive (sms, whatsapp, etc.) defaultChannelPreferred channel for auto-routing verifiedWhether the contact has been verified metadataCustom key-value data
TypeScript
Python
Ruby
Go
PHP
cURL
import Zavudev from '@zavudev/sdk' ;
const zavu = new Zavudev ();
const contact = await zavu . contacts . get ( "con_abc123" );
console . log ( `Phone: ${ contact . phoneNumber } ` );
console . log ( `Country: ${ contact . countryCode } ` );
console . log ( `Channels: ${ contact . availableChannels . join ( ", " ) } ` );
console . log ( `Profile: ${ contact . profileName || "Unknown" } ` );
Response
{
"id" : "con_abc123" ,
"phoneNumber" : "+14155551234" ,
"countryCode" : "US" ,
"profileName" : "John Doe" ,
"availableChannels" : [ "sms" , "whatsapp" ],
"defaultChannel" : "whatsapp" ,
"verified" : true ,
"metadata" : {
"tier" : "premium" ,
"source" : "website"
},
"createdAt" : "2024-01-15T10:30:00.000Z" ,
"updatedAt" : "2024-01-15T12:00:00.000Z"
}
Look up a contact using their phone number:
TypeScript
Python
Ruby
Go
PHP
cURL
const contact = await zavu . contacts . getByPhone ( "+14155551234" );
if ( contact ) {
console . log ( `Found contact: ${ contact . id } ` );
console . log ( `Available channels: ${ contact . availableChannels } ` );
} else {
console . log ( "Contact not found" );
}
Use this endpoint to check if a recipient already exists before sending messages, or to retrieve their metadata for personalization.
Retrieve all contacts with pagination:
TypeScript
Python
Ruby
Go
PHP
cURL
// List all contacts
const { items , nextCursor } = await zavu . contacts . list ({
limit: 50 ,
});
for ( const contact of items ) {
console . log ( ` ${ contact . id } : ${ contact . phoneNumber } ` );
}
// Paginate through all contacts
let cursor : string | undefined ;
const allContacts = [];
do {
const result = await zavu . contacts . list ({ cursor , limit: 100 });
allContacts . push ( ... result . items );
cursor = result . nextCursor ?? undefined ;
} while ( cursor );
console . log ( `Total contacts: ${ allContacts . length } ` );
Filter by Phone Number
Search for contacts matching a phone number prefix:
// Find all contacts with US country code
const { items } = await zavu . contacts . list ({
phoneNumber: "+1" ,
limit: 50 ,
});
Update a contact’s default channel or metadata:
TypeScript
Python
Ruby
Go
PHP
cURL
const contact = await zavu . contacts . update ( "con_abc123" , {
defaultChannel: "whatsapp" ,
metadata: {
name: "John Doe" ,
tier: "premium" ,
source: "mobile_app" ,
},
});
console . log ( `Updated default channel: ${ contact . defaultChannel } ` );
Updateable Fields
Field Description defaultChannelPreferred channel for smart routing (sms, whatsapp, telegram, email) metadataCustom key-value pairs (merged with existing metadata)
Setting defaultChannel affects smart routing . When you send a message with channel: "auto", Zavu will prefer the contact’s default channel.
Store custom data on contacts for personalization and segmentation:
// Add customer data
await zavu . contacts . update ( "con_abc123" , {
metadata: {
customerId: "cust_12345" ,
plan: "enterprise" ,
signupDate: "2024-01-15" ,
preferredLanguage: "es" ,
},
});
// Use in messages
const contact = await zavu . contacts . get ( "con_abc123" );
const message = await zavu . messages . send ({
to: contact . phoneNumber ,
text: `Hola ${ contact . metadata ?. customerId } ! Your ${ contact . metadata ?. plan } plan is active.` ,
});
Metadata values must be strings. Store complex data as JSON strings if needed.
Available Channels
The availableChannels array indicates which channels can reach this contact:
Channel When Available smsValid mobile or landline number whatsappContact has WhatsApp (detected on first message or reply) telegramContact has connected via Telegram bot emailContact has email address on file
const contact = await zavu . contacts . get ( "con_abc123" );
if ( contact . availableChannels . includes ( "whatsapp" )) {
// Send via WhatsApp for richer experience
await zavu . messages . send ({
to: contact . phoneNumber ,
channel: "whatsapp" ,
text: "Hello via WhatsApp!" ,
});
} else {
// Fall back to SMS
await zavu . messages . send ({
to: contact . phoneNumber ,
channel: "sms" ,
text: "Hello via SMS!" ,
});
}
Phone Number Introspection
Validate a phone number and check available channels without creating a contact:
const result = await zavu . introspect . phone ({
phoneNumber: "+14155551234" ,
});
console . log ( `Valid: ${ result . validNumber } ` );
console . log ( `Country: ${ result . countryCode } ` );
console . log ( `Format: ${ result . nationalFormat } ` );
console . log ( `Type: ${ result . lineType } ` );
console . log ( `Carrier: ${ result . carrier ?. name } ` );
console . log ( `Channels: ${ result . availableChannels } ` );
Response
{
"phoneNumber" : "+14155551234" ,
"countryCode" : "US" ,
"validNumber" : true ,
"nationalFormat" : "(415) 555-1234" ,
"lineType" : "mobile" ,
"carrier" : {
"name" : "Verizon Wireless" ,
"type" : "mobile"
},
"availableChannels" : [ "sms" , "whatsapp" ]
}
Use introspection to validate phone numbers before adding them to broadcasts or CRM systems.
Complete Example
import Zavudev from '@zavudev/sdk' ;
const zavu = new Zavudev ();
async function processNewCustomer ( phone : string , customerData : {
name : string ;
email : string ;
plan : string ;
}) {
// 1. Validate the phone number
const introspection = await zavu . introspect . phone ({ phoneNumber: phone });
if ( ! introspection . validNumber ) {
throw new Error ( "Invalid phone number" );
}
console . log ( `Valid ${ introspection . lineType } number from ${ introspection . countryCode } ` );
// 2. Send welcome message (creates contact automatically)
const message = await zavu . messages . send ({
to: phone ,
channel: "auto" , // Smart routing based on available channels
text: `Welcome ${ customerData . name } ! Your ${ customerData . plan } account is ready.` ,
});
console . log ( `Welcome message sent: ${ message . id } ` );
// 3. Update contact with customer data
const contact = await zavu . contacts . getByPhone ( phone );
await zavu . contacts . update ( contact . id , {
defaultChannel: introspection . availableChannels . includes ( "whatsapp" )
? "whatsapp"
: "sms" ,
metadata: {
name: customerData . name ,
email: customerData . email ,
plan: customerData . plan ,
signupDate: new Date (). toISOString (),
},
});
console . log ( `Contact updated: ${ contact . id } ` );
return contact ;
}
// Usage
processNewCustomer ( "+14155551234" , {
name: "John Doe" ,
email: "john@example.com" ,
plan: "premium" ,
});
Next Steps
Smart Routing Learn how defaultChannel affects message routing
Broadcasts Send messages to many contacts at once
Phone Lookup Validate and lookup phone numbers
Webhooks Receive updates when contacts reply