Quando usar
- Você precisa importar ou atualizar vários contatos no Cloud Chat de uma vez via API
- Você quer fazer upsert (criar novos + atualizar existentes) na mesma chamada
- Você precisa de funcionalidades avançadas como tags granulares, lookup de variantes de telefone ou merge de JSONB
Pré-requisitos
-
API Key em mãos — ver Como encontrar sua API Key no Cloud Chat
-
CLOUDCHAT_DOMAINeACCOUNT_ID -
Cada contato deve ter ao menos um identificador entre
phone_number,emailouidentifier
Quer importar apenas um contato? Use o endpoint de Como importar um contato individual via API. Os dois endpoints têm formatos de body diferentes — não misture.
Endpoint
POST https://{{CLOUDCHAT_DOMAIN}}/api/v1/accounts/{{ACCOUNT_ID}}/contacts/bulk_create
Headers
| Header | Valor |
|---|---|
content-type |
application/json |
api_access_token |
Seu token de API |
Corpo da requisição
O body usa um array data contendo os contatos a serem importados:
{
"upsert": true,
"data": [
{
"name": "Contato 1",
"email": "[email protected]",
"phone_number": "+5511999998888",
"identifier": "EXT-001",
"additional_attributes": {
"company": "Acme",
"city": "São Paulo"
},
"custom_attributes": {
"plano": "premium",
"origem": "campanha-março"
}
},
{
"name": "Contato 2",
"phone_number": "+5511888887777"
}
]
}
Campos por contato
| Campo | Obrigatório | Descrição |
|---|---|---|
phone_number |
Pelo menos 1 dos 3* | Telefone em E.164 com + |
email |
Pelo menos 1 dos 3* | E-mail do contato |
identifier |
Pelo menos 1 dos 3* | Identificador externo único |
name |
Não | Nome do contato |
additional_attributes |
Não | Objeto chave-valor. Sobrescrito por completo a cada update |
custom_attributes |
Não | Atributos personalizados criados pela conta. Sobrescrito por completo a cada update |
*Cada contato deve ter pelo menos um entre phone_number, email ou identifier.
Flag upsert
| Valor | Comportamento |
|---|---|
false ou ausente |
Apenas cria contatos novos. Se uma chave já existir, a linha falha com 422 |
true |
Cria novos e atualiza existentes |
Exemplo de requisição
curl -X POST \
'https://{{CLOUDCHAT_DOMAIN}}/api/v1/accounts/{{ACCOUNT_ID}}/contacts/bulk_create' \
--header 'content-type: application/json' \
--header 'api_access_token: SEU_TOKEN' \
--data '{
"upsert": true,
"data": [
{
"name": "Contato 1",
"email": "[email protected]",
"phone_number": "+5511999998888"
},
{
"name": "Contato 2",
"phone_number": "+5511888887777"
}
]
}'
Resposta
Sucesso (HTTP 201)
{ "success": true }
Erro de validação ou conflito (HTTP 422)
{
"success": false,
"errors": [
{
"index": 0,
"attributes": { "name": "Contato 1", "email": "[email protected]" },
"errors": ["Email is invalid"]
},
{
"index": 1,
"attributes": { "name": "Contato 2" },
"errors": "Duplicate: Contact with this phone number already exists"
}
]
}
indexindica a posição (0-based) da linha no arraydataerrorspor linha pode ser array de validação ou string única para conflitos de chave (duplicidade)
Body vazio (HTTP 400)
Retornado quando data é nulo ou array vazio.
Cuidados com upsert
Risco de perda de dados com upsert: true.
Ao atualizar um contato existente via bulk_create com upsert: true, qualquer campo que você não enviar é sobrescrito com null.
Exemplo: se um contato tem email e phone_number, e você envia update apenas com phone_number, o campo email é apagado.
Se você precisa atualizar apenas alguns campos sem apagar os demais, use o endpoint de update individual:
PUT /api/v1/accounts/{{ACCOUNT_ID}}/contacts/{{CONTACT_ID}}
Comportamento avançado (opcional)
A partir de 30/04/2026, o endpoint aceita parâmetros opcionais no body para customizar o processamento. Todos têm default conservador (paridade com o comportamento anterior) — só envie se quiser habilitar novas funcionalidades.
| Parâmetro | Tipo | Default | Efeito |
|---|---|---|---|
api_version |
string | "v1" |
"v1": paridade com comportamento anterior. "v2": habilita tudo (tags, __DELETE__, lookup de variantes, merge raso JSONB). "v2-safe": subset conservador |
apply_tags |
boolean | false |
Habilita tags_add e tags_remove por linha |
respect_sentinel |
boolean | false |
Habilita o valor especial __DELETE__ em campos JSONB e escalares |
merge_jsonb |
string | "overwrite" |
"overwrite": substitui colunas JSONB inteiras. "shallow": faz merge por chave |
coalesce_nulls |
boolean | false |
Trata null no payload como "preservar valor existente" |
coerce_blank_jsonb |
boolean | false |
Trata string vazia ("") em chaves JSONB como remoção da chave |
normalize_lookup |
boolean | false |
Lookup por variantes ao identificar contatos (especialmente telefones BR mobile-9) |
orphan_guard |
boolean | false |
Rejeita payloads que orfanizariam um contato existente |
Atalho: api_version: "v2" habilita tudo de uma vez — equivale a apply_tags: true + respect_sentinel: true + merge_jsonb: "shallow" + normalize_lookup: true.
Combinações que exigem atenção
-
merge_jsonb: "shallow"semrespect_sentinel: true— o merge raso preserva chaves não enviadas, mas não tem semântica de remoção. Se seu cliente assumiu que enviar uma chave vazia significa "apagar", a chave fica com o valor antigo. Userespect_sentinel: trueem conjunto e envie__DELETE__para remover explicitamente. -
coerce_blank_jsonb: trueem payloads com strings vazias intencionais — qualquer string vazia ("") em chaves JSONB será tratada como remoção. Não use se a sua conta tem campos legitimamente vazios. -
orphan_guard: trueem contas com contatos identifier-only — contatos sem email e sem telefone (apenasidentifier) serão rejeitados.
tags_add e tags_remove no body
Para adicionar e remover tags de forma granular por contato. Ignorados silenciosamente se você não enviar apply_tags: true (ou api_version: "v2").
{
"api_version": "v2",
"data": [
{
"email": "[email protected]",
"tags_add": ["vip", "premium"],
"tags_remove": ["pending"]
}
]
}
A ordem é determinística: primeiro adiciona, depois remove. Se uma mesma tag aparecer nos dois arrays, a remoção ganha.
Removendo chaves JSONB com __DELETE__
Para remover uma chave específica de additional_attributes ou custom_attributes sem mexer nas demais, envie o valor literal "__DELETE__". Requer respect_sentinel: true (ou api_version: "v2").
{
"api_version": "v2",
"data": [
{
"email": "[email protected]",
"custom_attributes": {
"favorite_color": "__DELETE__"
}
}
]
}
Funciona apenas em chaves de primeiro nível dos objetos JSONB. Combine com merge_jsonb: "shallow" (já incluso em api_version: "v2") para preservar as outras chaves.
Lookup de variantes de telefone (BR mobile-9)
Com normalize_lookup: true (ou api_version: "v2"), o sistema busca contatos existentes por variantes do telefone enviado.
{
"api_version": "v2",
"data": [
{
"phone_number": "+5511933334444",
"name": "Maria"
}
]
}
Se já existe um contato com +551133334444 (sem o 9), ele é encontrado e atualizado — em vez de criar duplicado.
Coalesce de null (preservar campos existentes)
Com coalesce_nulls: true, valores null no payload são tratados como "preservar valor existente". Útil quando você gera o payload programaticamente.
{
"coalesce_nulls": true,
"data": [
{
"email": "[email protected]",
"name": null,
"phone_number": "+5511999998888"
}
]
}
Sem coalesce_nulls, o name seria apagado. Com coalesce_nulls: true, o name existente é preservado.
Detecção de ambiguidade (AMBIGUOUS_MATCH)
Se uma linha contiver dois ou mais campos chave (email, telefone, identifier) que apontem para contatos diferentes já existentes, a linha é rejeitada com erro AMBIGUOUS_MATCH.
Mudança a partir de 30/04/2026: antes, o sistema usava o primeiro match encontrado (precedência email > identifier > telefone) e silenciosamente sobrescrevia dados do outro contato. Agora a linha é rejeitada explicitamente.
Diferença entre este endpoint e o Import individual
Este endpoint (bulk_create) |
Import individual (external_import) |
|
|---|---|---|
| Quando usar | Importar/atualizar vários contatos | Importar/atualizar 1 contato por chamada |
| Formato do body | {"upsert": true, "data": [{...}]} |
Objeto JSON simples (flat) |
| Upsert | Precisa do flag "upsert": true |
Sempre ativo |
| Cuidado com null | Campos omitidos são sobrescritos com null |
Campos omitidos são preservados |
Não misture os formatos. Se enviar um objeto flat (sem data: [...]) para este endpoint, não vai funcionar.
Onde encontrar os parâmetros
-
CLOUDCHAT_DOMAIN— domínio visível na URL do navegador -
ACCOUNT_ID— em Configurações da conta -
API_TOKEN— emhttps://{{CLOUDCHAT_DOMAIN}}/app/accounts/{{ACCOUNT_ID}}/profile/settings
Observações
-
Para importar apenas 1 contato: Como importar um contato individual via API
-
Para importar via HubSpot workflows: Como importar contatos via HubSpot
-
Para remover tags em massa: Como remover tags de contatos em massa via API
-
Visão geral de todas as APIs disponíveis: Guia Mestre — Como acessar e operar dados do Cloud Chat via API