PiXBrasil.org
Client Portal
MERCHANT WEBHOOKS

Confirmação de pagamento deve chegar ao seu backend assinada.

O PiXBrasil envia eventos somente para endpoints HTTPS registrados pelo merchant. Cada endpoint recebe um signing secret exclusivo guardado em Vault.

Eventos

payment.pending
Estado intermediário. Não entregue produto/serviço apenas com este evento.
payment.succeeded
Confirmação verificada pelo provider. Este é o evento normal para fulfillment.
payment.failed
Falha definitiva conhecida.
payment.canceled
Cancelamento ou estado equivalente confirmado.

1. Registre seu endpoint

Registercurl
curl -X POST https://api.pixbrasil.org/api/v1/webhook-endpoints \
  -H "Authorization: Bearer $PIXBRASIL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Checkout production",
    "endpointUrl": "https://shop.example.com/api/webhooks/pixbrasil",
    "events": ["payment.pending","payment.succeeded","payment.failed","payment.canceled"]
  }'
One-time responsejson
{
  "success": true,
  "data": {
    "endpointId": "uuid",
    "endpointUrl": "https://shop.example.com/api/webhooks/pixbrasil",
    "status": "ACTIVE",
    "signingSecret": "whsec_...",
    "signingAlgorithm": "HMAC-SHA256",
    "signatureHeader": "X-PiXBrasil-Signature",
    "timestampHeader": "X-PiXBrasil-Timestamp"
  }
}

Salve o signingSecret em PIXBRASIL_WEBHOOK_SECRET. Ele é exibido uma única vez.

2. Valide a assinatura

A assinatura é HMAC-SHA256 sobre timestamp + "." + rawBody. O header contém v1=HEX. Compare em tempo constante e rejeite timestamps antigos.

Node.js verificationts
import { createHmac, timingSafeEqual } from "node:crypto";

export function verifyPixBrasilWebhook(rawBody, headers, secret) {
  const timestamp = headers.get("x-pixbrasil-timestamp") || "";
  const received = (headers.get("x-pixbrasil-signature") || "").replace(/^v1=/, "");

  if (!/^\d+$/.test(timestamp)) throw new Error("invalid timestamp");
  if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) throw new Error("expired webhook");

  const expected = createHmac("sha256", secret)
    .update(timestamp + "." + rawBody)
    .digest();
  const receivedBytes = Buffer.from(received, "hex");

  if (expected.length !== receivedBytes.length || !timingSafeEqual(expected, receivedBytes)) {
    throw new Error("invalid signature");
  }
}

3. Faça um handler idempotente

Next.js App Routerts
export async function POST(request) {
  const rawBody = await request.text();
  verifyPixBrasilWebhook(rawBody, request.headers, process.env.PIXBRASIL_WEBHOOK_SECRET);

  const event = JSON.parse(rawBody);
  const deliveryId = request.headers.get("x-pixbrasil-delivery");

  // 1. dedupe by deliveryId in your DB
  // 2. update the order idempotently
  // 3. return 2xx quickly
  // 4. queue analytics/postbacks after the response when possible

  return Response.json({ received: true });
}
Use X-PiXBrasil-Delivery como chave de deduplicação. Responda 2xx rapidamente; não dependa de analytics externo para confirmar o webhook.

Payload de pagamento

payment.succeededjson
{
  "id": "delivery-uuid",
  "type": "payment.succeeded",
  "createdAt": "2026-09-19T...Z",
  "data": {
    "paymentIntentId": "uuid",
    "reference": "ORDER-8472",
    "amount": 149.90,
    "currency": "BRL",
    "status": "SUCCEEDED",
    "store": { "code": "SIGNUM" },
    "provider": { "code": "MISTICPAY", "paymentId": "..." },
    "completedAt": "2026-09-19T...Z",
    "metadata": {
      "orderId": "8472",
      "attribution": { "utm_source": "meta" }
    }
  }
}

Headers enviados

HeaderUso
X-PiXBrasil-EventTipo do evento.
X-PiXBrasil-DeliveryUUID para deduplicação e auditoria.
X-PiXBrasil-TimestampUnix timestamp usado na assinatura.
X-PiXBrasil-Signaturev1=HMAC-SHA256.

Teste antes de receber dinheiro

Use POST /webhook-endpoints/:endpointId/test. O PiXBrasil enviará webhook.test e registrará HTTP status, delivery ID e eventual falha. O endpoint deve responder 2xx.

Precisa integrar agora?

Use o AI Setup Kit e entregue o prompt à IA que já trabalha no seu repositório.

Abrir AI Setup Kits