PayZuDocs

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

StatusMeaning
REQUESTEDRequest received. The amount and the fee have already left the available balance.
CREATEDRegistered at the bank.
APPROVEDApproved, on its way. The money has not been delivered yet.
CONFIRMEDThe money arrived. Webhook: WITHDRAW_COMPLETED.
FAILEDIt 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 sendThe API responds
The same key, with the same amount and the same pixKeyThe existing withdrawal, in its current status. No new Pix goes out.
The same key, with another amount or another pixKey409 WITHDRAW_IDEMPOTENCY_KEY_REUSED.
No keyA 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: 422 WITHDRAW_INSUFFICIENT_BALANCE, with details.available and details.required. WITHDRAW_INSUFFICIENT_PROVIDER_BALANCE: the bank does not cover the withdrawal at that moment, even with enough available.
  • The amount must be between the account's minimum and maximum withdrawal, in withdraw in 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; 0 blocks every withdrawal and limit: null means no cap. Going over it responds 422 WITHDRAW_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 429 with Retry-After.

Lookups and receipts

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.

On this page