Webhook genérico: eventos, payload e assinatura
Receba no seu servidor um POST em JSON a cada evento escolhido, assinado com um segredo que só você e o VSL Max conhecem.
O webhook genérico manda para o seu servidor um POST em JSON sempre que acontece um dos eventos que você escolheu. É o caminho para ligar o VSL Max a um ERP, a uma área de membros ou a qualquer sistema próprio.
Como cadastrar um endpoint
- Abra Configurações › Integrações e, no cartão Webhook genérico, clique em Conectar.
- Em Adicionar endpoint, informe a URL do endpoint. Ela precisa ser
https, sem usuário e senha na URL, na porta padrão, 443 ou 8443, e apontar para um endereço público. Endereço local ou de rede privada é recusado. - Escolha os eventos e clique em Adicionar endpoint.
- Copie o segredo de assinatura que aparece na hora. Ele começa com
whsec_e não aparece de novo: depois disso a tela mostra só os últimos caracteres. Se perder, gere outro.
Só administradores criam e alteram endpoints. A conta aceita até 10 endpoints.
Eventos disponíveis
sale.approved: venda aprovada.sale.refunded: reembolso.sale.chargeback: chargeback.sale.canceled: venda cancelada.video.ready: um vídeo terminou de processar e está pronto.balance.low: o aviso de saldo de plays baixo foi disparado (o mesmo gatilho do e-mail).organization.suspended: a conta foi suspensa.
Se você não escolher nada, o endpoint recebe os quatro eventos de venda. O botão Testar manda um test.ping.
Formato da requisição
Toda entrega leva estes cabeçalhos:
Content-Type: application/jsoneUser-Agent: VSLMax-Webhooks/1.0.X-VSLMax-Event: o tipo do evento, o mesmo do campotypedo corpo.X-VSLMax-Delivery: o id da entrega, igual em todas as tentativas.X-VSLMax-Signature: no formatot=<horário unix>,v1=<assinatura>.
Exemplo de corpo de uma venda aprovada:
{
"id": "evt_3f2a9c1e-8b7d-4e21-9a55-0c1d2e3f4a5b",
"type": "sale.approved",
"createdAt": "2026-09-23T15:04:05.000Z",
"data": {
"sale": {
"id": "3f2a9c1e-8b7d-4e21-9a55-0c1d2e3f4a5b",
"externalId": "HP123456",
"status": "approved",
"amount": 197,
"amountCents": 19700,
"currency": "BRL",
"occurredAt": "2026-09-23T15:03:58.000Z"
},
"conversion": { "id": "…", "name": "Hotmart principal", "platform": "hotmart" },
"video": { "id": "…", "title": "VSL v3" },
"attribution": "key",
"visitorId": "…"
}
}
Em reembolso e chargeback, amount e amountCents vêm negativos. video é null quando a venda não foi atribuída a nenhum vídeo, e attribution diz como ela foi ligada ao vídeo (none quando não foi).
Nos outros eventos, data traz:
video.ready:videocomid,titleedurationSeconds.balance.low:balancecom o aviso, plays inclusos, usados, restantes e o início e fim do ciclo.organization.suspended:organizationcomid,statuse o motivo.test.ping: uma mensagem de teste.
Como verificar a assinatura
Confira a assinatura antes de confiar no corpo:
- Separe
tev1do cabeçalhoX-VSLMax-Signature. - Calcule o HMAC-SHA256, com o seu segredo, do texto formado por
t, um ponto e o corpo cru da requisição (antes de converter o JSON). - Compare o resultado em hexadecimal com
v1, em tempo constante. - Recuse se
testiver a mais de 5 minutos do seu relógio. Isso evita o reenvio de uma requisição capturada. - Use o
iddo evento para ignorar repetições: a retentativa manda o mesmo id.
Exemplo em Node.js:
import crypto from 'node:crypto'
function assinaturaValida(rawBody, header, segredo) {
const partes = Object.fromEntries(header.split(',').map((p) => p.split('=')))
const t = Number(partes.t)
if (Math.abs(Date.now() / 1000 - t) > 300) return false
const esperado = crypto.createHmac('sha256', segredo).update(`${t}.${rawBody}`).digest('hex')
const a = Buffer.from(esperado)
const b = Buffer.from(partes.v1 ?? '')
return a.length === b.length && crypto.timingSafeEqual(a, b)
}
Respostas e retentativas
Responda com qualquer status 2xx em até 10 segundos. Qualquer outra resposta, ou falta de resposta, conta como falha. Redirecionamento não é seguido.
Depois de uma falha, tentamos de novo em 1 minuto, 5 minutos e então a cada 15 minutos, até 6 tentativas no total. Se todas falharem, a entrega fica como falha no histórico do endpoint e o cartão mostra quantas falhas seguidas houve.
Pausar, testar e trocar o segredo
- Testar manda um
test.pingna hora e mostra se foi entregue, o status HTTP e o tempo de resposta. - Últimas entregas lista as entregas recentes do endpoint, com status e número de tentativas.
- Pausar suspende os envios sem apagar o endpoint. Retomar volta a enviar os eventos novos.
- Gerar novo segredo troca o segredo na hora: as próximas entregas já saem assinadas com o novo. Atualize o seu servidor logo em seguida.
- Excluir endpoint pede a sua senha e para as entregas imediatamente. Não tem como desfazer.