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.

  1. Cadastrar a URL em POST /v1/sellers/{sellerId}/webhooks com os eventTypes desejados.
  2. Guardar o secret retornado na criação — ele não é exibido novamente e serve para validar o header X-Reborn-Signature.
  3. No dashboard do seller, em Configurações → Notificações, manter o canal Webhook habilitado para o tipo de evento (ex.: pagamento confirmado, estorno).
  4. Endpoint público em HTTPS, respondendo 2xx em até alguns segundos.

Criar webhook
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_PAIDPagamento confirmado (PIX, cartão, etc.)
TRANSACTION_REFUNDEDEstorno concluído na adquirente
TRANSACTION_CANCELLEDTransação cancelada ou recusada após 3DS (status FAILED/CANCELLED)
SELLER_STATUS_CHANGEDKYC aprovado ou rejeitado
CHARGEBACK_RECEIVEDChargeback de cartão, alerta de pre-chargeback ou MED Pix aberto
CHARGEBACK_RESOLVEDDisputa encerrada, com result WON ou LOST
SETTLEMENT_PAIDLiquidação paga ao seller
PAYMENT_LINK_*Criação, atualização ou expiração de link
PAYOUT_CREATEDSaque PIX solicitado
PAYOUT_PAIDSaque PIX pago
PAYOUT_PARTIALLY_PAIDSaque PIX pago parcialmente
PAYOUT_FAILEDSaque PIX rejeitado ou com erro
PAYOUT_REFUNDEDSaque 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.

HeaderValor
Content-Typeapplication/json
Acceptapplication/json
X-Reborn-SignatureHMAC-SHA256 do body bruto (hex minúsculo), usando o secret do webhook
Exemplo de requisição recebida
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.

TRANSACTION_PAID
{
  "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).

PAYOUT_PAID
{
  "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.

CHARGEBACK_RECEIVED
{
  "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
    }
  }
}
CHARGEBACK_RESOLVED
{
  "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
// 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.

Node.js
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' }), ...)
Python
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 2xx ou 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 em data.details) para ignorar duplicatas.
  • Consulte o histórico em GET /v1/sellers/{sellerId}/webhooks/deliveries (status, HTTP da última tentativa, erros).
Histórico de entregas
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:

Evento de teste
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_WON e MED_LOST — abre a MED e encerra com CHARGEBACK_RESOLVED (WON ou LOST).

Saque PIX: primeiro termo de description.

  • PAID — saque pago (PAYOUT_PAID).
  • ERROR — o saque fica salvo como ERROR, o webhook PAYOUT_FAILED é enviado e o POST responde 502.
  • REJECTED — a resposta vem AWAITING_APPROVAL e, em seguida, o saque é recusado.
  • SPLIT_PAID e SPLIT_PARTIAL — exigem amount acima de R$ 15.000. O saque é dividido em parcelas de R$ 15.000 e termina PAID ou PARTIALLY_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.