Documentação para desenvolvedores

Webhooks & API

O Proa Pay envia eventos da escola (lead ganho, fatura paga, matrícula) para o sistema que você quiser — CRM, planilha, automação. Cada entrega é um POST JSON assinado, com re-tentativas automáticas. Conecte direto ou via Make, Pluga, Zapier e n8n.

Visão geral

O fluxo é simples: um fato acontece na escola → o Proa Pay enfileira o evento → um worker entrega via HTTPS POST ao seu endpoint, assinado. Você valida a assinatura, responde 2xx e processa. Se o seu endpoint cair, re-tentamos com backoff.

Nesta primeira versão a saída é somente de eventos (webhooks-out). Uma API de leitura (REST) e conectores nativos vêm a seguir.

Configurar um endpoint

No painel admin, em Conta → Integrações → Criar webhook: informe um nome, a URL HTTPS do seu endpoint e marque os eventos desejados. Ao salvar, enviamos um evento ping de verificação — se ele responder 2xx, o endpoint fica ativo.

Você recebe um segredo de assinatura (whsec_…) uma única vez — guarde-o com segurança; é com ele que você valida cada entrega. Pode pausar, re-verificar e ver o histórico de entregas a qualquer momento.

Formato do evento

Toda entrega tem o mesmo envelope, com os campos específicos em data:

POST https://seu-endpoint.com/webhook
Content-Type: application/json
X-AppmaxEdu-Signature: sha256=<hmac-hex>
X-AppmaxEdu-Timestamp: 1781524667000
Idempotency-Key: 3f1c…(= id do envelope)

{
  "id": "3f1c2b6e-...",          // único por evento — use como chave de dedupe
  "event": "invoice.paid",
  "api_version": "v1",
  "occurred_at": "2026-06-15T13:00:00.000Z",
  "tenant_id": "a03bb4a7-...",   // a escola (estabelecimento)
  "data": { /* payload mínimo do evento — ver catálogo */ }
}

Campos fixos do envelope (iguais em todo evento):

  • idID único do envelope (UUID) — repetido no header Idempotency-Key
  • eventtipo do evento (ex.: 'invoice.paid')
  • api_versionversão do contrato de saída (ex.: 'v1')
  • occurred_atquando o evento ocorreu (ISO 8601, UTC)
  • tenant_idID opaco do estabelecimento que originou o evento
  • dataobjeto com os campos específicos do evento (detalhados por evento abaixo)

Cabeçalhos HTTP de cada entrega (POST application/json):

  • content-typesempre application/json
  • X-AppmaxEdu-Signaturesha256=<HMAC-SHA256 de "{timestamp}.{corpo}" usando o segredo do endpoint>
  • X-AppmaxEdu-Timestampmomento do envio (Unix ms); entra na assinatura — rejeite se diferir mais de 5 min do agora
  • Idempotency-Keyigual ao id do envelope — use para deduplicar reentregas de um mesmo evento

Verificar a assinatura

A assinatura é HMAC-SHA256 sobre `${timestamp}.${corpo}`, com o timestamp também no cabeçalho. Rejeite requisições fora de uma janela de 5 minutos — isso previne ataques de replay. Compare em tempo constante.

import crypto from 'node:crypto';

// Em cada request, valide assinatura + janela de 5 min ANTES de processar.
function verificar(rawBody, headers, secret) {
  const sig = headers['x-appmaxedu-signature'];
  const ts = Number(headers['x-appmaxedu-timestamp']);
  if (!Number.isFinite(ts) || Math.abs(Date.now() - ts) > 5 * 60 * 1000) {
    return false; // fora da janela → possível replay
  }
  const esperado =
    'sha256=' +
    crypto.createHmac('sha256', secret).update(`${ts}.${rawBody}`).digest('hex');
  const a = Buffer.from(esperado);
  const b = Buffer.from(sig ?? '');
  return a.length === b.length && crypto.timingSafeEqual(a, b); // tempo constante
}

Entregas e re-tentativas

Consideramos entregue qualquer resposta 2xx em até 10s. Em falha (timeout, 4xx/5xx), re-tentamos com backoff exponencial + jitter (até 16 tentativas, ~72h). Esgotadas as tentativas, a entrega vai para não-entregue e você pode reenviar manualmente pelo painel.

As entregas são at-least-once: o mesmo evento pode chegar mais de uma vez (ex.: você respondeu 2xx mas demorou). Deduplique pelo Idempotency-Key / id do envelope. Cada (evento, endpoint) é entregue com sucesso no máximo uma vez.

Segurança e LGPD

Por padrão os payloads são minimizados: carregam ids, valores em centavos, status e datas. Dados de contato do pagador (adulto) — CPF, e-mail e nome — só saem quando o dono da escola ativa explicitamente o enriquecimento no endpoint, com aceite de tratamento de dados (DPA). Dados pessoais de alunos menores (nome, CPF, nascimento) nunca são enviados.

Só aceitamos endpoints HTTPS com IP público (bloqueamos redes internas — proteção SSRF), validado a cada envio. Registramos cada entrega (o que saiu, para qual endpoint, quando) para atender pedidos de titular e auditoria.