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/json
X-Webhook-Event-Id: <event id, the same on every retry>
X-Webhook-Correlation-Id: <id>
X-Webhook-Sent-At: 2025-11-27T10:12:34Z
X-Webhook-Attempt: 1
X-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, refunded
companyIdnumberID of the company that owns the withdrawal
withdrawIdnumberBaanko's internal withdrawal ID
valuenumberWithdrawn amount in reais
valueInCentsnumberWithdrawn amount in cents
currencystringCurrency (always 'BRL')
providerstringProvider used (e.g. 'A55')
providerStatusnumberNumeric code returned by the provider
providerTidstringWithdrawal TID at the provider
providerPaymentIdstringPayment ID at the provider (UUID)
endToEndIdstringUnique PIX code of the withdrawal (E2E). Can be used for PIX Out lookups.
providerAmountnumberAmount confirmed by the provider
providerConfirmedAtstringDate/time the provider confirmed it
providerDebitedAtstring|nullDate/time the account was debited (if available)
providerPayloadobjectFull raw response from the provider
pixKeystringDestination PIX key
pixKeyTypestringKey type (CPF, CNPJ, EMAIL, PHONE, EVP)
creditorDocumentstringBeneficiary's document
payerobjectPayer data (bank/provider)
receiverobjectReceiver data (customer)
createdAtstringDate/time the withdrawal was created
updatedAtstringDate/time of the last update
processedAtstringDate/time the provider processed the withdrawal
metadatastring|object|nullCustom metadata sent with the request

Important 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 });
});