Webhooks
Webhooks permitem que o 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 do 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 |
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-1e2f3a4b5c6dO corpo é um envelope com os dados do evento em data. Exemplo de PAYMENT_CONFIRMED de um pagamento com cartão:
{ "eventId": "1a2b3c4d-5e6f-7a8b-9c0d-1e2f3a4b5c6d", "eventType": "PAYMENT_CONFIRMED", "establishmentId": "e1f2a3b4-c5d6-7e8f-9a0b-1c2d3e4f5a6b", "timestamp": "2026-07-18T14:35:04.402942623Z", "data": { "paymentId": "9f8a7b6c-5d4e-4a3b-2c1d-0e9f8a7b6c5d", "establishmentId": "e1f2a3b4-c5d6-7e8f-9a0b-1c2d3e4f5a6b", "establishmentName": "Minha Loja", "receiverId": "c3d4e5f6-a7b8-4c9d-8e0f-1a2b3c4d5e6f", "externalId": "pedido-1042", "referenceId": "CARTAO-4d2a9f1e-8b3c-4a7d-9e6f-1c0b2a3d4e5f", "status": "CONFIRMED", "paymentMethod": "CREDIT_CARD", "installments": 3, "amount": 159.9, "originalAmount": 159.9, "interestAmount": 0.0, "netAmount": 155.44, "refundedAmount": 0, "refundableAmount": 159.9, "description": "Pedido #1042", "customerName": "Maria Silva", "customerEmail": "maria@exemplo.com.br", "cardBrand": "visa", "cardLastFour": "1111", "paidAt": "2026-07-18T14:35:02.184529Z", "expectedSettlementDate": "2026-08-17" }}| Campo | Tipo | Descrição |
|---|---|---|
eventId | string (UUID) | Identificador único do evento, o mesmo do header X-Orcapay-Event-Id |
eventType | string | Tipo do evento, o mesmo do header X-Orcapay-Event |
establishmentId | string (UUID) | Estabelecimento a que o evento pertence |
timestamp | string | Momento em que a notificação foi gerada, em ISO 8601 (UTC). Reentregas mantêm o mesmo valor |
data | objeto | Recurso no momento do evento. Os campos dependem do tipo de evento, veja abaixo |
Tipos e formatos
Seção intitulada “Tipos e formatos”- Valores monetários são números em reais, sem quantidade fixa de casas decimais (
159.9,0). - Campos sem valor chegam como
null. - Dentro de
data, datas e horários usam o mesmo formato ISO 8601 das respostas da API. Instantes (paidAt,reversedAt,openedAt,disputeDeadline,resolvedAt) vêm como string em UTC (2026-07-18T14:35:02.184529Z). Datas sem hora (expectedSettlementDate) vêm como stringAAAA-MM-DD(2026-08-17). - Até setembro de 2026 os instantes chegavam como número de segundos desde 1970-01-01 e
expectedSettlementDatecomo array[ano, mês, dia]. Se a sua integração multiplicapaidAtpor 1000 ou desestrutura esse array, passe a ler as strings ISO 8601. - A ordem das chaves não é fixa e novos campos podem ser incluídos. Leia os campos pelo nome e ignore os que não conhecer.
Eventos de pagamento
Seção intitulada “Eventos de pagamento”No cartão enviado com allowPending: true, o pagamento em análise antifraude chega primeiro como PAYMENT_CREATED com "status": "PENDING" e é fechado depois por PAYMENT_CONFIRMED, PAYMENT_FAILED ou PAYMENT_CANCELLED. Veja Cartão em análise antifraude.
PAYMENT_CREATED, PAYMENT_CONFIRMED, PAYMENT_FAILED e PAYMENT_CANCELLED trazem em data os campos abaixo. PAYMENT_REVERSED e PAYMENT_PARTIALLY_REVERSED trazem os mesmos campos e mais os dados do estorno, descritos em Estornos.
| Campo | Tipo | Descrição |
|---|---|---|
paymentId | string (UUID) | Identificador do pagamento no OrcaPay. É o id retornado na criação e usado em GET /payments/{id} |
establishmentId | string (UUID) | Estabelecimento dono do pagamento |
establishmentName | string | Nome fantasia do estabelecimento. Omitido quando indisponível |
receiverId | string (UUID) | Recebedor do pagamento |
externalId | string | Identificador enviado por você na criação do pagamento |
referenceId | string | Código de referência da cobrança na operadora (PIX-... ou CARTAO-...), o mesmo da coluna “Código de Referência” no relatório do PagBank. Veja Identificadores do pagamento |
status | string | Status do pagamento após o evento, veja Status do pagamento |
paymentMethod | string | PIX, CREDIT_CARD ou DEBIT_CARD |
installments | inteiro | Quantidade de parcelas (1 no Pix e no débito) |
amount | número | Valor cobrado do cliente, incluindo juros de parcelamento repassados |
originalAmount | número | Valor da venda antes dos juros repassados |
interestAmount | número | Juros de parcelamento pagos pelo cliente (amount = originalAmount + interestAmount) |
netAmount | número | Valor líquido após as taxas |
refundedAmount | número | Total já estornado |
refundableAmount | número | Saldo que ainda pode ser estornado |
description | string | Descrição do pagamento |
customerName | string | Nome do cliente |
customerEmail | string | E-mail do cliente |
cardBrand | string | Bandeira do cartão como informada pela operadora (ex.: visa). null no Pix |
cardLastFour | string | Últimos quatro dígitos do cartão. null no Pix |
paidAt | string | Momento da confirmação, em ISO 8601 (UTC). null antes da confirmação |
expectedSettlementDate | string | Data prevista de liquidação, no formato AAAA-MM-DD |
Eventos de chargeback
Seção intitulada “Eventos de chargeback”CHARGEBACK_OPENED, CHARGEBACK_UPDATED e CHARGEBACK_RESOLVED trazem em data o chargeback, e não o pagamento:
| Campo | Tipo | Descrição |
|---|---|---|
chargebackId | string (UUID) | Identificador do chargeback no OrcaPay |
paymentId | string (UUID) | Pagamento contestado. null enquanto o chargeback não estiver vinculado a um pagamento |
establishmentId | string (UUID) | Estabelecimento dono do pagamento |
provider | string | Operadora que notificou o chargeback (ex.: PAGBANK) |
providerChargebackId | string | Identificador do chargeback na operadora |
amount | número | Valor contestado |
currency | string | Moeda (BRL) |
status | string | RECEIVED, AWAITING_EVIDENCE, EVIDENCE_SUBMITTED, UNDER_GATEWAY_REVIEW, SUBMITTED_TO_ISSUER, ACCEPTED_BY_MERCHANT, EXPIRED, WON ou LOST |
statusDescription | string | Descrição do status em português |
classification | string | NOT_RECOGNIZED, DISAGREEMENT, FRAUD_REPORT ou OTHER |
reasonCode | string | Código do motivo da contestação |
cycle | string | Ciclo da disputa informado pela operadora |
openedAt | string | Abertura, em ISO 8601 (UTC) |
disputeDeadline | string | Prazo para enviar a defesa, em ISO 8601 (UTC) |
resolvedAt | string | Resolução, em ISO 8601 (UTC). null enquanto não resolvido |
matchStatus | string | Vínculo com o pagamento: MATCHED, UNMATCHED ou MANUAL |
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 do 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, o 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}, usando opaymentIdrecebido, quando necessário.