Documentação da API · versão 1

API de entrada de leads

Mande leads de qualquer sistema: o seu distribuidor de leads, o formulário do site ou o seu CRM. Cada lead chega com a origem completa e a base legal registrada e, em segundos, recebe a primeira mensagem pelo WhatsApp. Quando ele responde, a IA assume a conversa.

Chave por integraçãoJSON · UTF-8Mensagens em portuguêsAtualizada em 24/09/2026
POST/api/integrations/leadsJSON
{  "external_id": "DL-88213",  "name": "Camila Ribeiro",  "phone": "(21) 98714-2290",  "legal_basis": "solicitaram",  "source": {    "platform": "meta",    "campaign_name": "Reserva Alcântara — Set/26",    "ad_name": "Vídeo tour 2 quartos"  }}
Nesta página · Visão geral

Visão geral

Cada vez que um lead novo aparece no seu sistema, ele faz uma chamada para este endereço. A partir daí, o painel cuida do resto: junta pelo telefone com quem já existe, registra a origem e a base legal, manda a primeira mensagem pelo WhatsApp e coloca o cartão no Funil.

  1. Seu sistema
  2. Envia o lead
  3. Junta pelo telefone
  4. Primeiro contato
  5. IA assume
1

Crie a integração

No painel, em Integrações → Entrada de leads → Nova integração. A chave aparece uma vez: guarde na hora.

2

Mande um lead de teste

Use o exemplo desta página ou o botão Enviar lead de teste do painel. O lead aparece na hora, com o selo Teste.

3

Ligue no seu sistema

Uma chamada por lead novo, na hora em que ele chega. Mande o external_id para reenviar sem medo de duplicar.

Autenticação

Toda chamada leva a chave da integração no cabeçalho X-Api-Key. A chave começa com atld_ e é de uma integração só: cada sistema que manda leads tem a sua, e você pode pausar ou gerar outra sem mexer nas demais.

Cabeçalhos
X-Api-Key: atld_SUA_CHAVE
Content-Type: application/json
A chave é de servidor para servidor
Nunca coloque a chave no código do seu site, num aplicativo ou num repositório público: quem abrir a página consegue ver. Se ela vazar, gere uma nova no painel; a anterior para de funcionar na hora. A rota só aceita a chave no cabeçalho X-Api-Key: o login do painel não serve para enviar leads.
  • Por segurança, a chave completa aparece uma única vez, quando é criada. Depois o painel mostra só o começo e o fim.
  • A chave de pedidos continua servindo só para pedidos. Para leads, use a chave da integração.
  • Usa o painel de um parceiro? O endereço certo aparece em Integrações, no seu painel, já com o domínio dele.

Enviar leads

POSThttps://api.attendto.com.br/api/integrations/leads

O corpo pode ser um lead solto, no formato que a maioria dos distribuidores já manda, ou uma lista em "leads" com até 100 leads. Os nomes dos campos são em inglês. Os valores da base legal podem ir em português (solicitaram, clientes, consentimento) ou em inglês (requested, customers, consent). As mensagens de volta vêm em português.

curl -X POST https://api.attendto.com.br/api/integrations/leads \
  -H "X-Api-Key: $CHAVE_DA_INTEGRACAO" \
  -H "Content-Type: application/json" \
  --data '{
    "external_id": "DL-88213",
    "name": "Camila Ribeiro",
    "phone": "(21) 98714-2290",
    "legal_basis": "solicitaram",
    "source": { "platform": "meta", "campaign_name": "Reserva Alcântara — Set/26" }
  }'
Teste sem programar
No painel, o botão Enviar lead de teste cria um lead marcado como teste e mostra a resposta da API. Se quiser, a primeira mensagem vai para o seu próprio WhatsApp.

Campos do lead

Só o telefone e a base legal são indispensáveis. Todo o resto deixa o lead mais completo para a IA e para o seu time.

CampoTipoPrecisa?O que é
phonetextoObrigatórioCelular com DDD. Aceita máscara; sem DDI, entendemos que é do Brasil (55). Também aceitamos telefone, celular e whatsapp. Sem telefone o lead é recusado: sem WhatsApp não há conversa.
legal_basistextoObrigatório*solicitaram, clientes ou consentimento. *Pode ficar de fora se a integração tiver uma base legal padrão. Veja .
external_idtexto · até 120RecomendadoO ID do lead no seu sistema. É o que impede duplicar quando o mesmo lead é reenviado.
nametexto · até 120OpcionalNome da pessoa. Também aceitamos nome e full_name.
emailtextoOpcionalE-mail válido. Também aceitamos e-mail.
sourceobjetoOpcionalDe onde o lead veio: campanha de anúncio, conjunto, anúncio, formulário e UTMs. Veja .
consentobjetoOpcionalProva do aceite: text (até 1.000 caracteres), collected_at e page_url. Fica guardada junto com a entrada.
fieldsobjetoOpcionalAté 50 dados livres, cada um com texto, número ou sim/não de até 1.000 caracteres. Aparecem na ficha do lead como Dados recebidos, com nome legível. Um dado com o Nome na API de um campo do negócio (Funil → Configurar quadro → Campos do cartão) preenche esse campo no cartão; valor que não serve para o campo fica em Dados recebidos. Campo de moeda em reais (450000 ou "450.000,00"); os webhooks devolvem em centavos.
tagslista de textosOpcionalAté 10 etiquetas, somadas às etiquetas da integração.
first_contactsim/nãoOpcionalfalse pede para não mandar a primeira mensagem para este lead. true nunca liga um primeiro contato que você desligou no painel.
Ver um lead com todos os campos
Lead completo · JSON
{
  "leads": [
    {
      "external_id": "DL-88213",
      "name": "Camila Ribeiro",
      "phone": "(21) 98714-2290",
      "email": "camila.ribeiro@exemplo.com",
      "legal_basis": "solicitaram",
      "consent": {
        "text": "Aceito receber contato da Imobiliária Horizonte sobre este imóvel.",
        "collected_at": "2026-09-24T20:56:41-03:00",
        "page_url": "https://www.horizonteimoveis.com.br/reserva-alcantara"
      },
      "source": {
        "platform": "meta",
        "campaign_id": "120214875530910001",
        "campaign_name": "Reserva Alcântara — Set/26",
        "adset_id": "120214875530910022",
        "adset_name": "Alcântara 28-45",
        "ad_id": "120214875530910347",
        "ad_name": "Vídeo tour 2 quartos",
        "form_id": "987650000000001",
        "form_name": "Reserva Alcântara — interesse",
        "meta_lead_id": "1234567890123456",
        "utm_source": "facebook",
        "utm_medium": "cpc",
        "utm_campaign": "reserva-alcantara-set",
        "utm_content": "video-tour-2q",
        "utm_term": null,
        "clicked_at": "2026-09-24T20:56:30-03:00"
      },
      "fields": {
        "tipo_de_imovel": "Apartamento 2 quartos",
        "faixa_de_valor": "Até R$ 300 mil",
        "usar_fgts": true
      },
      "tags": ["reserva alcântara"],
      "first_contact": true
    }
  ]
}

Origem do anúncio

Tudo dentro de source é opcional, mas é isso que dá nome de campanha de anúncio, conjunto e anúncio a cada lead no painel. Mande os IDs sempre como texto, entre aspas: número grande perde os últimos dígitos em muitos sistemas.

CampoO que é
platformmeta, outros_anuncios, site, portal ou outro. Valor fora da lista vira outro.
campaign_id · campaign_nameID e nome da campanha de anúncio.
adset_id · adset_nameID e nome do conjunto de anúncios.
ad_id · ad_nameID e nome do anúncio. O ID liga o lead ao gasto do anúncio no relatório de investimento.
form_id · form_nameID e nome do formulário de anúncio.
meta_lead_idID do lead no formulário de anúncio da Meta, quando o seu sistema tiver.
utm_source · utm_medium · utm_campaign · utm_content · utm_termOs parâmetros UTM do link, como vieram.
clicked_atQuando a pessoa clicou ou mandou o formulário, em data e hora ISO 8601 com fuso (ex.: 2026-09-24T20:56:30-03:00).

Primeiro contato automático

Com o primeiro contato ligado na integração, o lead recebe em segundos uma mensagem com um modelo aprovado do WhatsApp, assinada pela assistente da sua empresa. Quando ele responde, a IA assume a conversa e qualifica. O modelo, o horário e o custo por envio ficam no painel, na integração.

A mensagem não sai quando:

  • alguém do seu time já está na conversa com essa pessoa;
  • o lead já está conversando com a IA (não faz sentido gastar um modelo);
  • a mesma pessoa já recebeu uma primeira mensagem nos últimos 30 dias, por qualquer integração;
  • o número não é um celular do Brasil;
  • a base legal do lead é clientes: mensagem automática de marketing pede o consentimento da pessoa;
  • o seu time marcou o contato para não receber campanha;
  • você mandou "first_contact": false.

Lead que chega fora do horário de envio da integração (padrão: das 8h às 21h, horário de Brasília) recebe a mensagem na próxima abertura. O motivo de cada decisão volta na resposta, em first_contact_reason, e aparece no registro de entradas do painel.

Resposta

Quando a chamada entra, a resposta é 200 com o resultado de cada lead, na mesma ordem em que foram enviados. Um lead com problema não derruba os outros.

{
  "received": 2,
  "created": 1,
  "updated": 1,
  "duplicates": 0,
  "rejected": 0,
  "items": [
    { "index": 0, "external_id": "DL-88213", "status": "created",
      "lead_id": "7f0c2a91-4d1e-4b0a-9c55-2e8f1d3a6b70",
      "first_contact": "scheduled" },
    { "index": 1, "external_id": "DL-88214", "status": "updated",
      "lead_id": "a91e5b30-77c2-4f18-8d0e-5c4b2a1f9e33",
      "first_contact": "skipped",
      "first_contact_reason": "O lead já está conversando com a IA." }
  ],
  "errors": []
}

Resultado de cada lead · status

createdLead novo criado.
updatedO telefone já existia: a entrada foi juntada ao lead e só o que estava vazio foi preenchido. Nada que o seu time digitou é apagado.
duplicateMesmo external_id já recebido, ou mesmo telefone em até 10 minutos sem external_id. Nada muda.
blockedA pessoa pediu para não receber mensagens. A entrada fica registrada, sem mensagem. (Contato que o seu time só tirou das campanhas volta como updated, com o primeiro contato dispensado.)
rejectedO lead não entrou. O motivo vem em errors.

Primeiro contato · first_contact

scheduledA mensagem vai sair em segundos, ou na próxima abertura do horário de envio.
skippedA mensagem não vai sair. O motivo, em português, vem em first_contact_reason.
offO primeiro contato está desligado na integração, ou você mandou false para este lead.

Erros

Quando a chamada inteira não pode entrar, a resposta vem com o código HTTP e uma frase em detail, pronta para mostrar no log do seu sistema.

CódigoQuando aconteceMensagem
401Faltou a chave ou ela está errada.“Informe a chave da integração em X-Api-Key.” ou “Chave da integração inválida.”
403A integração está pausada.“Esta integração está pausada. Reative em Integrações → Entrada de leads.”
403A conta está desativada ou é de demonstração.“Esta conta não recebe leads pela API.”
413Mais de 100 leads, ou corpo acima de 1 MB.“Envie no máximo 100 leads por requisição.”
422O corpo não é um JSON válido.“O corpo precisa ser um JSON com um lead ou com a lista "leads".”
429Chamadas demais em pouco tempo, o limite do dia acabou, ou a mesma rede mandou chave errada muitas vezes seguidas.“Muitas requisições. Tente de novo em N s.” Com o cabeçalho Retry-After.

Motivos de recusa

Quando só um lead do lote tem problema, ele volta como rejected e o motivo aparece em errors, com o índice dele. Os outros entram normalmente.

MotivoComo resolver
Telefone ausenteEnvie o telefone com DDD.
Telefone inválidoUse DDD + número. Para fora do Brasil, mande com o DDI (ex.: 5511987654321). A mensagem diz o que houve: veio sem DDD, faltam dígitos ou dígitos demais.
Base legal ausenteEnvie legal_basis ou defina a base padrão da integração no painel.
Base legal inválidaUse solicitaram, clientes ou consentimento.
E-mail inválidoCorrija ou deixe o e-mail de fora.
ID repetido no loteO mesmo lead apareceu duas vezes na mesma chamada.
Contato em atendimento agoraO contato estava ocupado por uma conversa naquele instante. Reenvie em alguns segundos: com external_id, não duplica.
Número da própria empresaO telefone é o da conta do WhatsApp conectada ao painel.

Atualizar a etapa

Com a permissão Atualizar etapas ligada na integração (vem desligada), a mesma chave move o cartão do lead no quadro de destino da integração, ou no quadro padrão quando ela não tem destino. A etapa é o Nome na API da coluna, que não muda quando alguém renomeia a coluna. Liste as etapas de um quadro em GET /api/integrations/boards/{board_id}/stages.

CampoTipoUsoO que é
external_id ou phonetextoObrigatórioQual lead: o ID no seu sistema ou o telefone.
stagetextoObrigatórioO Nome na API da coluna de destino.
fieldsobjetoOpcionalOs campos do negócio que a coluna de destino pede, pelo Nome na API de cada um. Campo de moeda em reais (450000 ou "450.000,00"); os webhooks devolvem em centavos.
value_centsnúmeroOpcionalNa coluna de ganho: o valor da venda em centavos.
lost_reasontextoNa perdaNa coluna de perdido: a chave de um motivo de perda daquele quadro.
allow_backwardssim/nãoOpcionalMande true para voltar a uma etapa anterior.
POST /api/integrations/leads/stage · JSON
{
  "external_id": "CRM-48213",
  "stage": "pasta",
  "fields": {
    "valor_imovel": 450000,
    "tipo_financiamento": "Financiamento bancário"
  }
}

A resposta traz status: moved quando o cartão mudou de etapa, ou unchanged quando ele já estava nela. Mandar a mesma etapa de novo não move o cartão nem repete os avisos dos webhooks; campos diferentes em fields são gravados, com o histórico de cada um.

GET /api/integrations/boards/{board_id}/stages · resposta
[
  { "key": "novo", "name": "Novo", "role": "entrada" },
  { "key": "qualificado", "name": "Qualificado", "role": "qualificado" },
  { "key": "visita", "name": "Visita", "role": "intermediaria" },
  { "key": "pasta", "name": "Pasta", "role": "intermediaria" },
  { "key": "venda", "name": "Venda", "role": "ganho" },
  { "key": "perdido", "name": "Perdido", "role": "perdido" }
]
CódigoQuando aconteceMensagem
403A integração não tem a permissão de etapas.“Esta integração não tem permissão para atualizar etapas. Ligue em Integrações → Entrada de leads → Editar.”
404O lead não tem cartão no quadro.“O lead não está no quadro [nome].”
422O corpo não é um JSON com stage e external_id ou phone.“O corpo precisa ser um JSON com stage e external_id ou phone.”
422A etapa não existe no quadro.“Etapa [x] não existe no quadro [nome].”
422A coluna pede campos que não vieram.“Para entrar em [coluna] falta: [campos]”
422A etapa fica antes da atual.“A etapa [x] fica antes da atual. Mande allow_backwards: true para voltar.”
409As colunas do quadro mudaram no mesmo instante.“As etapas deste quadro acabaram de mudar. Tente de novo em alguns segundos.”

Ligue só para o sistema em que você confia

Com a permissão, a chave marca venda e perda no seu funil. Cada vez que alguém liga ou desliga, a auditoria registra quem foi.

Repetidos e reenvio

Na dúvida, reenvie. O painel reconhece o que já recebeu e não cria lead, nem manda mensagem, nem cobra de novo.

  • Com external_id: o mesmo ID na mesma integração volta como duplicate, com o mesmo lead_id, a qualquer momento.
  • Sem external_id: o mesmo telefone na mesma integração em até 10 minutos também volta como duplicate. Cobre o reenvio automático por tempo esgotado.
  • Quando reenviar: em 429, espere o tempo de Retry-After. Em erro do servidor ou queda de rede, tente de novo com espera crescente, por exemplo 2 s, 10 s e 1 min.
  • Não reenvie os itens que voltaram como rejected sem corrigir: eles voltam recusados de novo.

Limites

Por chamada
100
leads por requisição
Por minuto
120
requisições por chave
Por dia
5.000
leads por integração
Tamanho
1 MB
por requisição

O limite de 1 MB vale antes de tudo: um lote de 100 leads com muitos campos pode passar dele, e aí é melhor dividir em requisições menores. Cada requisição tem até 25 s; o lead que não couber volta com “Tempo da requisição esgotado” e pode ser reenviado sem duplicar.

Receber leads pela API não tem custo. O que tem custo é a primeira mensagem por modelo, quando ligada, e o valor aparece no painel antes de você ligar.

Formato do seu sistema

O seu distribuidor manda um JSON próprio e não dá para mudar? No painel, em Receber no formato do seu sistema, cole um exemplo real e ligue cada campo ao nosso. A integração passa a aceitar esse formato, um lead por chamada.

contato.celularTelefonelead.nomeNomeid_distribuidorID no seu sistemautm.campanhaCampanha de anúncio

Campo que não vier fica vazio. Se faltar o telefone, o lead é recusado com o motivo “Telefone não encontrado em contato.celular”.

Depois que o lead entra

Esta página ajudou?

Precisa de ajuda na primeira integração?

Fale com a gente pelo chat do painel. A nossa equipe acompanha você até o primeiro lead chegar.

Abrir Integrações no painel