For AI agents: a documentation index is available at the root level at /llms.txt and /llms-full.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
StatusDashboard
  • Getting Started
    • Introduction
    • Authentication
    • Rate Limits
    • Error Handling
  • Guides
    • Cash-In (Receiving Payments)
    • Cash-Out (Sending Payments)
    • PIX Keys Management
    • Webhooks Integration
    • MED (Special Returns)
  • API Reference
LogoLogo
StatusDashboard
On this page
  • Webhooks Integration
  • How It Works
  • Step 1 — Create a Webhook
  • Step 2 — Validate Signatures
  • Supported Events
  • PIX Cash-In Events
  • PIX Cash-Out Events
  • Other Events
  • Notification Payload
  • Transaction Statuses in Payloads
  • Automatic Retries
  • Managing Webhooks
  • List Webhooks
  • Get Webhook by ID
  • Update Webhook
  • Delete Webhook
  • Monitoring Deliveries
  • List Deliveries
  • Get Delivery by ID
  • Resend a Failed Delivery
  • Best Practices
Guides

Webhooks Integration

Was this page helpful?
Edit this page
Previous

MED (Special Returns)

Next
Built with

Webhooks Integration

Webhooks allow your system to receive real-time HTTP notifications whenever events occur in your BRZ account — such as incoming PIX payments, completed cash-outs, limit approvals, and more.

Instead of polling the API for status changes, you register a URL and the BRZ platform pushes event data to your server as soon as it happens.

Webhook endpoints require Bearer Token or API Key authentication with webhooks:read and/or webhooks:write scopes.

How It Works

  1. You register a webhook URL in the BRZ API
  2. When an event occurs (e.g., a PIX payment is received), the system sends an HTTP POST to your URL
  3. Your server processes the notification and returns HTTP 200
  4. If delivery fails, the system retries automatically with exponential backoff

Step 1 — Create a Webhook

Register a new webhook to start receiving notifications:

$curl -X POST https://api.brzip.com.br/api/v1/webhooks \
> -H "Authorization: Bearer <your-jwt>" \
> -H "Content-Type: application/json" \
> -d '{
> "url": "https://your-system.com/webhooks/pix",
> "events": [
> "pix.cash_in.confirmed",
> "pix.cash_in.received",
> "pix.cash_out.completed",
> "onboarding.status_changed",
> "limits.request_approved",
> "limits.request_rejected"
> ]
> }'

Request fields:

FieldRequiredDescription
urlYesHTTPS URL that will receive the notifications
eventsNoList of events to subscribe to. If empty or ["*"], receives all events

Response:

1{
2 "success": true,
3 "data": {
4 "id": "wh_abc123-def456-ghi789",
5 "url": "https://your-system.com/webhooks/pix",
6 "events": ["pix.cash_in.confirmed", "pix.cash_in.received", "pix.cash_out.completed"],
7 "status": "active",
8 "secret": "whsec_a1b2c3d4e5f6g7h8i9j0..."
9 }
10}

The secret is returned only at creation time. Store it securely — you will need it to validate webhook signatures.

Step 2 — Validate Signatures

Every webhook delivery includes two headers for signature verification:

HeaderDescription
x-webhook-timestampUnix timestamp of when the webhook was sent
x-webhook-signatureHMAC-SHA256 signature of the payload

The signing process works as follows:

  1. Remove the whsec_ prefix from the signing key (the secret returned at creation time)
  2. Concatenate the timestamp header value + "." + raw request body
  3. Compute HMAC-SHA256 of the concatenated string using the secret
  4. Compare the result with the x-webhook-signature header

Always use the raw request body (not a parsed/re-serialized JSON) to compute the signature. Re-serializing may change field ordering and break validation.

1const crypto = require('crypto');
2
3function verifyWebhookSignature(rawBody, signingKey, headers) {
4 // 1. Remove "whsec_" prefix from the key
5 const secret = signingKey.replace('whsec_', '');
6
7 // 2. Get timestamp from header
8 const timestamp = headers['x-webhook-timestamp'];
9
10 // 3. Concatenate timestamp + "." + raw body
11 const signedPayload = timestamp + '.' + rawBody;
12
13 // 4. Compute HMAC-SHA256
14 const expected = 'sha256=' + crypto
15 .createHmac('sha256', secret)
16 .update(signedPayload)
17 .digest('hex');
18
19 // 5. Compare with the received header
20 const received = headers['x-webhook-signature'];
21 return crypto.timingSafeEqual(
22 Buffer.from(expected),
23 Buffer.from(received)
24 );
25}
1import hmac
2import hashlib
3
4def verify_webhook_signature(raw_body: str, signing_key: str, headers: dict) -> bool:
5 # 1. Remove "whsec_" prefix from the key
6 secret = signing_key.replace('whsec_', '')
7
8 # 2. Get timestamp from header
9 timestamp = headers['x-webhook-timestamp']
10
11 # 3. Concatenate timestamp + "." + raw body
12 signed_payload = timestamp + '.' + raw_body
13
14 # 4. Compute HMAC-SHA256
15 expected = 'sha256=' + hmac.new(
16 secret.encode(),
17 signed_payload.encode(),
18 hashlib.sha256
19 ).hexdigest()
20
21 # 5. Compare with the received header
22 received = headers['x-webhook-signature']
23 return hmac.compare_digest(expected, received)

Supported Events

PIX Cash-In Events

EventDescription
pix.cash_in.confirmedPayment received — funds credited to account
pix.cash_in.receivedCharge confirmed — QR Code generated and ready for payment
pix.cash_in.expiredCharge expired without payment
pix.cash_in.cancelledCharge was cancelled
pix.cash_in.refundedPayment was refunded to the payer

PIX Cash-Out Events

EventDescription
pix.cash_out.completedPayment sent successfully
pix.cash_out.failedPayment failed
pix.cash_out.returnedPayment was returned by the recipient’s bank

Other Events

EventDescription
onboarding.status_changedAccount onboarding status changed
limits.request_approvedLimit change request approved
limits.request_rejectedLimit change request rejected
pix.infraction.receivedPIX infraction notification received
pix.med_refund.receivedMED refund request received
payment_link.paidPayment link paid
payment_link.expiredPayment link expired

Use ["*"] in the events field to subscribe to all events at once.

Notification Payload

Every webhook delivery sends an HTTP POST to your URL with a JSON payload:

1{
2 "event": "pix.cash_in.received",
3 "timestamp": "2026-03-15T14:30:00.000Z",
4 "data": {
5 "id": "txn_abc123",
6 "external_id": "order-12345",
7 "type": "cash_in",
8 "status": "completed",
9 "amount": "150.00",
10 "payer_name": "John Doe",
11 "payer_document": "123.456.789-00",
12 "created_at": "2026-03-15T14:28:00.000Z",
13 "completed_at": "2026-03-15T14:30:00.000Z"
14 }
15}

Transaction Statuses in Payloads

StatusDescription
pendingPending processing
processingBeing processed
completedSuccessfully completed
failedFailed
expiredExpired
cancelledCancelled
refundedRefunded (cash-in)
returnedReturned (cash-out)

Automatic Retries

If your URL returns an error (HTTP status >= 400 or timeout), the system automatically retries with exponential backoff:

AttemptDelay
1st retry1 minute
2nd retry5 minutes
3rd retry30 minutes
4th retry1 hour
5th retrySent to DLQ (Dead Letter Queue)

After all retries are exhausted, the delivery is marked as failed. You can manually resend it later.

Managing Webhooks

List Webhooks

Retrieve all registered webhooks:

$curl -X GET "https://api.brzip.com.br/api/v1/webhooks?limit=20&offset=0" \
> -H "Authorization: Bearer <your-jwt>"

Query parameters:

ParameterDefaultDescription
limit20Items per page (max 100)
offset0Pagination offset

Get Webhook by ID

Retrieve details of a specific webhook, including status and last activity timestamps:

$curl -X GET https://api.brzip.com.br/api/v1/webhooks/<webhook-id> \
> -H "Authorization: Bearer <your-jwt>"

Update Webhook

Update an existing webhook. All fields are optional — send only what you want to change:

$curl -X PUT https://api.brzip.com.br/api/v1/webhooks/<webhook-id> \
> -H "Authorization: Bearer <your-jwt>" \
> -H "Content-Type: application/json" \
> -d '{
> "url": "https://your-system.com/webhooks/pix-v2",
> "events": ["*"],
> "status": "active"
> }'

Updatable fields:

FieldTypeDescription
urlstringNew destination URL
eventsarrayNew list of events (use ["*"] for all)
statusstring"active" or "inactive"

Delete Webhook

Permanently remove a webhook. Pending deliveries for this webhook will be cancelled.

$curl -X DELETE https://api.brzip.com.br/api/v1/webhooks/<webhook-id> \
> -H "Authorization: Bearer <your-jwt>"

This action is irreversible. All pending deliveries for this webhook will be cancelled.

Monitoring Deliveries

List Deliveries

View the delivery history for your webhooks. Each delivery shows the event, status, payload sent, response received, attempt count, and timestamps.

$curl -X GET "https://api.brzip.com.br/api/v1/webhooks/deliveries?webhook_id=<webhook-id>&limit=20&page=1" \
> -H "Authorization: Bearer <your-jwt>"

Available filters:

ParameterDescription
webhook_idFilter by webhook ID (UUID)
transaction_idFilter by transaction ID (UUID)
event_typeFilter by event type (e.g., pix.cash_in.confirmed)
statusFilter by status: delivered, pending, failed
start_dateFilter by start date (YYYY-MM-DD)
end_dateFilter by end date (YYYY-MM-DD)

Pagination:

ParameterDefaultDescription
page1Page number (1-based)
limit50Items per page (max 100)
offset—Alternative to page-based pagination (0-based)

Response includes: page, totalPages, total, limit, offset, and an array of deliveries with payload and response_body.

Get Delivery by ID

Retrieve details of a specific delivery, including the payload sent, HTTP response status, and number of attempts:

$curl -X GET https://api.brzip.com.br/api/v1/webhooks/deliveries/<delivery-id> \
> -H "Authorization: Bearer <your-jwt>"

Resend a Failed Delivery

Manually resend a delivery that failed or was not delivered. Useful when:

  • Your URL was down and is now back online
  • You missed a notification and need to reprocess it
  • You want to test your integration with real data
$curl -X POST https://api.brzip.com.br/api/v1/webhooks/deliveries/<delivery-id>/resend \
> -H "Authorization: Bearer <your-jwt>"

The delivery will be re-queued and delivered on the next worker execution cycle.

Best Practices

  1. Always validate signatures — Use the secret from webhook creation to verify that requests are authentic.
  2. Return HTTP 200 quickly — Process the webhook asynchronously if needed. The system considers any non-2xx response as a failure and will retry.
  3. Handle duplicates — Use the transaction_id or delivery_id to deduplicate notifications, as retries may deliver the same event more than once.
  4. Use event filtering — Subscribe only to the events you need instead of ["*"] to reduce noise and processing overhead.
  5. Monitor delivery status — Regularly check the deliveries endpoint to identify and troubleshoot failed deliveries.
  6. Store the secret securely — The webhook secret is only shown once at creation. If lost, you must delete and recreate the webhook.
  7. Use HTTPS — Webhook URLs must use HTTPS to ensure data is encrypted in transit.