contacts-management

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Contacts Management

联系人管理

When to Use

适用场景

Use this skill when building code to create, update, or manage contacts and their communication channels. Covers the multi-channel contact model, merge operations, and phone number introspection.
当你需要编写代码来创建、更新或管理联系人及其沟通渠道时,可使用此技能。涵盖多渠道联系人模型、合并操作以及电话号码检测功能。

Contact Model

联系人模型

Contacts are multi-channel: one contact can have multiple channels (SMS, WhatsApp, Email, Telegram, Voice), each with its own identifier and delivery metrics. Top-level fields expose primary identifiers for quick access.
Contact (John Doe)
├── primaryPhone: +14155551234           (E.164)
├── primaryEmail: john@example.com
├── profileName: "John D."               (WhatsApp profile name, if available)
├── verified: true
├── countryCode: "US"
└── Channels:
    ├── SMS: +14155551234 (primary)
    ├── WhatsApp: +14155551234 (primary)
    ├── Email: john@example.com (primary)
    ├── Email: john.work@company.com (label: "work")
    ├── Telegram: @johndoe
    └── Voice: +14155551234
Note: The legacy
phoneNumber
field on Contact is deprecated — use
primaryPhone
instead.
Valid contact channel types:
sms
,
whatsapp
,
email
,
telegram
,
voice
(note:
instagram
,
auto
,
sms_oneway
are message-send channels, not contact channel types).
联系人支持多渠道:一个联系人可拥有多个渠道(SMS、WhatsApp、Email、Telegram、Voice),每个渠道都有自己的标识和交付指标。顶层字段提供主标识以便快速访问。
Contact (John Doe)
├── primaryPhone: +14155551234           (E.164)
├── primaryEmail: john@example.com
├── profileName: "John D."               (WhatsApp profile name, if available)
├── verified: true
├── countryCode: "US"
└── Channels:
    ├── SMS: +14155551234 (primary)
    ├── WhatsApp: +14155551234 (primary)
    ├── Email: john@example.com (primary)
    ├── Email: john.work@company.com (label: "work")
    ├── Telegram: @johndoe
    └── Voice: +14155551234
注意: Contact中的旧字段
phoneNumber
已被弃用,请改用
primaryPhone
有效的联系人渠道类型:
sms
whatsapp
email
telegram
voice
(注意:
instagram
auto
sms_oneway
是消息发送渠道,不属于联系人渠道类型)。

Auto-Creation

自动创建

Contacts are automatically created when you send a message to a new recipient. No explicit creation needed for basic messaging.
当你向新收件人发送消息时,联系人会自动创建。基础消息发送无需显式创建联系人。

Create Contact

创建联系人

typescript
const contact = await zavu.contacts.create({
  displayName: "John Doe",
  channels: [
    { channel: "sms", identifier: "+14155551234", isPrimary: true },
    { channel: "whatsapp", identifier: "+14155551234", isPrimary: true },
    { channel: "email", identifier: "john@example.com", isPrimary: true },
  ],
  metadata: { source: "import", plan: "enterprise" },
});
console.log(contact.id);
Python:
python
contact = zavu.contacts.create(
    display_name="John Doe",
    channels=[
        {"channel": "sms", "identifier": "+14155551234", "isPrimary": True},
        {"channel": "email", "identifier": "john@example.com", "isPrimary": True},
    ],
)
Go:
go
contact, err := client.Contacts.Create(context.TODO(), zavudev.ContactCreateParams{
    DisplayName: zavudev.String("John Doe"),
    Channels: []zavudev.ContactChannelParam{
        {Channel: "sms", Identifier: "+14155551234", IsPrimary: zavudev.Bool(true)},
        {Channel: "email", Identifier: "john@example.com", IsPrimary: zavudev.Bool(true)},
    },
})
Ruby:
ruby
contact = client.contacts.create(
    display_name: "John Doe",
    channels: [
        { channel: "sms", identifier: "+14155551234", is_primary: true },
        { channel: "email", identifier: "john@example.com", is_primary: true },
    ],
)
PHP:
php
$contact = $client->contacts->create([
    'displayName' => 'John Doe',
    'channels' => [
        ['channel' => 'sms', 'identifier' => '+14155551234', 'isPrimary' => true],
        ['channel' => 'email', 'identifier' => 'john@example.com', 'isPrimary' => true],
    ],
]);
typescript
const contact = await zavu.contacts.create({
  displayName: "John Doe",
  channels: [
    { channel: "sms", identifier: "+14155551234", isPrimary: true },
    { channel: "whatsapp", identifier: "+14155551234", isPrimary: true },
    { channel: "email", identifier: "john@example.com", isPrimary: true },
  ],
  metadata: { source: "import", plan: "enterprise" },
});
console.log(contact.id);
Python:
python
contact = zavu.contacts.create(
    display_name="John Doe",
    channels=[
        {"channel": "sms", "identifier": "+14155551234", "isPrimary": True},
        {"channel": "email", "identifier": "john@example.com", "isPrimary": True},
    ],
)
Go:
go
contact, err := client.Contacts.Create(context.TODO(), zavudev.ContactCreateParams{
    DisplayName: zavudev.String("John Doe"),
    Channels: []zavudev.ContactChannelParam{
        {Channel: "sms", Identifier: "+14155551234", IsPrimary: zavudev.Bool(true)},
        {Channel: "email", Identifier: "john@example.com", IsPrimary: zavudev.Bool(true)},
    },
})
Ruby:
ruby
contact = client.contacts.create(
    display_name: "John Doe",
    channels: [
        { channel: "sms", identifier: "+14155551234", is_primary: true },
        { channel: "email", identifier: "john@example.com", is_primary: true },
    ],
)
PHP:
php
$contact = $client->contacts->create([
    'displayName' => 'John Doe',
    'channels' => [
        ['channel' => 'sms', 'identifier' => '+14155551234', 'isPrimary' => true],
        ['channel' => 'email', 'identifier' => 'john@example.com', 'isPrimary' => true],
    ],
]);

Get & List Contacts

获取与列出联系人

typescript
// Get by ID
const contact = await zavu.contacts.get({ contactId: "ct_abc123" });

// Get by phone number
const contact = await zavu.contacts.getByPhone({
  phoneNumber: "+14155551234",
});

// List with filters
let cursor: string | undefined;
do {
  const result = await zavu.contacts.list({
    phoneNumber: "+14155551234",
    limit: 50,
    cursor,
  });
  for (const contact of result.items) {
    console.log(contact.id, contact.displayName, contact.availableChannels);
  }
  cursor = result.nextCursor ?? undefined;
} while (cursor);
typescript
// Get by ID
const contact = await zavu.contacts.get({ contactId: "ct_abc123" });

// Get by phone number
const contact = await zavu.contacts.getByPhone({
  phoneNumber: "+14155551234",
});

// List with filters
let cursor: string | undefined;
do {
  const result = await zavu.contacts.list({
    phoneNumber: "+14155551234",
    limit: 50,
    cursor,
  });
  for (const contact of result.items) {
    console.log(contact.id, contact.displayName, contact.availableChannels);
  }
  cursor = result.nextCursor ?? undefined;
} while (cursor);

Channel Operations

渠道操作

typescript
// Add channel
const channel = await zavu.contacts.channels.add({
  contactId: "ct_abc123",
  channel: "email",
  identifier: "john.work@company.com",
  label: "work",       // optional
  countryCode: "US",   // optional, 2-letter ISO
});

// Update channel
await zavu.contacts.channels.update({
  contactId: "ct_abc123",
  channelId: "ch_xyz789",
  label: "personal",
  verified: true,
});

// Set as primary
await zavu.contacts.channels.setPrimary({
  contactId: "ct_abc123",
  channelId: "ch_xyz789",
});

// Remove channel (cannot remove the last channel)
await zavu.contacts.channels.remove({
  contactId: "ct_abc123",
  channelId: "ch_xyz789",
});
typescript
// Add channel
const channel = await zavu.contacts.channels.add({
  contactId: "ct_abc123",
  channel: "email",
  identifier: "john.work@company.com",
  label: "work",       // optional
  countryCode: "US",   // optional, 2-letter ISO
});

// Update channel
await zavu.contacts.channels.update({
  contactId: "ct_abc123",
  channelId: "ch_xyz789",
  label: "personal",
  verified: true,
});

// Set as primary
await zavu.contacts.channels.setPrimary({
  contactId: "ct_abc123",
  channelId: "ch_xyz789",
});

// Remove channel (cannot remove the last channel)
await zavu.contacts.channels.remove({
  contactId: "ct_abc123",
  channelId: "ch_xyz789",
});

Update Contact

更新联系人

typescript
await zavu.contacts.update({
  contactId: "ct_abc123",
  defaultChannel: "whatsapp",
  metadata: { plan: "premium", region: "US" },
});

// Clear default channel
await zavu.contacts.update({
  contactId: "ct_abc123",
  defaultChannel: null,
});
typescript
await zavu.contacts.update({
  contactId: "ct_abc123",
  defaultChannel: "whatsapp",
  metadata: { plan: "premium", region: "US" },
});

// Clear default channel
await zavu.contacts.update({
  contactId: "ct_abc123",
  defaultChannel: null,
});

Merge Contacts

合并联系人

When duplicate contacts are detected, the API suggests merges:
typescript
// Check for merge suggestion
const contact = await zavu.contacts.get({ contactId: "ct_abc123" });
if (contact.suggestedMergeWith) {
  // Merge source into target (all channels move to target)
  const merged = await zavu.contacts.merge({
    contactId: "ct_abc123",
    sourceContactId: contact.suggestedMergeWith,
  });
  console.log("Merged channels:", merged.channels.length);
}

// Dismiss suggestion
await zavu.contacts.mergeSuggestion.dismiss({
  contactId: "ct_abc123",
});
当检测到重复联系人时,API会给出合并建议:
typescript
// Check for merge suggestion
const contact = await zavu.contacts.get({ contactId: "ct_abc123" });
if (contact.suggestedMergeWith) {
  // Merge source into target (all channels move to target)
  const merged = await zavu.contacts.merge({
    contactId: "ct_abc123",
    sourceContactId: contact.suggestedMergeWith,
  });
  console.log("Merged channels:", merged.channels.length);
}

// Dismiss suggestion
await zavu.contacts.mergeSuggestion.dismiss({
  contactId: "ct_abc123",
});

Phone Introspection

号码检测

Validate phone numbers and check carrier info:
typescript
const result = await zavu.introspect.phone({
  phoneNumber: "+14155551234",
});
console.log(result.validNumber);      // true
console.log(result.countryCode);       // "US"
console.log(result.nationalFormat);    // "(415) 555-1234"
console.log(result.lineType);         // "mobile" | "landline" | "voip" | "toll_free"
console.log(result.carrier?.name);    // "Verizon Wireless"
console.log(result.availableChannels); // ["sms", "whatsapp", "voice"]
Python:
python
result = zavu.introspect.phone(phone_number="+14155551234")
print(result.valid_number)
print(result.line_type)
print(result.carrier.name if result.carrier else "Unknown")
Go:
go
result, err := client.Introspect.Phone(context.TODO(), zavudev.PhoneIntrospectionParams{
    PhoneNumber: zavudev.String("+14155551234"),
})
fmt.Println(result.ValidNumber, result.LineType, result.Carrier.Name)
Ruby:
ruby
result = client.introspect.phone(phone_number: "+14155551234")
puts result.valid_number, result.line_type, result.carrier&.name
PHP:
php
$result = $client->introspect->phone(['phoneNumber' => '+14155551234']);
echo $result->validNumber, $result->lineType, $result->carrier?->name;
验证电话号码并检查运营商信息:
typescript
const result = await zavu.introspect.phone({
  phoneNumber: "+14155551234",
});
console.log(result.validNumber);      // true
console.log(result.countryCode);       // "US"
console.log(result.nationalFormat);    // "(415) 555-1234"
console.log(result.lineType);         // "mobile" | "landline" | "voip" | "toll_free"
console.log(result.carrier?.name);    // "Verizon Wireless"
console.log(result.availableChannels); // ["sms", "whatsapp", "voice"]
Python:
python
result = zavu.introspect.phone(phone_number="+14155551234")
print(result.valid_number)
print(result.line_type)
print(result.carrier.name if result.carrier else "Unknown")
Go:
go
result, err := client.Introspect.Phone(context.TODO(), zavudev.PhoneIntrospectionParams{
    PhoneNumber: zavudev.String("+14155551234"),
})
fmt.Println(result.ValidNumber, result.LineType, result.Carrier.Name)
Ruby:
ruby
result = client.introspect.phone(phone_number: "+14155551234")
puts result.valid_number, result.line_type, result.carrier&.name
PHP:
php
$result = $client->introspect->phone(['phoneNumber' => '+14155551234']);
echo $result->validNumber, $result->lineType, $result->carrier?->name;

Constraints

限制条件

  • Max 20 channels per contact
  • Channel labels: max 50 characters
  • Display name: max 200 characters
  • Cannot remove the last channel from a contact
  • Cannot merge a contact with itself
  • Phone numbers must be E.164 format
  • Duplicate identifiers across contacts are rejected (use merge instead)
  • 每个联系人最多支持20个渠道
  • 渠道标签:最多50个字符
  • 显示名称:最多200个字符
  • 无法删除联系人的最后一个渠道
  • 无法将联系人与自身合并
  • 电话号码必须为E.164格式
  • 拒绝跨联系人的重复标识(请使用合并功能)