PayZuDocs

Create the charge, show the Pix copy-and-paste code to the customer and release the order when the payment arrives.

Create the charge

POST /transactions/payment, scope PAYMENT_WRITE. Required: amount in cents, method: "PIX" and the customer, with customer.name and customer.document (CPF or CNPJ).

Send your order number in externalRef: repeating the call with the same externalRef returns the same charge instead of creating another one.

curl -X POST https://api.hub.payzu.com.br/api/v1/transactions/payment \
  -H "Authorization: Bearer $PAYZU_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 1500,
    "method": "PIX",
    "description": "Pedido 4821",
    "externalRef": "pedido-4821",
    "metadata": { "pedido": "4821", "canal": "checkout-web" },
    "customer": {
      "name": "Maria Souza",
      "document": "52998224725",
      "email": "maria.souza@exemplo.com"
    }
  }'
const res = await fetch('https://api.hub.payzu.com.br/api/v1/transactions/payment', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.PAYZU_TOKEN}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    amount: 1500,
    method: 'PIX',
    description: 'Pedido 4821',
    externalRef: 'pedido-4821',
    metadata: { pedido: '4821', canal: 'checkout-web' },
    customer: {
      name: 'Maria Souza',
      document: '52998224725',
      email: 'maria.souza@exemplo.com',
    },
  }),
});
const cobranca = await res.json();

description is shown to the payer. metadata comes back in the charge's webhooks. callbackUrl receives this charge's webhooks and requires the callback secret. All fields are in Create Pix charge.

Show the Pix to the customer

The response (201) carries the Pix copy-and-paste code in pix.qrCodeText. Show it to the customer and generate the QR code from it.

{
  "id": "hubp-20261005K7Q2M9XB4T127431",
  "status": "PENDING",
  "amount": 1500,
  "serviceFee": 105,
  "netAmount": 1395,
  "externalRef": "pedido-4821",
  "pix": {
    "qrCodeText": "00020126580014br.gov.bcb.pix0136b3c7e9a2-4f1d-4c8a-9e2b-7d5f6a8c1e03520400005303986540515.005802BR5912LOJA EXEMPLO6009SAO PAULO62070503***63041EC4"
  }
}

serviceFee is the fee, deducted from the amount: on a R$ 15.00 charge with a R$ 1.05 fee, R$ 13.95 comes in (netAmount).

Release the order on payment

When the customer pays, the PAYMENT_PAID webhook arrives, with your externalRef and the metadata from creation. Release the order at that point. If the charge expires without payment, PAYMENT_EXPIRED arrives.

To check at any time, call GET /transactions/payment/{paymentId}, with the id from the response or the paymentId from the webhook.

Charge status

StatusMeaning
PENDINGWaiting for payment.
PAIDPaid. The net amount is in the account.
REFUNDEDFully refunded.
EXPIREDExpired without payment. It does not go back to PENDING.

After payment, payer shows who actually paid, with the CPF masked or the CNPJ formatted, and pix.conciliationId carries the Pix end-to-end ID. customer is still the customer you provided.

Repeated request

You sendThe API responds
The same externalRef with the same data200 with the existing charge.
The same externalRef with some different data409 PAYMENT_EXTERNAL_REF_MISMATCH. The different fields come in details.fields.
The same externalRef while the first one is still being processed412 PAYMENT_CREATION_IN_FLIGHT. Repeat in a few seconds.

The comparison uses amount, method, description, metadata and the customer data. callbackUrl and ipAddress are left out. Do not put anything in metadata that changes on each attempt.

Lookups and receipts

Refund

POST /transactions/payment/{paymentId}/refund, scope REFUND. Send amount to return part of it; without amount, it returns everything that remains.

{ "amount": 1000 }
  • The refund fee is charged separately, on top of the amount returned.
  • The amount and the fee leave the available balance at the time of the request and come back if the refund fails.
  • One refund at a time per charge. Partial refunds can be repeated up to the full amount.
  • With a MED dispute open on the charge, the refund is refused (REFUND_INFRACTION_OPEN).
  • The result arrives through the REFUND_COMPLETED or REFUND_FAILED webhooks.
  • The route does not accept Idempotency-Key. On a 502, the refund may have gone out: get the charge before requesting it again.

Limits

  • The amount must be between the account's minimum and maximum and greater than the fee. See yours in limits.
  • Up to 60 charges per minute per credential and 120 per account. Above that, the API responds 429 with Retry-After.
  • Refunds count toward the same limit as withdrawals: 5 per minute per credential and 10 per account.

Each route's rejections, with the code, are in Create Pix charge and Refund charge.

On this page