API — Contacts
Contacts são as pessoas externas que você atende — clientes, leads, parceiros. Cada contato pode ter múltiplas conversas em canais diferentes, atributos personalizados, etiquetas e negócios associados. Esta página cobre todos os endpoints para operar a base de contatos via API.
Endpoints
Seção intitulada “Endpoints”| Método | Endpoint | Ação |
|---|---|---|
GET | /api/v1/accounts/{id}/contacts | Lista contatos |
POST | /api/v1/accounts/{id}/contacts | Cria contato |
GET | /api/v1/accounts/{id}/contacts/{contact_id} | Detalhes |
PATCH | /api/v1/accounts/{id}/contacts/{contact_id} | Atualizar |
DELETE | /api/v1/accounts/{id}/contacts/{contact_id} | Remover |
GET | /api/v1/accounts/{id}/contacts/search | Busca por nome, e-mail ou telefone |
POST | /api/v1/accounts/{id}/contacts/filter | Filtros combinados |
POST | /api/v1/accounts/{id}/actions/contact_merge | Mesclar dois contatos |
GET | /api/v1/accounts/{id}/contacts/{contact_id}/conversations | Conversas do contato |
POST | /api/v1/accounts/{id}/contacts/import | Importação em batch |
Campos do recurso
Seção intitulada “Campos do recurso”{ "id": 4521, "name": "Maria Silva", "phone_number": "+5511999990000", "identifier": "ERP-001", "company_name": "Suaempresa Cliente Ltda", "city": "São Paulo", "country": "BR", "avatar_url": "https://...", "bio": "Cliente desde 2024", "custom_attributes": { "cpf": "123.456.789-00", "plano": "premium", "valor_ltv": 8500.00 }, "labels": ["vip", "indicacao"], "blocked": false, "last_activity_at": "2026-05-24T14:30:00Z", "created_at": "2024-01-15T10:00:00Z"}GET /contacts
Seção intitulada “GET /contacts”Lista paginada de contatos.
curl -X GET "https://app.smart2.com.br/api/v1/accounts/1/contacts?page=1&per_page=50" \ -H "api_access_token: SEU_TOKEN"Filtros query simples
Seção intitulada “Filtros query simples”?q=maria # Busca por nome/email/telefone[email protected] # Email exato?identifier=ERP-001 # Identifier exato?labels[]=vip&labels[]=premium # Tem alguma das labels?sort=created_at&order=desc # OrdenaçãoPOST /contacts
Seção intitulada “POST /contacts”Cria contato novo. Se email/phone/identifier já existir, retorna o existente em vez de criar duplicado.
curl -X POST "https://app.smart2.com.br/api/v1/accounts/1/contacts" \ -H "api_access_token: SEU_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "name": "Maria Silva", "email": "[email protected]", "phone_number": "+5511999990000", "identifier": "ERP-001", "custom_attributes": { "cpf": "123.456.789-00" } }'Resposta (200 OK ou 201 Created)
Seção intitulada “Resposta (200 OK ou 201 Created)”Status 201 = criou novo. Status 200 = retornou existente (dedup).
{ "payload": { "contact": { ... } }}PATCH /contacts/{contact_id}
Seção intitulada “PATCH /contacts/{contact_id}”Atualização parcial. Apenas campos enviados são alterados.
curl -X PATCH "https://app.smart2.com.br/api/v1/accounts/1/contacts/4521" \ -H "api_access_token: SEU_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "company_name": "Nova Empresa Cliente", "custom_attributes": { "plano": "enterprise" } }'Comportamento de custom_attributes
Seção intitulada “Comportamento de custom_attributes”Atributos enviados substituem apenas os enviados. Atributos não enviados permanecem. Para remover atributo, envie null:
{ "custom_attributes": { "atributo_antigo": null }}GET /contacts/search
Seção intitulada “GET /contacts/search”Busca textual avançada.
curl "https://app.smart2.com.br/api/v1/accounts/1/contacts/search?q=maria" \ -H "api_access_token: SEU_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "q": "silva", "include": "conversations" }'Busca em: nome, email, telefone, identifier, atributos com valor textual.
POST /contacts/filter
Seção intitulada “POST /contacts/filter”Filtros combinados complexos.
curl -X POST "https://app.smart2.com.br/api/v1/accounts/1/contacts/filter" \ -H "api_access_token: SEU_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "payload": [ { "attribute_key": "labels", "filter_operator": "contains", "values": ["vip"] }, { "attribute_key": "city", "filter_operator": "equal_to", "values": ["São Paulo"], "query_operator": "and" }, { "attribute_key": "custom_attributes.plano", "filter_operator": "equal_to", "values": ["premium"], "query_operator": "and" } ] }'Equivalente a “contatos com etiqueta vip + cidade São Paulo + plano premium”.
POST /actions/contact_merge
Seção intitulada “POST /actions/contact_merge”Mescla dois contatos em um (resolve duplicação).
curl -X POST "https://app.smart2.com.br/api/v1/accounts/1/actions/contact_merge" \ -H "api_access_token: SEU_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "secondary_contact_id": 4522 }'Após merge:
- Conversas do
secondary_contact_id(4522) são vinculadas ao principal (4521) - Atributos do secundário preenchem campos vazios do principal
- Secundário é excluído
DELETE /contacts/{contact_id}
Seção intitulada “DELETE /contacts/{contact_id}”Remove contato permanentemente.
curl -X DELETE "https://app.smart2.com.br/api/v1/accounts/1/contacts/4521" \ -H "api_access_token: SEU_TOKEN"Importação em massa
Seção intitulada “Importação em massa”Pra importar muitos contatos de uma vez (planilha inteira, base de outro CRM), use o importador CSV pelo painel em Contatos → Importar. Suporta milhares de linhas com mapeamento visual de colunas e relatório de erros por linha.
Pra automatizar via API, faça loop com POST /contacts respeitando rate limits — ver caso de uso abaixo.
Casos de uso
Seção intitulada “Casos de uso”Sync diário com CRM externo
Seção intitulada “Sync diário com CRM externo”external_contacts = fetch_from_crm() # 500 contatos
# Loop respeitando rate limitimport timecreated, updated = 0, 0for ext in external_contacts: # Verifica se existe search = requests.get( f"{BASE_URL}/contacts?q={ext['email']}", headers=HEADERS ).json().get('payload', [])
if search: requests.patch(f"{BASE_URL}/contacts/{search[0]['id']}", headers=HEADERS, json={ 'name': ext['name'], 'custom_attributes': {'crm_external_id': ext['id']}, }) updated += 1 else: requests.post(f"{BASE_URL}/contacts", headers=HEADERS, json={ 'name': ext['name'], 'email': ext['email'], 'phone_number': ext.get('phone'), 'custom_attributes': {'crm_external_id': ext['id']}, }) created += 1 time.sleep(0.25) # ~4 req/s, bem abaixo do limite
print(f"Criados: {created}, Atualizados: {updated}")Marcar contatos VIP com base em valor
Seção intitulada “Marcar contatos VIP com base em valor”# Listar contatos com LTV > 10kr = requests.post( f"{BASE_URL}/contacts/filter", headers=HEADERS, json={ "payload": [{ "attribute_key": "valor_ltv", "filter_operator": "is_greater_than", "values": [10000] }] })
# Aplicar label VIP em todosfor contact in r.json()['payload']: requests.patch( f"{BASE_URL}/contacts/{contact['id']}", headers=HEADERS, json={"labels": list(set(contact['labels'] + ['vip']))} )Limpar duplicação
Seção intitulada “Limpar duplicação”# Busca dois contatos com mesmo emailcontacts = requests.get( headers=HEADERS).json()
if len(contacts['payload']) == 2: primary = contacts['payload'][0] secondary = contacts['payload'][1]
requests.post( f"{BASE_URL}/actions/contact_merge", headers=HEADERS, json={"secondary_contact_id": secondary['id']} )Próximos passos
Seção intitulada “Próximos passos”- Conversations — vincular conversas ao contato
- Custom Attributes — definir atributos
- Labels — etiquetas
- Manual — Importar contatos