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
| Header | Uso |
|---|---|
| X-PiXBrasil-Event | Tipo do evento. |
| X-PiXBrasil-Delivery | UUID para deduplicação e auditoria. |
| X-PiXBrasil-Timestamp | Unix timestamp usado na assinatura. |
| X-PiXBrasil-Signature | v1=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?
Abrir AI Setup Kits Use o AI Setup Kit e entregue o prompt à IA que já trabalha no seu repositório.