Contatos
Liste, consulte, crie e atualize contatos pela API pública v1 da OctoSolve.
Contatos
O recurso /contacts permite ler, criar, atualizar e apagar contatos da própria conta.
Campos
| Campo | Tipo | Leitura | Escrita | Regras |
|---|---|---|---|---|
id | uuid | Sim | Não | Identificador do contato |
telefone | string ou null | Sim | Apenas na criação | Obrigatório ao criar: só dígitos, de 10 a 15 caracteres, com DDI e DDD, como 5511999998888. Na leitura pode vir null: contato que chegou pelo Instagram ou pelo Telegram se identifica por username e não tem telefone |
nome | string ou null | Sim | Sim | Máximo de 120 caracteres |
email | string ou null | Sim | Sim | E-mail válido, máximo de 254 caracteres |
cidade | string ou null | Sim | Sim | Máximo de 120 caracteres |
data_nascimento | string ou null | Sim | Sim | Formato YYYY-MM-DD |
observacoes | string ou null | Sim | Sim | Máximo de 2.000 caracteres |
tags | string[] | Sim | Sim | Máximo de 20 tags, com até 40 caracteres cada |
status | enum ou null | Sim | Sim | novo, ativo, inativo ou bloqueado; o enum pode ganhar valores em mudanças aditivas. Contato antigo pode vir com null |
ig_username | string ou null | Sim | Não | Identidade do Instagram |
telegram_username | string ou null | Sim | Não | Identidade do Telegram |
updated_at | datetime ou null | Sim | Não | Data e hora ISO 8601 da atualização |
cpf | string ou null | Sim | Não | Só dígitos, 11 caracteres. Não sai nos webhooks, só aqui. Cadastro e alteração continuam pelo painel |
Identidades de outros canais são somente leitura. A v1 cria contatos apenas por telefone.
Sobre o cpf: ele sai aqui, mas não sai nos webhooks. A diferença é o caminho. Aqui a consulta é feita pela sua chave, fica registrada e você escolhe a hora. No webhook o dado sairia sozinho e passaria por lugares que ninguém controla depois: o log do seu servidor, o log do seu gateway e ferramentas de automação no meio (Make, n8n, Zapier). Como o documento é do seu cliente e não da sua empresa, ele fica no caminho que deixa rastro.
Se você recebe um evento e precisa do CPF, use o id do contato que veio no evento e consulte aqui.
Endpoints
| Método | Caminho | Escopo | Resultado |
|---|---|---|---|
GET | /contacts | read ou write | Lista paginada |
GET | /contacts/{id} | read ou write | Um contato |
POST | /contacts | write | Cria e responde 201 |
PATCH | /contacts/{id} | write | Atualiza os campos enviados |
DELETE | /contacts/{id} | write | Apaga o contato e responde 200 com o resumo |
Listar contatos
Filtros disponíveis:
| Filtro | Regra |
|---|---|
telefone | Igualdade depois da normalização para dígitos |
q | Busca no nome sem diferenciar maiúsculas e minúsculas, de 2 a 80 caracteres |
status | novo, ativo, inativo ou bloqueado |
tag | Contato que contém a tag, máximo de 40 caracteres |
limit | De 1 a 100, padrão 50 |
cursor | Valor opaco retornado pela página anterior |
Consultar um contato
Um UUID inexistente ou pertencente a outra conta responde o mesmo 404 not_found.
Criar um contato
O telefone é normalizado para dígitos e identifica o contato dentro da conta. Se já existir um contato com o mesmo telefone, a API responde 409 conflict:
Idempotência na criação
O header opcional Idempotency-Key aceita até 128 caracteres e evita repetir uma criação quando há timeout ou nova tentativa. Use uma chave estável e única para a mesma operação de origem.
O registro é durável e fica retido por 24 horas:
- Mesma chave e mesmo pedido: devolve a resposta original, inclusive o status HTTP.
- Mesma chave com corpo, método ou rota diferente:
409 idempotency_conflict. - Pedido original ainda em andamento:
409 idempotency_in_progress. Aguarde e tente novamente com a mesma chave e o mesmo corpo.
Atualizar um contato
No PATCH, um campo ausente não muda. Um null explícito limpa um campo que aceita null. Atualizações concorrentes usam a regra da última gravação, sem bloqueio otimista. Use updated_at da resposta se a sua integração precisar detectar uma alteração posterior.
Apagar um contato
Resposta 200:
A exclusão é definitiva. Ela cancela toda cobrança pendente do contato no Asaas, e o resumo mostra quantas foram canceladas em cobrancas_canceladas e quantas falharam ao cancelar em cobrancas_com_falha. Quando o regulatório impede apagar o cliente no Asaas, ele é mascarado em vez de removido, e cliente_mascarado vem true.
O registro financeiro não é apagado, é anonimizado: o histórico de pagamento continua existindo para fins contábeis e fiscais, sem o dado pessoal do contato.
Uma segunda chamada no mesmo id responde 404 not_found, porque o contato já não existe. Chamar duas vezes ao mesmo tempo cancela a cobrança pendente uma única vez: uma chamada responde 200, a outra 404.
Apagar um contato pela API dispara o evento de webhook contact.deleted. Veja o payload em Webhooks.
Qualquer chave com escopo write já criada passa a poder apagar contato, inclusive as que você usa só para cadastrar. Se a sua chave circula em automação compartilhada, vale criar uma chave separada e guardar a de escrita para quem realmente precisa apagar.
Receita para Make ou n8n
Para sincronizar contatos de um CRM ou formulário:
- Receba o registro de origem e normalize o telefone com DDI e DDD.
- Faça
GET /contacts?telefone=NUMEROcom uma chavewrite. - Se
dataestiver vazio, enviePOST /contactscomContent-Type: application/json. - No
POST, preenchaIdempotency-Keycom um identificador estável, comocrm_contato_ID_DA_ORIGEM. Não gere outro valor a cada nova tentativa da mesma execução. - Se o contato existir, envie
PATCH /contacts/{id}apenas com os campos que deseja alterar. - Trate
409 conflictusandoerror.details[0].existing_idpara localizar o contato já criado. - Em
idempotency_in_progress, espere e repita o mesmoPOST, com a mesma chave e o mesmo corpo. - Para importar muitos contatos, respeite as três janelas de limites de requisições.