Skip to main content
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)
// 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"

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.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"
}

Get Contact by Phone Number

Look up a contact using their phone number:
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.

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

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

Contact Metadata

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