Skip to content

Contacts

Manage contacts and recipient information

View .md

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.

How Contacts Work

When you send a message to a new recipient, Zavu automatically:

  1. Creates a contact record
  2. Detects the country from the phone number
  3. Determines available messaging channels
  4. Captures the WhatsApp profile name (if available)
TypeScript
// 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.retrieveByPhone("+14155551234"); console.log(contact.id); // "con_abc123"

Contact Properties

PropertyDescription
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

Get Contact by ID

import Zavudev from '@zavudev/sdk'; const zavu = new Zavudev(); const contact = await zavu.contacts.retrieve("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

JSON
{ "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" }

Get Contact by Phone Number

Look up a contact using their phone number:

const contact = await zavu.contacts.retrieveByPhone("+14155551234"); if (contact) { console.log(`Found contact: ${contact.id}`); console.log(`Available channels: ${contact.availableChannels}`); } else { console.log("Contact not found"); }

List Contacts

Retrieve all contacts with pagination:

// 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

phoneNumber is an exact match on the contact's primary phone number, in E.164. It is not a prefix filter — use search for partial matches.

TypeScript
const { items } = await zavu.contacts.list({ phoneNumber: "+14155551234", });

search matches the contact's name — both displayName and the WhatsApp profile name — as well as its phone numbers and email addresses. It is case- and accent-insensitive, so jose finds "José".

TypeScript
const { items } = await zavu.contacts.list({ search: "marta", limit: 25 });

A phone number also matches on a trailing fragment, which is how people usually remember them:

TypeScript
// finds +14155551234 const { items } = await zavu.contacts.list({ search: "5551234" });

Filter by Tag

Tags group contacts into an audience you send to more than once. Filter by name:

TypeScript
const { items } = await zavu.contacts.list({ tag: "vip" });

Repeat the parameter to require every tag, not any of them:

terminal
curl "https://api.zavu.dev/v1/contacts?tag=vip&tag=chile" \ -H "Authorization: Bearer $ZAVUDEV_API_KEY"

Update Contact

Update a contact's default channel or metadata:

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

FieldDescription
displayNameThe contact's name. Pass null to clear it and fall back to the identifier.
defaultChannelPreferred channel for smart routing (sms, whatsapp, telegram, email)
metadataCustom key-value pairs (merged with existing metadata)

Contact Metadata

Store custom data on contacts for personalization and segmentation:

TypeScript
// 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.retrieve("con_abc123"); const message = await zavu.messages.send({ to: contact.phoneNumber, text: `Hola ${contact.metadata?.customerId}! Your ${contact.metadata?.plan} plan is active.`, });

Available Channels

The availableChannels array indicates which channels can reach this contact:

ChannelWhen 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
TypeScript
const contact = await zavu.contacts.retrieve("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.validatePhone({ 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

JSON
{ "phoneNumber": "+14155551234", "countryCode": "US", "validNumber": true, "nationalFormat": "(415) 555-1234", "lineType": "mobile", "carrier": { "name": "Verizon Wireless", "type": "mobile" }, "availableChannels": ["sms", "whatsapp"] }

Complete Example

TypeScript
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.validatePhone({ 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.retrieveByPhone(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

API Reference

Manage contacts programmatically: