Configuring a webhook
1
Open the Dashboard
Go to Webhooks → Add webhook in your project.
2
Provide the URL
Enter your application’s HTTPS URL that will receive the events (e.g.
https://yourapi.com/webhooks/bob).3
Copy the secret
A secret is generated automatically. Store it to verify the authenticity of the requests.
Webhooks work normally in the sandbox. Use them to test the full flow before going to production.
Payload versions (v1 and v2)
The webhook payload is versioned. The version is pinned per channel (dashboard webhooks) or per session (checkout):- New channels created in the dashboard start on v2.
- Existing channels stay on v1 until you migrate — once your consumer is ready, update the channel with
webhookApiVersion: "v2"(via the dashboard orPATCH /api/v1/notification-channels/:id). - The v1 shape is frozen: it never changes. All payload evolution happens on v2.
transaction.paid on v2 (note apiVersion and amountCents):
Available events
The examples below show the v1 (legacy) format. On v2, the only data difference is that
data.amount (reais) is replaced by data.amountCents (cents) and the envelope gains apiVersion: "v2" — all other fields are identical.transaction.created
transaction.created
Fired when a PIX charge is created. Includes
pixCode and expirationDate.transaction.paid
transaction.paid
Fired when a PIX payment is confirmed. Use it to release the product or service to the customer. Includes
fee when a fee applies.transaction.expired
transaction.expired
Fired when a transaction expires without payment. Use it to notify the customer or create a new charge.
transaction.refunded
transaction.refunded
Fired when a transaction is refunded.
transaction.cancelled
transaction.cancelled
Fired when a transaction is cancelled manually.
transaction.failed
transaction.failed
Fired when a transaction fails during processing.
Verifying the signature
Every request includes two security headers:
Always verify the signature to make sure the request came from Bob Payments.
With the Node.js SDK (recommended)
The SDK automatically detects the format (v1 or v2), compares in constant time, and applies anti-replay protection:v2 signature (anti-replay)
On v2, the header has the formatt=<unix>,v1=<hex>. The HMAC covers timestamp + "." + body, so a captured webhook can’t be replayed later — reject events whose t is outside a tolerance window (recommended: 5 minutes).
v1 signature (legacy)
On v1, the header is the HMAC-SHA256 hex of the body, with no timestamp:Next steps
Idempotency
Handle repeated deliveries without releasing the order twice.
Test in the sandbox
Fire
transaction.paid and transaction.expired without real money.