Contacts & Profile
Create and import contacts with a WhatsApp channel for broadcasts, and read or update the WhatsApp business profile.
When you finish this page you have contacts with a WhatsApp channel that broadcasts can target by tag, and the business profile customers see is up to date. You need a connected WhatsApp account, its accountId and its profileId. A contact is a person in your CRM; the channel on it is the phone number Zernio messages through your WhatsApp account.
Step 1: Create a contact
Call POST /v1/contacts with profileId and name. Add accountId, platform: "whatsapp" and platformIdentifier (the phone in E.164) together to create the WhatsApp channel in the same request; the three are all-or-nothing.
import Zernio from '@zernio/node';
const zernio = new Zernio();
const profileId = '66a1f0c2a4b9d3e8f1a2b3c4';
const accountId = '66b2e19d8c3f5a7e9d0b1c2d';
const { data: created } = await zernio.contacts.createContact({
body: {
profileId,
name: 'Ana Costa',
email: 'ana@example.com',
tags: ['vip', 'newsletter'],
accountId,
platform: 'whatsapp',
platformIdentifier: '+13105551234'
}
});
const contactId = created.contact.id;Response (200):
{
"success": true,
"contact": {
"id": "66e5b2c3d4f5a6b7c8d9e0f1",
"name": "Ana Costa",
"email": "ana@example.com",
"tags": ["vip", "newsletter"],
"isSubscribed": true,
"isBlocked": false,
"createdAt": "2027-01-01T09:00:00Z"
},
"channel": {
"id": "66e5b2c3d4f5a6b7c8d9e0f9",
"platform": "whatsapp",
"platformIdentifier": "13105551234"
}
}contact.id is the id broadcasts take in contactIds.
Step 2: Import contacts in bulk
Call POST /v1/contacts/bulk with up to 1,000 contacts. With accountId set, every row needs a platformIdentifier; on WhatsApp it is normalized to digits, and a value that is not phone-shaped is rejected per row in errors[] rather than failing the import. Duplicates are skipped and their new tags merged onto the existing contact.
const { data: imported } = await zernio.contacts.bulkCreateContacts({
body: {
profileId,
accountId,
contacts: [
{ name: 'Ana Costa', platformIdentifier: '+13105551234', tags: ['vip'] },
{ name: 'Ben Okafor', platformIdentifier: '+442071234567', tags: ['newsletter'] }
]
}
});
console.log(imported.created, imported.skipped, imported.errors);Response (200):
{
"success": true,
"created": 1,
"skipped": 1,
"errors": [],
"total": 2
}Ana was skipped because Step 1 already created her; her vip tag was already there.
Step 3: Update a contact
Call PATCH /v1/contacts/{contactId} with the fields to change. Only the fields you send are written. isSubscribed: false drops the contact from segment-targeted broadcasts.
const { data: updated } = await zernio.contacts.updateContact({
path: { contactId },
body: { tags: ['vip', 'promo-2027'], isSubscribed: true }
});
console.log(updated.contact.tags);Response (200):
{
"success": true,
"contact": {
"id": "66e5b2c3d4f5a6b7c8d9e0f1",
"name": "Ana Costa",
"tags": ["vip", "promo-2027"],
"isSubscribed": true,
"isBlocked": false,
"updatedAt": "2027-01-01T09:05:00Z"
}
}Business profile
The business profile is what customers see when they open your number in WhatsApp. Read it with GET /v1/whatsapp/business-profile and change it with POST /v1/whatsapp/business-profile; only the fields you send are updated. about is at most 139 characters, description at most 512, and websites holds at most 2 entries.
const { data: profile } = await zernio.whatsapp.getWhatsAppBusinessProfile({
query: { accountId }
});
console.log(profile.businessProfile.about);
await zernio.whatsapp.updateWhatsAppBusinessProfile({
body: {
accountId,
about: 'Widgets, shipped the same day',
description: 'Acme sells widgets to workshops in 40 countries.',
email: 'hello@example.com',
websites: ['https://example.com']
}
});Response (200), the read:
{
"success": true,
"businessProfile": {
"about": "Widgets, shipped the same day",
"address": "1 Main St, Springfield",
"description": "Acme sells widgets to workshops in 40 countries.",
"email": "hello@example.com",
"profilePictureUrl": "https://...",
"websites": ["https://example.com"],
"vertical": "RETAIL"
}
}Response (200), the update:
{
"success": true,
"message": "Business profile updated successfully"
}The profile picture, display name and WhatsApp username have their own endpoints under Business profile; on a coexistence number the picture is locked and managed in the WhatsApp Business app.
If it fails
A 409 from Step 1 means the phone number is already a channel on this account:
{
"error": "Duplicate channel. The platformIdentifier is already bound to a channel on this accountId."
}Look the contact up with List contacts and update it instead, or use the bulk import, which skips duplicates rather than rejecting them. A 400 with code missing_required_field means accountId, platform and platformIdentifier were not sent together. Every error uses the envelope in error handling.
Related
- Broadcasts: target these contacts by phone, id or tag.
- Contacts API: list, get, delete, channels and custom fields.
- Business profile API: photo, display name and username.
- WhatsApp inbox: the conversations these contacts appear in.