Documentação

API de eventos

O seu sistema avisa o Speakus quando algo acontece com um usuário — e o funcionário de IA puxa a conversa no WhatsApp. É uma requisição HTTP assinada, sem SDK e sem dependência nova.

Os dois momentos da integração

O mesmo endpoint recebe os dois. Muda apenas o campo event.

  1. Evento de ciclo de vidatrial_ended, checkout_abandonado, cadastro_sem_ativacao, assinatura_cancelada… O Speakus cria ou atualiza o lead e prepara a abordagem.
  2. Aviso de conversãoevent: "converted". Fecha o ciclo: o lead vira recuperado nas métricas e abordagens pendentes são canceladas. Não envia mensagem nenhuma.

Implementar só o primeiro deixa o loop pela metade: sem o aviso de conversão, o Speakus mostra quantos você reabordou, mas não quantos voltaram a pagar.

Credenciais

A URL e o segredo são emitidos por workspace no painel, em Configurações → Integrações. A URL já contém a sua chave de ingestão:

POST https://app.speakus.app/v1/hooks/inbound/{ingestKey}

Guarde o segredo em variável de ambiente. Na mesma tela há um arquivo de instruções pronto para colar numa IA de código — ela implementa a integração inteira a partir dele.

Assinatura

Envie o header X-Speakus-Signature com sha256= seguido do HMAC-SHA256 hexadecimal do corpo cru da requisição.

Serialize o JSON uma única vez, assine essa string e envie essa mesma string. Re-serializar o objeto depois de assinar é a causa nº 1 de 401.

Exemplo

curl -X POST https://app.speakus.app/v1/hooks/inbound/wk_SUA_CHAVE \
  -H "Content-Type: application/json" \
  -H "X-Speakus-Signature: sha256=ASSINATURA_DO_CORPO" \
  -d '{
    "eventId": "trial_usr_412",
    "event": "trial_ended",
    "occurredAt": "2026-07-27T18:00:00Z",
    "lead": {
      "phone": "+5585999998888",
      "name": "Marina Silva",
      "email": "marina@empresa.com",
      "externalId": "usr_412"
    },
    "data": {
      "plan": "pro",
      "trial_days": 14,
      "last_feature_used": "relatorios",
      "login_count": 7
    }
  }'

Os dados do lead são dinâmicos

Em data você manda o que quiser sobre o usuário — qualquer chave escalar válida é aceita e vira contexto para a conversa. Quanto mais o funcionário de IA souber, melhor a primeira mensagem: plano testado, dias de trial, última funcionalidade usada, etapa onde a pessoa travou no onboarding, valor do carrinho.

  • Chaves em snake_case começando por letra; até 30 por evento.
  • Valores escalares: texto, número, booleano ou data ISO. Objetos aninhados são ignorados.
  • O tipo é inferido automaticamente e o contrato do evento aprende as chaves novas — elas aparecem na tela de Gatilhos do funcionário.
  • Um dado que a IA já descobriu conversando nunca é sobrescrito pelo webhook.

Idempotência

Use um eventId único e determinístico por acontecimento, como trial_<userId>. Reenviar o mesmo eventId devolve a mesma resposta sem criar lead nem abordagem duplicados — então retry após timeout é seguro.

Node.js

import crypto from 'node:crypto'

async function speakusNotify(event, eventId, lead, data = {}) {
  const raw = JSON.stringify({ eventId, event, occurredAt: new Date().toISOString(), lead, data })
  const signature = 'sha256=' + crypto
    .createHmac('sha256', process.env.SPEAKUS_WEBHOOK_SECRET)
    .update(raw, 'utf8')
    .digest('hex')

  const res = await fetch(process.env.SPEAKUS_WEBHOOK_URL, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json', 'X-Speakus-Signature': signature },
    body: raw, // a MESMA string que foi assinada
  })
  if (res.status >= 500) throw new Error('retry seguro: a chamada é idempotente por eventId')
  return res.json()
}

// 1) o trial acabou e o usuário não assinou
await speakusNotify('trial_ended', `trial_${user.id}`,
  { phone: user.phoneE164, name: user.name, email: user.email, externalId: String(user.id) },
  { plan: user.trialPlan, trial_days: 14, login_count: user.loginCount })

// 2) o usuário voltou e assinou — fecha o ciclo
await speakusNotify('converted', `conv_${user.id}`,
  { phone: user.phoneE164 }, { plan_purchased: user.plan, mrr: user.mrr })

Respostas

CódigoSignificado
202Aceito. O corpo traz leadId, scheduledMessageId e avisos não bloqueantes.
400eventId ausente, JSON inválido ou corpo acima de 64 KB.
401Assinatura ausente ou inválida — confira se assinou o corpo cru com o segredo certo.
403Webhook pausado no painel.
404ingestKey desconhecida.
422Evento fora do catálogo do workspace, ou telefone fora do formato E.164.
5xxFalha nossa. Refaça a chamada com o mesmo eventId — é idempotente.

Recursos para máquinas

O Speakus está em lista de espera. Entre na fila para receber acesso e as credenciais.