Pix withdrawals
Send money from the account to a Pix key and know when it reached the destination.
The amount you request is what reaches the destination; the fee is added on top. Both leave the available balance at the time of the request and come back if the withdrawal fails.
Check who receives
Optional. To show the key holder before confirming, use Look up recipient.
Request the withdrawal
POST /transactions/withdraw, scope WITHDRAW. Required: amount, in cents, and pixKey, the destination key.
Generate an Idempotency-Key for each withdrawal and store it with your record. Repeating the call with the same key returns the existing withdrawal, without sending another Pix.
IDEMPOTENCY_KEY=$(uuidgen)
curl -X POST https://api.hub.payzu.com.br/api/v1/transactions/withdraw \
-H "Authorization: Bearer $PAYZU_TOKEN" \
-H "Idempotency-Key: $IDEMPOTENCY_KEY" \
-H "Content-Type: application/json" \
-d '{
"amount": 10000,
"pixKey": "fulano@exemplo.com",
"pixKeyType": "EMAIL",
"comment": "Repasse semanal"
}'import crypto from 'node:crypto';
const idempotencyKey = crypto.randomUUID();
const res = await fetch('https://api.hub.payzu.com.br/api/v1/transactions/withdraw', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.PAYZU_TOKEN}`,
'Idempotency-Key': idempotencyKey,
'Content-Type': 'application/json',
},
body: JSON.stringify({
amount: 10000,
pixKey: 'fulano@exemplo.com',
pixKeyType: 'EMAIL',
comment: 'Repasse semanal',
}),
});
const saque = await res.json();Also send pixKeyType (CPF, CNPJ, EMAIL, PHONE or EVP). Without it, the type is inferred from the format, and an 11-digit mobile number can be read as a CPF. A type that does not match the key is refused with 400 WITHDRAW_PIX_KEY_TYPE_MISMATCH, and nothing leaves the balance.
comment goes to the recipient when their bank displays it. callbackUrl receives this withdrawal's webhooks and requires the callback secret. All fields are in Withdraw to Pix key.
Store the withdrawal
The response (201) carries the withdrawal. Store the id.
{
"id": "hubp-20261005R4D8TN2WQZ127431",
"status": "APPROVED",
"amount": 10000,
"serviceFee": 250,
"totalDebited": 10250,
"pixKey": "fulano@exemplo.com",
"comment": "Repasse semanal",
"e2e": null,
"providerRejectedReason": null,
"callbackUrl": null,
"createdAt": "2026-10-05T14:40:11.002Z",
"sentAt": "2026-10-05T14:40:11.380Z",
"approvedAt": "2026-10-05T14:40:11.702Z",
"confirmedAt": null
}totalDebited is what left the account: amount + serviceFee. With a fee of 1.5% + R$ 1.00, a R$ 100.00 withdrawal debits R$ 102.50.
Confirm delivery
The withdrawal is delivered when the WITHDRAW_COMPLETED webhook arrives, with status: "CONFIRMED". If it fails, WITHDRAW_FAILED arrives.
To check at any time, call GET /transactions/withdraw/{withdrawId}, scope WITHDRAW_READ, with the id from the response or the withdrawId from the webhook.
In the lookup and in the list, the key comes in destination.pixKey, masked when it is a CPF, email or phone number. Only the POST response carries pixKey at the root.
Withdrawal status
| Status | Meaning |
|---|---|
REQUESTED | Request received. The amount and the fee have already left the available balance. |
CREATED | Registered at the bank. |
APPROVED | Approved, on its way. The money has not been delivered yet. |
CONFIRMED | The money arrived. Webhook: WITHDRAW_COMPLETED. |
FAILED | It did not go out, and the amount and the fee came back to the balance. It can come from any previous status. Webhook: WITHDRAW_FAILED. |
Repeated request
The Idempotency-Key has 1 to 255 visible ASCII characters, with no spaces. It is valid per account and does not expire.
| You send | The API responds |
|---|---|
The same key, with the same amount and the same pixKey | The existing withdrawal, in its current status. No new Pix goes out. |
The same key, with another amount or another pixKey | 409 WITHDRAW_IDEMPOTENCY_KEY_REUSED. |
| No key | A new withdrawal on each request. |
comment and callbackUrl are not part of the comparison.
On a 502 with PROVIDER_UNAVAILABLE, or PROVIDER_REFUSED with details.status 408 or 429, the Pix may have gone out, and the amount stays out of the available balance until the result is checked with the bank. Repeat with the same Idempotency-Key, which returns the original withdrawal, or look for the withdrawal in GET /transactions/withdraw before requesting again. Any other PROVIDER_REFUSED is a final refusal: the amount comes back right away and the withdrawal becomes FAILED.
Balance and limits
- Insufficient balance refuses the whole withdrawal, with no partial withdrawal:
422WITHDRAW_INSUFFICIENT_BALANCE, withdetails.availableanddetails.required.WITHDRAW_INSUFFICIENT_PROVIDER_BALANCE: the bank does not cover the withdrawal at that moment, even with enoughavailable. - The amount must be between the account's minimum and maximum withdrawal, in
withdrawin the limits. - There is a daily cap on Pix outflows, adding up withdrawals and Pix copy-and-paste payments. The cap and how much was already used that day are in
dailyWithdraw;0blocks every withdrawal andlimit: nullmeans no cap. Going over it responds422WITHDRAW_DAILY_LIMIT. - Up to 5 requests per minute per credential and 10 per account, counted together with Pix copy-and-paste payments and refunds. Above that, the API responds
429withRetry-After.
Lookups and receipts
- List:
GET /transactions/withdraw, scopeWITHDRAW_READ, paginated by cursor. It also includes Pix copy-and-paste payments, withoperation: "EXTERNAL_PAYMENT". - Receipt:
GET /transactions/withdraw/{withdrawId}/receiptreturns the PDF in base64, for aCONFIRMEDwithdrawal.
Returned Pix
When the recipient returns the Pix, the amount comes back to the balance. Most of the time the WITHDRAW_REFUND_RECEIVED webhook arrives, with no fee. Details in Pix received without a charge.
The rejections, with the code, are in Withdraw to Pix key.