Create a contact
Create a contact with one or more channels. An identifier another contact already holds on the same channel is refused (400 duplicate_identifier, with details.conflicts[{channel, identifier, contactId}]); update the existing contact with PATCH /v2/contacts/{contactId} instead.
Authorization
AuthorizationheaderrequiredBearer YOUR_API_KEY. Create a key in the dashboard.
Body
application/json
displayNamestringDisplay name for the contact.
Limitsmax length 200channelsobject[]requiredCommunication channels for the contact.
Limitsmin items 1 · max items 205 properties
channelstringrequiredChannel type.
One ofsmswhatsappemailtelegraminstagrammessengervoiceidentifierstringrequiredChannel identifier (phone number in E.164 format or email address).
countryCodestringISO country code for phone numbers.
Limitsmin length 2 · max length 2labelstringOptional label for the channel.
Limitsmax length 50isPrimarybooleanWhether this should be the primary channel for its type.
Defaultfalse
metadataobjectArbitrary metadata to associate with the contact.
1 properties
{key}string
Responses
201Created.
idstringrequireddisplayNamestringDisplay name for the contact.
phoneNumberstringDEPRECATED: Use primaryPhone instead. Primary phone number in E.164 format.
primaryPhonestringPrimary phone number in E.164 format.
primaryEmailstring<email>Primary email address.
countryCodestringprofileNamestringContact's WhatsApp profile name. Only available for WhatsApp contacts.
whatsappobjectWhatsApp identity. Present when Zavu has a business-scoped user ID (BSUID) for the contact, and absent otherwise. A contact with a username can be reached under its BSUID, its phone number, or both; they are the same contact. Look one up by BSUID with the
bsuidquery parameter of the list endpoint.2 properties
bsuidstringrequiredBusiness-scoped user ID. Can be used as
towhen sending.usernamestringThe WhatsApp username, when Meta reported one.
availableChannelsstring[]requiredList of available messaging channels for this contact.
defaultChannelstringPreferred channel for this contact.
One ofsmswhatsapptelegramemailinstagrammessengervoiceverifiedbooleanrequiredWhether this contact has been verified.
channelsobject[]All communication channels for this contact.
12 properties
idstringrequiredchannelstringrequiredChannel type.
One ofsmswhatsappemailtelegraminstagrammessengervoiceidentifierstringrequiredChannel identifier (phone number or email address).
countryCodestringISO country code for phone numbers.
labelstringOptional label for the channel.
isPrimarybooleanrequiredWhether this is the primary channel for its type.
verifiedbooleanrequiredWhether this channel has been verified.
metricsobjectDelivery metrics for this channel.
5 properties
successCountintegerfailureCountintegertotalAttemptsintegeravgDeliveryTimeMsnumberlastSuccessAtstring<date-time>
lastInboundAtstring<date-time>Last time a message was received on this channel.
metadataobject1 properties
{key}string
createdAtstring<date-time>requiredupdatedAtstring<date-time>
metadataobjectrequired1 properties
{key}string
createdAtstring<date-time>requiredupdatedAtstring<date-time>
400Invalid body (`details.errors`), or `duplicate_identifier`: an identifier is already held by another contact (`details.conflicts`). A phone channel (`sms`, `whatsapp`, `voice`) whose identifier is not E.164 is refused with `details.errors[].path` `["channels", i, "identifier"]` (WhatsApp also takes a BSUID). An `email` identifier that is not an email address is refused the same way. Email identifiers are stored lower-case, and one that differs from another contact's only in case is that contact's address: `duplicate_identifier`.
codestringrequiredmessagestringrequireddetailsobjectMachine-readable context. Keys that mean the same thing everywhere: -
errors: present on every400 invalid_requestfor an invalid body or query parameter,[{path, message, ...}],pathnaming the field (["to"],["contacts", 2, "recipient"],["limit"]). -recommendation: one sentence saying what to do next. -dashboardUrl: the dashboard screen that fixes it. -connect: on409 no_channel, the channels this project can connect to reach the recipient, each{type, request, note, available, dashboardUrl?};requestis the exact call (POST /v2/channelswith its body, orPOST /v2/numbers), or null for a channel connected from the dashboard (WhatsApp, Instagram, Messenger).available: falsesays why innote(one-way SMS closed until business verification is approved). -address/from: the address the error is about, under the name the request used for it.1 properties
errorsobject[]3 properties
pathobject[]requiredmessagestringrequiredcodestring
401Unauthorized.
codestringrequiredmessagestringrequireddetailsobjectMachine-readable context. Keys that mean the same thing everywhere: -
errors: present on every400 invalid_requestfor an invalid body or query parameter,[{path, message, ...}],pathnaming the field (["to"],["contacts", 2, "recipient"],["limit"]). -recommendation: one sentence saying what to do next. -dashboardUrl: the dashboard screen that fixes it. -connect: on409 no_channel, the channels this project can connect to reach the recipient, each{type, request, note, available, dashboardUrl?};requestis the exact call (POST /v2/channelswith its body, orPOST /v2/numbers), or null for a channel connected from the dashboard (WhatsApp, Instagram, Messenger).available: falsesays why innote(one-way SMS closed until business verification is approved). -address/from: the address the error is about, under the name the request used for it.1 properties
errorsobject[]3 properties
pathobject[]requiredmessagestringrequiredcodestring