CashOut Webhook (Withdrawals)
Receive automatic notifications about the status of your withdrawal requests.
Endpoint and Authentication
URL set by you through the /api/SendWebhook route
You configure the webhook URL. Example: https://mysite.com/api/webhook/baanko
Headers Sent
Headers
Content-Type: application/jsonX-Webhook-Event-Id: <event id, the same on every retry>X-Webhook-Correlation-Id: <id>X-Webhook-Sent-At: 2025-11-27T10:12:34ZX-Webhook-Attempt: 1X-Webhook-Secret: <your webhook secret, when configured>Use X-Webhook-Event-Id to ignore duplicates, and compare X-Webhook-Secret with the secret you configured to make sure the call came from Baanko.
Real CashOut Webhook Example
Webhook Payload - Successful
{ "object": "withdraw", "type": "cashout", "status": "successful", "companyId": 1, "withdrawId": 7184, "value": 10, "valueInCents": 1000, "currency": "BRL", "provider": "A55", "providerStatus": 1, "providerTid": "wld-00007184", "providerPaymentId": "uuid-provider", "endToEndId": "Exxxxxxxx", "providerAmount": 10, "providerConfirmedAt": "2025-11-27T10:12:33Z", "providerDebitedAt": null, "providerPayload": { }, "pixKey": "key", "pixKeyType": "CPF", "creditorDocument": "xxx", "payer": { "name": "BANK/PROVIDER NAME", "document": "xxx", "ispb": "xxxxx", "agency": "xxxx", "account": "xxxx" }, "receiver": { "name": "CUSTOMER NAME", "document": "xxx", "ispb": "xxxx", "agency": "xxxx", "account": "xxxx" }, "createdAt": "2025-11-27T00:00:00Z", "updatedAt": "2025-11-27T00:00:00Z", "processedAt": "2025-11-27T00:00:00Z", "metadata": null}Field Descriptions
objectstringAlways 'withdraw'typestringEvent type - always 'cashout'statusstringFinal status: successful, failure, refundedcompanyIdnumberID of the company that owns the withdrawalwithdrawIdnumberBaanko's internal withdrawal IDvaluenumberWithdrawn amount in reaisvalueInCentsnumberWithdrawn amount in centscurrencystringCurrency (always 'BRL')providerstringProvider used (e.g. 'A55')providerStatusnumberNumeric code returned by the providerproviderTidstringWithdrawal TID at the providerproviderPaymentIdstringPayment ID at the provider (UUID)endToEndIdstringUnique PIX code of the withdrawal (E2E). Can be used for PIX Out lookups.providerAmountnumberAmount confirmed by the providerproviderConfirmedAtstringDate/time the provider confirmed itproviderDebitedAtstring|nullDate/time the account was debited (if available)providerPayloadobjectFull raw response from the providerpixKeystringDestination PIX keypixKeyTypestringKey type (CPF, CNPJ, EMAIL, PHONE, EVP)creditorDocumentstringBeneficiary's documentpayerobjectPayer data (bank/provider)receiverobjectReceiver data (customer)createdAtstringDate/time the withdrawal was createdupdatedAtstringDate/time of the last updateprocessedAtstringDate/time the provider processed the withdrawalmetadatastring|object|nullCustom metadata sent with the requestImportant Notes
OK
Baanko stores the endToEndId automatically,
so you can also look the withdrawal up by it later (see Get Withdrawal).
OK
How to use the endToEndId:
- Check the PIX-out status with the provider
- Trace it for bank audits
- Show the details in your own dashboard
When Is the Webhook Sent?
The webhook is sent whenever:
- The withdrawal is confirmed (successful)
- The withdrawal is refunded (refunded)
- The withdrawal is rejected (failure)
Possible Statuses
pendingRequested, waiting
successfulPaid
failureFailed / rejected
Automatic Retries
OKThe first delivery is immediate. Reply with any 2xx status within 10 seconds to confirm receipt.
OKAny other response, or a timeout, is retried up to 16 times at growing intervals (5s, 15s, 30s, 1 min, 2 min, 5 min ... up to 24 h), for about 2 days in total.
OKRetries keep the same X-Webhook-Event-Id, so you can safely skip an event you already processed. X-Webhook-Attempt tells you which attempt it is.
Response Example
Response
{ "received": true, "idempotent": false }Handler Example
Node.js / Express
app.post('/webhook/baanko/cashout', async (req, res) => { const { type, status, withdrawId, value, valueInCents, endToEndId, providerConfirmedAt, receiver } = req.body; const eventId = req.headers['x-webhook-event-id']; // Check the secret you configured if (req.headers['x-webhook-secret'] !== process.env.BAANKO_WEBHOOK_SECRET) { return res.status(401).end(); } // Skip events that were already processed if (await checkIdempotency(eventId)) { return res.status(200).json({ received: true, idempotent: true }); } if (type === 'cashout') { switch (status) { case 'successful': console.log(`Withdrawal ${withdrawId} confirmed: R$ ${value}`); console.log(`Amount in cents: ${valueInCents}`); console.log(`E2E: ${endToEndId}`); console.log(`Confirmed at: ${providerConfirmedAt}`); console.log(`Recipient: ${receiver.name}`); await updateWithdrawStatus(withdrawId, 'confirmed'); break; case 'failure': console.log(`Withdrawal ${withdrawId} failed`); await updateWithdrawStatus(withdrawId, 'failed'); // Notify the user about the failure break; } } await markAsProcessed(eventId); res.status(200).json({ received: true, idempotent: false });});