Webhooks
Receba no seu servidor cada venda, reembolso, disputa e assinatura, na hora em que acontece.
Um webhook é uma URL sua que a Rivoo chama (POST, JSON) sempre que algo acontece na loja: pedido pago, reembolso, disputa, renovação de assinatura. É o jeito certo de liberar uma compra no seu sistema, em vez de ficar consultando a API.
Cadastrar
No painel, abra Integrações › Webhooks e clique em Adicionar. Ou pela API: Criar webhook.
Informe a URL (HTTPS, pública) e os eventos que ela recebe. Sem eventos marcados, ela recebe todos.
Guarde o segredo de assinatura (whsec_...). Ele aparece só nesta hora e serve para conferir que o pedido veio da Rivoo.
O que chega
POST /webhooks/rivoo HTTP/1.1
Content-Type: application/json
User-Agent: Rivoo-Webhooks/1
webhook-id: evt_mhexample0000event00001
webhook-timestamp: 1793567091
webhook-signature: v1,K5oZfzN95Z9UVu1EsfQmfVNQhnkZ2pj9o9NDN/H/pI4=
{
"id": "evt_mhexample0000event00001",
"type": "order.paid",
"createdAt": "2026-10-31T21:04:51.000Z",
"data": { "object": { "id": "ord_mhexample0000vip0000001", "source": "STOREFRONT", "totalCents": 2990, "paymentId": "pay_mhexample0000vip0000001" } }
}data.object muda conforme o evento: veja a lista de eventos. Valores em dinheiro vêm em centavos (2990 = R$ 29,90).
Verificar a assinatura
O formato segue o padrão aberto Standard Webhooks. A assinatura é um HMAC-SHA256 de webhook-id.webhook-timestamp.corpo, com a chave sendo o segredo sem o prefixo whsec_, decodificado de base64. Compare com cada assinatura do header (separadas por espaço, cada uma com o prefixo v1,): durante a troca do segredo chegam duas.
import { createHmac, timingSafeEqual } from 'node:crypto';
// rawBody: o corpo como string, antes do JSON.parse
export function verify(rawBody, headers, secret = process.env.RIVOO_WEBHOOK_SECRET) {
const id = headers['webhook-id'];
const ts = Number(headers['webhook-timestamp']);
if (Math.abs(Date.now() / 1000 - ts) > 300) return false;
const key = Buffer.from(secret.replace(/^whsec_/, ''), 'base64');
const expected = createHmac('sha256', key).update(`${id}.${ts}.${rawBody}`).digest();
return headers['webhook-signature'].split(' ').some((sig) => {
const got = Buffer.from(sig.replace(/^v1,/, ''), 'base64');
return got.length === expected.length && timingSafeEqual(got, expected);
});
}Responder
Responda 2xx em até 10 segundos. Faça o trabalho pesado depois (fila), não antes de responder. Redirecionamentos não são seguidos.
Novas tentativas
Se a resposta não for 2xx (ou demorar mais de 10 s), a Rivoo tenta de novo: 8 tentativas no total, depois de 1 min, 5 min, 30 min, 2 h, 6 h, 12 h e 24 h. O webhook-id é o mesmo em todas: guarde os ids já processados e ignore repetidos.
Uma URL que falha seguido por mais de 3 dias é desativada, e você recebe um aviso no painel. Reative em Integrações › Webhooks depois de corrigir.
Testar
Use Enviar teste no webhook (ou Testar webhook) para receber um evento de exemplo. Em Envios do webhook você vê cada tentativa com o código de resposta.
Trocar o segredo
Trocar segredo do webhook gera um segredo novo. Por 24 horas as mensagens chegam assinadas com os dois (duas assinaturas no header), para você atualizar sem perder eventos.