API e Integrações

Última atualização: 14 de agosto de 2026

O que dá para fazer

A Ledio se integra ao seu sistema nos dois sentidos. Você avisa a Ledio quando algo acontece do seu lado (alguém se cadastrou, alguém comprou) e a Ledio avisa você quando algo acontece na conversa (um contato novo apareceu, um contato virou cliente).

Todos os endpoints partem de https://api.ledio.ai e recebem e devolvem JSON.

Autenticação

Toda chamada precisa de dois cabeçalhos. Os dois são gerados no painel, em Configurações → API e Webhooks.

CampoTipoDescrição
x-api-keyobrigatóriostringIdentifica a sua empresa na Ledio. Fica visível no painel e pode ser copiada de lá.
x-webhook-secretobrigatóriostringSegredo da integração, começa com whsec_. É mostrado uma única vez no momento em que você gera. A Ledio guarda apenas um hash, então não há como recuperá-lo depois: se perder, gere outro.
Esses cabeçalhos valem por qualquer requisição em nome da sua empresa. Mantenha-os no servidor. Nunca coloque em código de frontend, app mobile ou repositório público — quem tiver os dois pode enviar mensagens pelo seu WhatsApp.

Faltando ou errado, a resposta é 401 com uma mensagem dizendo qual dos dois falhou.

Resposta padrão

Os endpoints respondem 200 com o mesmo formato. Confira sempre o campo success: um 200 com success: false significa que autenticamos você, mas a ação não aconteceu (número inexistente no WhatsApp, contato não encontrado, canal desconectado).

resposta
{
  "success": true,
  "message": "Welcome message sent",
  "contactId": "1f5c2a10-2b3c-4d5e-6f70-8a9b0c1d2e3f"
}
CampoTipoDescrição
successbooleanSe a ação foi concluída.
messagestringDetalhe do que aconteceu — ou o motivo, quando success é false.
contactIdstringId do contato na Ledio, quando a ação envolveu um. Guarde para correlacionar com o seu sistema.

1. Novo cadastro

POST/webhook/external/new-user

Avisa que alguém se cadastrou no seu sistema. A Ledio cria o contato, confere se o número existe no WhatsApp e, existindo, o agente de IA inicia a conversa no fluxo escolhido.

CampoTipoDescrição
phoneobrigatóriostringTelefone com DDI, só números: 5511999999999. Sem espaços, parênteses ou traços.
namestringNome da pessoa. O agente usa para personalizar o atendimento.
externalIdstringO id dela no seu sistema. Serve para você correlacionar os dois lados depois.
flowCONVERSION | SUPPORT | ONBOARDING | BILLING | FEEDBACK | CUSTOMComo o agente deve abordar. Padrão CONVERSION (foco em venda).
contextobjetoDados livres que o agente passa a conhecer durante a conversa — origem, campanha, plano pretendido.
curl
curl -X POST https://api.ledio.ai/webhook/external/new-user \
  -H "Content-Type: application/json" \
  -H "x-api-key: SUA_API_KEY" \
  -H "x-webhook-secret: whsec_SEU_SECRET" \
  -d '{
    "phone": "5511999999999",
    "name": "João Silva",
    "externalId": "usr_abc123",
    "flow": "CONVERSION",
    "context": { "source": "landing_page", "campaign": "black_friday" }
  }'

2. Usuário converteu

POST/webhook/external/user-converted

Avisa que a pessoa assinou ou comprou. O agente para de vender e passa a tratá-la como cliente. Mande isso assim que o pagamento confirmar: sem esse aviso, o agente continua oferecendo o que ela já comprou.

CampoTipoDescrição
phoneobrigatóriostringO mesmo telefone usado no cadastro.
namestringAtualiza o nome do contato, se já existir.
externalIdstringId da pessoa no seu sistema.
contextobjetoO que ela comprou, para o agente ter contexto: { "plan": "pro", "value": 2990, "currency": "BRL" }.
curl
curl -X POST https://api.ledio.ai/webhook/external/user-converted \
  -H "Content-Type: application/json" \
  -H "x-api-key: SUA_API_KEY" \
  -H "x-webhook-secret: whsec_SEU_SECRET" \
  -d '{
    "phone": "5511999999999",
    "context": { "plan": "pro", "value": 2990, "currency": "BRL" }
  }'

3. Mudar o fluxo de atendimento

POST/webhook/external/change-flow

Muda como o agente se comporta com um contato que já existe. Útil quando a pessoa abre um chamado de suporte no seu sistema e você quer que a conversa no WhatsApp acompanhe.

CampoTipoDescrição
phoneobrigatóriostringTelefone do contato.
flowobrigatórioCONVERSION | SUPPORT | ONBOARDING | BILLING | FEEDBACK | CUSTOMO novo fluxo.
contextobjetoMotivo da mudança: { "reason": "user_requested_support", "ticket_id": "TK-123" }.
curl
curl -X POST https://api.ledio.ai/webhook/external/change-flow \
  -H "Content-Type: application/json" \
  -H "x-api-key: SUA_API_KEY" \
  -H "x-webhook-secret: whsec_SEU_SECRET" \
  -d '{ "phone": "5511999999999", "flow": "SUPPORT" }'

4. Enviar mensagem

POST/webhook/external/send-message

Envia um texto pelo WhatsApp para um contato que já conversou com você.

Este endpoint não cria contato e não envia para quem nunca falou com você. É proteção deliberada: disparar para número frio é a forma mais rápida de ter o WhatsApp da sua empresa banido. Para iniciar uma conversa do zero, use o endpoint de novo cadastro.
CampoTipoDescrição
phoneobrigatóriostringTelefone de um contato que já existe.
messagestringO texto a enviar.
contextstringInformação para o agente considerar daqui em diante. Ex.: "Lead veio do Instagram, interessado em SUV 2024".
curl
curl -X POST https://api.ledio.ai/webhook/external/send-message \
  -H "Content-Type: application/json" \
  -H "x-api-key: SUA_API_KEY" \
  -H "x-webhook-secret: whsec_SEU_SECRET" \
  -d '{
    "phone": "5511999999999",
    "message": "Oi! Posso te ajudar?"
  }'

5. Código de verificação (OTP)

POST/webhook/external/otp

Envia um código de verificação pelo WhatsApp usando um template de autenticação aprovado pela Meta.

Requer que a sua empresa esteja na Cloud API da Meta e tenha um template de autenticação aprovado. Se você usa a conexão por QR Code, este endpoint não funciona. Fale com o suporte antes de integrar.
CampoTipoDescrição
phoneobrigatóriostringTelefone de destino.
codeobrigatóriostringO código gerado por você. A Ledio apenas entrega, não gera nem valida.
expiresInMinutesobrigatórionumberQuantos minutos o código vale, exibido na mensagem.
namestringNome do destinatário.
externalIdstringId da pessoa no seu sistema.
brandstringNome da marca exibido na mensagem.
curl
curl -X POST https://api.ledio.ai/webhook/external/otp \
  -H "Content-Type: application/json" \
  -H "x-api-key: SUA_API_KEY" \
  -H "x-webhook-secret: whsec_SEU_SECRET" \
  -d '{
    "phone": "5511999999999",
    "code": "123456",
    "expiresInMinutes": 5
  }'

Receber eventos da Ledio

O caminho inverso. Cadastre uma URL em Configurações → API e Webhooks e a Ledio envia um POST para ela quando algo acontece na conversa.

CampoTipoDescrição
contact.createdeventoUm contato novo entrou em conversa.
contact.convertedeventoUm contato foi marcado como cliente — pelo agente, pelo painel ou pelo endpoint de conversão.

Todos os eventos chegam no mesmo envelope:

corpo enviado por nós
{
  "id": "5f1c2a10-2b3c-4d5e-6f70-8a9b0c1d2e3f",
  "type": "contact.converted",
  "createdAt": "2026-08-14T18:22:05.412Z",
  "data": {
    "businessSlug": "sua-empresa",
    "contactId": "1f5c2a10-2b3c-4d5e-6f70-8a9b0c1d2e3f",
    "phone": "5511999999999",
    "name": "João Silva",
    "status": "CONVERTED",
    "flow": "ONBOARDING"
  }
}

Use o id para descartar repetições: em caso de falha na entrega a Ledio tenta de novo, então o mesmo evento pode chegar duas vezes. Trate o recebimento como idempotente.

Conferindo a assinatura

Cada requisição vai assinada no cabeçalho x-ledio-signature, no formato sha256=<hex>. É um HMAC-SHA256 do corpo exatamente como recebido, usando o segredo que você cadastrou.

Calcule o HMAC sobre o corpo cru, antes de qualquer parse. Se você serializar o JSON de novo para conferir, a assinatura não vai bater — é o erro mais comum nessa etapa.
Node.js
import crypto from 'node:crypto'

// rawBody = o corpo como string, sem parse
function assinaturaConfere(rawBody, header, segredo) {
  const esperado =
    'sha256=' +
    crypto.createHmac('sha256', segredo).update(rawBody).digest('hex')

  const a = Buffer.from(esperado)
  const b = Buffer.from(header ?? '')
  // Comparação em tempo constante evita vazar a assinatura por timing
  return a.length === b.length && crypto.timingSafeEqual(a, b)
}

Responda 2xx rápido. Se o seu endpoint demorar ou responder erro, a Ledio considera falha e tenta de novo mais tarde.

Erros

CampoTipoDescrição
401autenticaçãoCabeçalho faltando, API key desconhecida ou segredo incorreto. A mensagem diz qual dos casos.
400validaçãoCorpo inválido — campo obrigatório ausente ou fluxo com valor fora da lista.
200 com success: falseregra de negócioAutenticado, mas a ação não aconteceu. O motivo vem em message: número não existe no WhatsApp, contato não encontrado, canal desconectado.

Recomendações de integração

Guarde o contactId que volta na primeira chamada. Ele é a chave para correlacionar a conversa na Ledio com o registro no seu sistema, e evita depender do telefone, que muda.

Mande sempre o telefone no mesmo formato, com DDI e apenas números. A Ledio normaliza, mas manter o padrão de um lado só facilita a conferência quando algo não bate.

Trate success: false como resposta esperada, não como exceção. Número que não existe no WhatsApp é situação comum e não deveria quebrar a sua fila de processamento.

Precisa de ajuda?

Se algo aqui não bater com o que você está vendo na prática, fale com a gente pelo suporte no painel. Documentação divergente do comportamento é bug, e a gente quer saber.