Principal APIs Como importar contatos em massa via API

Como importar contatos em massa via API

Última atualização em May 21, 2026

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

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"
    }
  ]
}
  • index indica a posição (0-based) da linha no array data
  • errors por 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" sem respect_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. Use respect_sentinel: true em conjunto e envie __DELETE__ para remover explicitamente.

  • coerce_blank_jsonb: true em 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: true em contas com contatos identifier-only — contatos sem email e sem telefone (apenas identifier) 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 — em https://{{CLOUDCHAT_DOMAIN}}/app/accounts/{{ACCOUNT_ID}}/profile/settings


Observações