# Pagar Pix copia e cola (/docs/conta-digital/qr-payments)

<QuickLinks>
  <QuickLink href="/docs/conta-digital/endpoints/pix/post_pix_qr_payment" title="Pagar Pix copia e cola" method="POST" path="/transactions/pix/qr-payments" />

  <QuickLink href="/docs/conta-digital/endpoints/pix/post_pix_decode" title="Ler Pix copia e cola" method="POST" path="/transactions/pix/decode" />

  <QuickLink href="/docs/conta-digital/endpoints/pix/post_pix_destination" title="Consultar destinatário" method="POST" path="/transactions/pix/destination" />

  <QuickLink href="/docs/conta-digital/withdrawals" title="Saques Pix" />
</QuickLinks>

Pagar um Pix copia e cola funciona como um [saque](/docs/conta-digital/withdrawals): 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.

<Mermaid
  chart="`
flowchart LR
  A[&#x22;Lê o Pix copia e cola (opcional)&#x22;] --> B[&#x22;Paga o Pix copia e cola&#x22;]
  B --> C[&#x22;Valor e tarifa saem do saldo&#x22;]
  C --> D[&#x22;Webhook WITHDRAW_COMPLETED&#x22;]
  C -.->|&#x22;falhou&#x22;| E[&#x22;Webhook WITHDRAW_FAILED&#x22;]

  click A &#x22;/docs/conta-digital/endpoints/pix/post_pix_decode&#x22; &#x22;Ler Pix copia e cola&#x22;
  click B &#x22;/docs/conta-digital/endpoints/pix/post_pix_qr_payment&#x22; &#x22;Pagar Pix copia e cola&#x22;
  click D &#x22;/docs/conta-digital/webhooks&#x22; &#x22;Webhooks&#x22;

  style B fill:#f59e0b,stroke:#d97706,color:#ffffff
  style D fill:#14ce71,stroke:#0eb464,color:#ffffff
  style E fill:#ef4444,stroke:#dc2626,color:#ffffff
`"
/>

<Steps>
  <Step>
    ### Ler o Pix copia e cola [#ler-o-pix-copia-e-cola]

    Opcional. [`POST /transactions/pix/decode`](/docs/conta-digital/endpoints/pix/post_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.

    <Tabs items="['curl', 'Node.js']">
      <Tab value="curl">
        ```bash
        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" }'
        ```
      </Tab>

      <Tab value="Node.js">
        ```ts
        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();
        ```
      </Tab>
    </Tabs>

    ```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](/docs/conta-digital/recipient). No código dinâmico, `pixKey` vem `null` e só `url` é preenchida; o titular e o valor saem da [consulta de destinatário](/docs/conta-digital/recipient).
  </Step>

  <Step>
    ### Pagar o Pix copia e cola [#pagar-o-pix-copia-e-cola]

    [`POST /transactions/pix/qr-payments`](/docs/conta-digital/endpoints/pix/post_pix_qr_payment), 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.

    <Tabs items="['curl', 'Node.js']">
      <Tab value="curl">
        ```bash
        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"
          }'
        ```
      </Tab>

      <Tab value="Node.js">
        ```ts
        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();
        ```
      </Tab>
    </Tabs>

    `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](/docs/conta-digital/webhooks#callbackurl-da-operação). Todos os campos estão em [Pagar Pix copia e cola](/docs/conta-digital/endpoints/pix/post_pix_qr_payment).
  </Step>

  <Step>
    ### Guardar o pagamento [#guardar-o-pagamento]

    A resposta (`201`) tem o formato do [saque](/docs/conta-digital/withdrawals#status-do-saque). Guarde o `id`.

    ```json
    {
      "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.
  </Step>

  <Step>
    ### Confirmar a entrega [#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}`](/docs/conta-digital/endpoints/withdrawals/get_withdraw).
  </Step>
</Steps>

## Valor [#valor]

| O código   | `amount` enviado | Resultado                                                                 |
| ---------- | ---------------- | ------------------------------------------------------------------------- |
| Fixa valor | Nenhum           | Paga o valor do código.                                                   |
| Fixa valor | O mesmo          | Paga.                                                                     |
| Fixa valor | Diferente        | `422` `QR_AMOUNT_MISMATCH`, com `details.expected` e `details.requested`. |
| Não fixa   | Um valor         | Paga o valor enviado.                                                     |
| Não fixa   | Nenhum           | `422` `QR_AMOUNT_REQUIRED`.                                               |

## Código dinâmico [#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](/docs/conta-digital/recipient): `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 [#pedido-repetido]

A `Idempotency-Key` segue as regras do [saque](/docs/conta-digital/withdrawals#pedido-repetido), 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`](/docs/conta-digital/endpoints/withdrawals/get_withdraws) antes de pagar de novo.

## Tarifa e limites [#tarifa-e-limites]

* A tarifa é a de pagamento de Pix copia e cola, `externalPayment` nos [limites](/docs/conta-digital/statement#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](/docs/conta-digital/endpoints/pix/post_pix_qr_payment).