Webhooks
Webhooks permitem que a OrcaPay notifique sua aplicação quando algo acontece — por exemplo, quando um pagamento é confirmado. Em vez de consultar a API repetidamente, você recebe um POST na URL que cadastrar.
Configurando
Seção intitulada “Configurando”Cadastre seus endpoints no console da OrcaPay, na seção de Webhooks. Para cada endpoint você define um nome, a URL (HTTPS, acessível publicamente) e os eventos que deseja receber. Ao criar o endpoint é gerado um secret, usado para assinar as notificações.
O secret é exibido uma única vez, na confirmação do cadastro. Copie e guarde em local seguro — ele não pode ser consultado depois. Se você perder o secret, exclua o endpoint e cadastre um novo.
Eventos disponíveis
Seção intitulada “Eventos disponíveis”| Evento | Disparado quando |
|---|---|
PAYMENT_CREATED | Um pagamento é criado |
PAYMENT_CONFIRMED | Um pagamento é confirmado |
PAYMENT_FAILED | Um pagamento não é aprovado |
PAYMENT_CANCELLED | Um pagamento é cancelado |
PAYMENT_REVERSED | O pagamento é estornado integralmente (estorno total ou último estorno parcial) |
PAYMENT_PARTIALLY_REVERSED | Um estorno parcial é concluído e o pagamento ainda tem saldo |
CHARGEBACK_OPENED | Um chargeback é aberto |
CHARGEBACK_UPDATED | O status de um chargeback muda |
CHARGEBACK_RESOLVED | Um chargeback é resolvido |
PIX_KEY_CREATED | Uma chave Pix é criada |
Endpoints cadastrados antes do estorno parcial não recebem PAYMENT_PARTIALLY_REVERSED automaticamente: edite o endpoint no console e marque o evento. Os campos extras dos eventos de estorno estão em Estornos.
Formato da notificação
Seção intitulada “Formato da notificação”Cada notificação é um POST com corpo JSON e três headers de identificação:
POST https://sua-aplicacao.com.br/webhooks/orcapayContent-Type: application/jsonX-Orcapay-Signature: sha256=K7gNU3sdo+OL0wNhqoVWhr3g6s1xYv72ol/pe/Unols=X-Orcapay-Event: PAYMENT_CONFIRMEDX-Orcapay-Event-Id: 1a2b3c4d-5e6f-7a8b-9c0d-1e2f3a4b5c6d{ "eventId": "1a2b3c4d-5e6f-7a8b-9c0d-1e2f3a4b5c6d", "eventType": "PAYMENT_CONFIRMED", "establishmentId": "e1f2a3b4-c5d6-7e8f-9a0b-1c2d3e4f5a6b", "timestamp": "2026-07-18T14:35:00Z", "data": { "id": "9f8a7b6c-5d4e-4a3b-2c1d-0e9f8a7b6c5d", "status": "CONFIRMED", "amount": 159.90, "externalId": "pedido-1042" }}Validando a assinatura
Seção intitulada “Validando a assinatura”Toda notificação é assinada com o secret do endpoint, exibido uma única vez no cadastro. O header X-Orcapay-Signature contém sha256= seguido do HMAC-SHA256 do corpo bruto da requisição, calculado com o secret e codificado em Base64. Recalcule a assinatura do seu lado e compare com o header antes de processar:
const crypto = require('crypto');
function isValidSignature(rawBody, signatureHeader, secret) { const expected = 'sha256=' + crypto .createHmac('sha256', secret) .update(rawBody, 'utf8') .digest('base64'); const received = Buffer.from(signatureHeader ?? ''); const expectedBuffer = Buffer.from(expected); return ( received.length === expectedBuffer.length && crypto.timingSafeEqual(received, expectedBuffer) );}Dois cuidados:
- Use o corpo exatamente como recebido. Se o framework desserializar o JSON e você serializar de novo, a assinatura não vai bater — em Express, por exemplo, capture o corpo bruto com
express.raw({ type: 'application/json' })na rota do webhook. - Compare em tempo constante (como
crypto.timingSafeEqualacima) em vez de===, para não vazar informação por tempo de resposta.
Rejeite qualquer notificação com assinatura inválida — ela não veio da OrcaPay.
Entregas e retentativas
Seção intitulada “Entregas e retentativas”- Uma entrega é considerada bem-sucedida quando seu endpoint responde
2xxem até 10 segundos. - Em caso de falha, a OrcaPay tenta novamente até 5 vezes, com intervalos de 1 minuto, 5 minutos, 15 minutos, 1 hora e 24 horas.
- Após esgotar as tentativas, a entrega é marcada como esgotada e não é reenviada.
Boas práticas
Seção intitulada “Boas práticas”- Responda
2xxo mais rápido possível e processe o evento de forma assíncrona. - Trate eventos de forma idempotente usando o
eventId: o mesmo evento pode ser entregue mais de uma vez. - Não confie apenas no webhook para decisões críticas — confirme o status com
GET /payments/{id}quando necessário.