Webhooks
Receba eventos HTTP em tempo real na sua URL — pagamentos, estornos e status do seller.
Webhooks são configurados por seller via API (autenticação com X-Api-Key). A Reborn envia um POST JSON para a URL cadastrada sempre que um evento ocorre e as condições abaixo são atendidas.
- Cadastrar a URL em
POST /v1/sellers/{sellerId}/webhookscom oseventTypesdesejados. - Guardar o
secretretornado na criação — ele não é exibido novamente e serve para validar o headerX-Reborn-Signature. - No dashboard do seller, em Configurações → Notificações, manter o canal Webhook habilitado para o tipo de evento (ex.: pagamento confirmado, estorno).
- Endpoint público em HTTPS, respondendo
2xxem até alguns segundos.
curl -X POST "https://sandbox-api.rebornpay.io/v1/sellers/{sellerId}/webhooks" \
-H "Content-Type: application/json" \
-H "X-Api-Key: rk_..." \
-d '{
"url": "https://seuservidor.com/webhooks/rebornpay",
"eventTypes": ["TRANSACTION_PAID", "TRANSACTION_REFUNDED"],
"description": "ERP produção"
}'Use ALL em eventTypes para assinar todos os tipos suportados, ou liste explicitamente (recomendado em produção).
| eventType (cadastro) | Quando dispara |
|---|---|
| TRANSACTION_PAID | Pagamento confirmado (PIX, cartão, etc.) |
| TRANSACTION_REFUNDED | Estorno concluído na adquirente |
| TRANSACTION_CANCELLED | Transação cancelada ou recusada após 3DS (status FAILED/CANCELLED) |
| SELLER_STATUS_CHANGED | KYC aprovado ou rejeitado |
| CHARGEBACK_RECEIVED | Chargeback de cartão, alerta de pre-chargeback ou MED Pix aberto |
| CHARGEBACK_RESOLVED | Disputa encerrada, com result WON ou LOST |
| SETTLEMENT_PAID | Liquidação paga ao seller |
| PAYMENT_LINK_* | Criação, atualização ou expiração de link |
| PAYOUT_CREATED | Saque PIX solicitado |
| PAYOUT_PAID | Saque PIX pago |
| PAYOUT_PARTIALLY_PAID | Saque PIX pago parcialmente |
| PAYOUT_FAILED | Saque PIX rejeitado ou com erro |
| PAYOUT_REFUNDED | Saque PIX pago e devolvido pelo banco do recebedor. O valor volta ao saldo |
Cada entrega é um POST com JSON no body. Além de Content-Type, a Reborn envia o header de assinatura abaixo.
| Header | Valor |
|---|---|
| Content-Type | application/json |
| Accept | application/json |
| X-Reborn-Signature | HMAC-SHA256 do body bruto (hex minúsculo), usando o secret do webhook |
POST /webhooks/rebornpay HTTP/1.1
Host: seuservidor.com
Content-Type: application/json
Accept: application/json
X-Reborn-Signature: a1b2c3d4e5f6789... // HMAC-SHA256 hex (body bruto + secret)
{"type":"TRANSACTION_PAID","sellerId":"...","occurredAt":"...","data":{...}}Todos os webhooks seguem o envelope abaixo. O campo type repete o tipo do evento;occurredAt está em UTC.
Para TRANSACTION_PAID e TRANSACTION_REFUNDED, data.transaction usa o mesmo schema de GET /v1/transactions/{id} (valores em centavos, documento mascarado). Em PIX pago, paymentDetails.endToEndId é o end-to-end id do pagamento. idempotencyKey é a chave enviada na cobrança, ou a gerada pela Reborn quando o header não veio.
{
"type": "TRANSACTION_PAID",
"sellerId": "ca31b75f-ba3f-491c-9971-aff7d99e4ec5",
"occurredAt": "2026-06-18T03:04:08.479374",
"data": {
"transaction": {
"id": "f81a8a94-b0d8-44f3-850f-aa699e664b62",
"status": "PAID",
"paymentMethod": "PIX",
"amount": 50,
"currency": "BRL",
"description": "Pedido #1234",
"customer": {
"name": "João da Silva",
"email": null,
"document": "***982247-**"
},
"paymentDetails": {
"qrCode": "00020126580014br.gov.bcb.pix...",
"qrCodeUrl": null,
"expiresAt": "2026-06-18T04:00:24.047",
"endToEndId": "E12345678202610091800abcd"
},
"idempotencyKey": "pedido-1234",
"createdAt": "2026-06-18T03:00:21.417691",
"updatedAt": "2026-06-18T03:03:51.161477",
"paidAt": "2026-06-18T03:03:51.141472",
"refunds": []
}
}
}Para PAYOUT_CREATED, PAYOUT_PAID, PAYOUT_PARTIALLY_PAID e PAYOUT_FAILED, data.payout usa o mesmo schema de GET /v1/payouts/{id} (valores em centavos).
{
"type": "PAYOUT_PAID",
"sellerId": "ca31b75f-ba3f-491c-9971-aff7d99e4ec5",
"occurredAt": "2026-06-18T03:04:08.479374",
"data": {
"payout": {
"pixTransactionId": "f81a8a94-b0d8-44f3-850f-aa699e664b62",
"status": "PAID",
"amount": 1000,
"currency": "BRL",
"destinationKey": "cliente@exemplo.com",
"destinationKeyType": "EMAIL",
"description": "Saque PIX",
"createdAt": "2026-06-18T03:00:21.417691",
"requiresApproval": false,
"idempotencyKey": "saque-123",
"paidAmountCents": 1000,
"pendingAmountCents": 0,
"gowdEndToEndId": "E123456789",
"errorMessage": null,
"batchTransactions": []
}
}
}Em TRANSACTION_REFUNDED, status é REFUNDED e refunds lista os estornos com COMPLETED quando aplicável.
CHARGEBACK_RECEIVED e CHARGEBACK_RESOLVED cobrem chargeback de cartão e MED Pix. O campo kind é PIX_MED, CARD_CHARGEBACK ou CARD_PRE_CHARGEBACK. endToEndId vem preenchido no MED e é nulo no cartão. amount está em centavos. Para defender um MED, use chargeId em POST /v1/sellers/{sellerId}/meds/{chargeId}/contest.
{
"type": "CHARGEBACK_RECEIVED",
"sellerId": "ca31b75f-ba3f-491c-9971-aff7d99e4ec5",
"occurredAt": "2026-10-09T18:00:00",
"data": {
"details": {
"kind": "PIX_MED",
"chargeId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"transactionId": "f81a8a94-b0d8-44f3-850f-aa699e664b62",
"endToEndId": "E12345678202610091800abcd",
"amount": 10000,
"reason": "FRAUDE",
"defenseDeadline": "2026-10-16",
"status": "OPEN",
"result": null
}
}
}{
"type": "CHARGEBACK_RESOLVED",
"sellerId": "ca31b75f-ba3f-491c-9971-aff7d99e4ec5",
"occurredAt": "2026-10-12T15:00:00",
"data": {
"details": {
"kind": "PIX_MED",
"chargeId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"transactionId": "f81a8a94-b0d8-44f3-850f-aa699e664b62",
"endToEndId": "E12345678202610091800abcd",
"amount": 10000,
"reason": "FRAUDE",
"defenseDeadline": "2026-10-16",
"status": "RESOLVED",
"result": "LOST"
}
}
}Aceitar um MED (result: LOST) também devolve o PIX e dispara TRANSACTION_REFUNDED quando a adquirente confirma. MED perdido na resolução debita o saldo e não dispara estorno. Chargeback de cartão perdido debita o saldo de cartão e também não dispara TRANSACTION_REFUNDED.
Demais eventos enviam data.details com metadados específicos do evento. O endpoint POST .../webhooks/{id}/test envia o mesmo formato com test: true no body (apenas para validar conectividade — eventos reais de pagamento não incluem esse campo).
O secret é retornado uma única vez ao criar o webhook. Guarde-o no seu servidor (variável de ambiente ou secrets manager) — nunca no frontend.
// Algoritmo (igual em todas as entregas)
// secret = valor retornado em POST /webhooks (whsec_...)
// rawBody = bytes exatos do POST, como string UTF-8, ANTES do JSON.parse
//
// X-Reborn-Signature = HMAC_SHA256(key=secret, message=rawBody).hexdigest()
//
// Node.js:
// crypto.createHmac("sha256", secret).update(rawBody, "utf8").digest("hex")Use o body bruto da requisição (string ou bytes exatos antes do parse). Re-serializar o JSON invalida a assinatura porque a ordem dos campos pode mudar.
import crypto from "node:crypto";
/** Use o body bruto (string) exatamente como recebido — antes do JSON.parse. */
export function verifyRebornWebhook(
rawBody: string,
secret: string,
signatureHeader: string | null,
): boolean {
if (!signatureHeader) return false;
const expected = crypto
.createHmac("sha256", secret)
.update(rawBody, "utf8")
.digest("hex");
try {
return crypto.timingSafeEqual(
Buffer.from(expected, "utf8"),
Buffer.from(signatureHeader, "utf8"),
);
} catch {
return false;
}
}
// Express: app.post('/webhooks/rebornpay', express.raw({ type: 'application/json' }), ...)import hmac
import hashlib
def verify_reborn_webhook(raw_body: bytes, secret: str, signature_header: str | None) -> bool:
if not signature_header:
return False
expected = hmac.new(
secret.encode("utf-8"),
raw_body,
hashlib.sha256,
).hexdigest()
return hmac.compare_digest(expected, signature_header)- Respostas fora da faixa
2xxou timeout (~15s) são reprocessadas até 5 tentativas, com intervalo padrão de 60s entre elas. - Trate cada entrega como idempotente: use
type+data.transaction.id(ou identificador emdata.details) para ignorar duplicatas. - Consulte o histórico em
GET /v1/sellers/{sellerId}/webhooks/deliveries(status, HTTP da última tentativa, erros).
curl "https://sandbox-api.rebornpay.io/v1/sellers/{sellerId}/webhooks/deliveries?limit=20" \
-H "X-Api-Key: rk_..."Dispare um evento de exemplo para validar URL, TLS e verificação de assinatura antes de ir a produção:
curl -X POST "https://sandbox-api.rebornpay.io/v1/sellers/{sellerId}/webhooks/{webhookId}/test" \
-H "X-Api-Key: rk_..."O teste usa o primeiro eventType cadastrado no webhook. Pagamento e saque mandam um exemplo em data.transaction ou data.payout. Chargeback e MED mandam data.details.
No sandbox, o primeiro termo de um campo dispara o cenário e o webhook correspondente alguns segundos depois da resposta de criação. Em produção esses termos são texto comum.
Cobrança PIX: primeiro termo de buyer.name.
PAID— a cobrança fica paga (TRANSACTION_PAID).FAIL— a cobrança falha.REFUND— paga e depois estorna (TRANSACTION_REFUNDED).MED— paga e abre uma MED (CHARGEBACK_RECEIVED), que permanece aberta para contestação.MED_WONeMED_LOST— abre a MED e encerra comCHARGEBACK_RESOLVED(WONouLOST).
Saque PIX: primeiro termo de description.
PAID— saque pago (PAYOUT_PAID).ERROR— o saque fica salvo comoERROR, o webhookPAYOUT_FAILEDé enviado e o POST responde 502.REJECTED— a resposta vemAWAITING_APPROVALe, em seguida, o saque é recusado.SPLIT_PAIDeSPLIT_PARTIAL— exigem amount acima de R$ 15.000. O saque é dividido em parcelas de R$ 15.000 e terminaPAIDouPARTIALLY_PAID.
Exemplo: buyer.name = "MED_LOST João da Silva". Repetir a mesma Idempotency-Key não dispara o cenário de novo.
Schemas completos dos endpoints em API Reference → Webhooks. Autenticação da API em Autenticação.
