PayZuDocs

Pagar Pix copia e cola

Pague um Pix copia e cola, estático ou dinâmico, com o saldo da conta.

Pagar um Pix copia e cola funciona como um saque: mesma resposta, mesmo acompanhamento e os mesmos limites, com tarifa própria. O destino vem do código, e o valor também, quando o código fixa um.

Ler o Pix copia e cola

Opcional. POST /transactions/pix/decode, escopo PIX_DICT_READ, lê o código sem pagar e sem consultar o banco: não conta no limite de consultas e não diz quem é o titular.

curl -X POST https://api.hub.payzu.com.br/api/v1/transactions/pix/decode \
  -H "Authorization: Bearer $PAYZU_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "brCode": "00020126400014br.gov.bcb.pix0118fulano@exemplo.com520400005303986540525.005802BR5913FULANO DE TAL6009SAO PAULO62140510PEDIDO482163048572" }'
const res = await fetch('https://api.hub.payzu.com.br/api/v1/transactions/pix/decode', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.PAYZU_TOKEN}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    brCode: '00020126400014br.gov.bcb.pix0118fulano@exemplo.com520400005303986540525.005802BR5913FULANO DE TAL6009SAO PAULO62140510PEDIDO482163048572',
  }),
});
const codigo = await res.json();
{
  "pixKey": "fulano@exemplo.com",
  "url": null,
  "amount": 2500,
  "merchantName": "FULANO DE TAL",
  "merchantCity": "SAO PAULO",
  "txid": "PEDIDO4821",
  "isDynamic": false,
  "isAmountFixed": true
}

isAmountFixed diz se o código já traz o valor. merchantName e merchantCity são o que quem gerou o código escreveu, sem verificação; para saber o titular, use Consultar destinatário. No código dinâmico, pixKey vem null e só url é preenchida; o titular e o valor saem da consulta de destinatário.

Pagar o Pix copia e cola

POST /transactions/pix/qr-payments, escopo WITHDRAW. Mande o código completo em brCode, como foi lido: a chave decodificada pelo seu sistema não é aceita no lugar dele. Mande amount, em centavos, só quando o código não fixa valor.

Gere uma Idempotency-Key para cada pagamento e, se repetir a chamada, mande a mesma.

IDEMPOTENCY_KEY=$(uuidgen)

curl -X POST https://api.hub.payzu.com.br/api/v1/transactions/pix/qr-payments \
  -H "Authorization: Bearer $PAYZU_TOKEN" \
  -H "Idempotency-Key: $IDEMPOTENCY_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "brCode": "00020126400014br.gov.bcb.pix0118fulano@exemplo.com520400005303986540525.005802BR5913FULANO DE TAL6009SAO PAULO62140510PEDIDO482163048572",
    "comment": "Pedido 4821"
  }'
import crypto from 'node:crypto';

const idempotencyKey = crypto.randomUUID();

const res = await fetch('https://api.hub.payzu.com.br/api/v1/transactions/pix/qr-payments', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.PAYZU_TOKEN}`,
    'Idempotency-Key': idempotencyKey,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    brCode: '00020126400014br.gov.bcb.pix0118fulano@exemplo.com520400005303986540525.005802BR5913FULANO DE TAL6009SAO PAULO62140510PEDIDO482163048572',
    comment: 'Pedido 4821',
  }),
});
const pagamento = await res.json();

comment vai ao destinatário; sem ele, vai o nome do destinatário que está no código. callbackUrl recebe os webhooks deste pagamento e exige o segredo de callback. Todos os campos estão em Pagar Pix copia e cola.

Guardar o pagamento

A resposta (201) tem o formato do saque. Guarde o id.

{
  "id": "hubp-20261005H2P6XC8VNM127431",
  "status": "APPROVED",
  "amount": 2500,
  "serviceFee": 100,
  "totalDebited": 2600,
  "pixKey": "f***@exemplo.com",
  "comment": "Pedido 4821",
  "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
}

pixKey vem mascarada. APPROVED é pagamento a caminho, não dinheiro entregue.

Confirmar a entrega

O pagamento está entregue quando chega o webhook WITHDRAW_COMPLETED, com status: "CONFIRMED" e operation: "EXTERNAL_PAYMENT". Se falhar, chega WITHDRAW_FAILED, e o valor e a tarifa voltam ao saldo.

A consulta é a do saque: GET /transactions/withdraw/{withdrawId}.

Valor

O códigoamount enviadoResultado
Fixa valorNenhumPaga o valor do código.
Fixa valorO mesmoPaga.
Fixa valorDiferente422 QR_AMOUNT_MISMATCH, com details.expected e details.requested.
Não fixaUm valorPaga o valor enviado.
Não fixaNenhum422 QR_AMOUNT_REQUIRED.

Código dinâmico

O código dinâmico traz só um link, que a PayZu resolve no banco antes de pagar; nada sai do saldo antes disso. O corpo e a resposta são os mesmos.

  • Se a resolução falha, a recusa usa os códigos da consulta de destinatário: 404 PIX_DEST_PIX_KEY, 503 PIX_DEST_UNAVAILABLE ou PIX_DEST_THROTTLED, 502 PIX_DEST_NOT_AUTHORIZED_AT_PROVIDER.
  • Se o valor impresso no código difere do valor que o banco devolve para ele, o pagamento é recusado com 422 QR_AMOUNT_DISAGREES.

Pedido repetido

A Idempotency-Key segue as regras do saque, e a comparação também considera o código pago. No código dinâmico, o código é resolvido antes de conferir a repetição, então repetir pode trazer as recusas da resolução em vez do pagamento original.

Num 502, o pagamento pode ter saído. Repita com a mesma Idempotency-Key ou procure o pagamento em GET /transactions/withdraw antes de pagar de novo.

Tarifa e limites

  • A tarifa é a de pagamento de Pix copia e cola, externalPayment nos limites.
  • O mínimo e o máximo são os do saque. O teto diário e o limite de requisições também, somados com ele.
  • Código já pago ou vencido é recusado pelo banco.
  • Código corrompido (QR_CRC), fora do formato (QR_MALFORMED) ou que não é de Pix (QR_NOT_PIX) é recusado com 400, na leitura e no pagamento.

As recusas, com o code, estão em Pagar Pix copia e cola.

Nesta página