# Cobranças Pix (/docs/conta-digital/charges)

<QuickLinks>
  <QuickLink href="/docs/conta-digital/endpoints/charges/post_payment" title="Criar cobrança Pix" method="POST" path="/transactions/payment" />

  <QuickLink href="/docs/conta-digital/endpoints/charges/get_payment" title="Consultar cobrança" method="GET" path="/transactions/payment/{paymentId}" />

  <QuickLink href="/docs/conta-digital/endpoints/charges/post_payment_refund" title="Estornar cobrança" method="POST" path="/transactions/payment/{paymentId}/refund" />
</QuickLinks>

<Mermaid
  chart="`
flowchart LR
  A[&#x22;Cria a cobrança&#x22;] --> B[&#x22;Mostra o Pix copia e cola&#x22;]
  B --> C[&#x22;Cliente paga&#x22;]
  C --> D[&#x22;Webhook PAYMENT_PAID&#x22;]
  D --> E[&#x22;Libera o pedido&#x22;]

  click A &#x22;/docs/conta-digital/endpoints/charges/post_payment&#x22; &#x22;Criar cobrança&#x22;
  click D &#x22;/docs/conta-digital/webhooks&#x22; &#x22;Webhooks&#x22;

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

<Steps>
  <Step>
    ### Criar a cobrança [#criar-a-cobrança]

    [`POST /transactions/payment`](/docs/conta-digital/endpoints/charges/post_payment), escopo `PAYMENT_WRITE`. Obrigatórios: `amount` em centavos, `method: "PIX"` e o cliente, com `customer.name` e `customer.document` (CPF ou CNPJ).

    Mande o número do seu pedido em `externalRef`: repetir a chamada com o mesmo `externalRef` devolve a mesma cobrança em vez de criar outra.

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

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

    `description` aparece para quem paga. `metadata` volta nos webhooks da cobrança. `callbackUrl` recebe os webhooks desta cobrança e exige o [segredo de callback](/docs/conta-digital/webhooks#callbackurl-da-operação). Todos os campos estão em [Criar cobrança Pix](/docs/conta-digital/endpoints/charges/post_payment).
  </Step>

  <Step>
    ### Mostrar o Pix ao cliente [#mostrar-o-pix-ao-cliente]

    A resposta (`201`) traz o Pix copia e cola em `pix.qrCodeText`. Mostre-o ao cliente e gere o QR Code a partir dele.

    ```json
    {
      "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` é a tarifa, descontada do valor: numa cobrança de R$ 15,00 com tarifa de R$ 1,05, entram R$ 13,95 (`netAmount`).
  </Step>

  <Step>
    ### Liberar o pedido no pagamento [#liberar-o-pedido-no-pagamento]

    Quando o cliente paga, chega o webhook `PAYMENT_PAID`, com o seu `externalRef` e o `metadata` da criação. Libere o pedido aí. Se a cobrança vencer sem pagamento, chega `PAYMENT_EXPIRED`.

    Para conferir a qualquer momento, consulte [`GET /transactions/payment/{paymentId}`](/docs/conta-digital/endpoints/charges/get_payment), com o `id` da resposta ou o `paymentId` do webhook.
  </Step>
</Steps>

## Status da cobrança [#status-da-cobrança]

<Mermaid
  chart="`
stateDiagram-v2
  [*] --> PENDING
  PENDING --> PAID: paga
  PENDING --> EXPIRED: vencida
  PAID --> REFUNDED: estornada por inteiro
  REFUNDED --> [*]
  EXPIRED --> [*]
`"
/>

| Status     | Significado                                  |
| ---------- | -------------------------------------------- |
| `PENDING`  | Aguardando pagamento.                        |
| `PAID`     | Paga. O valor líquido está na conta.         |
| `REFUNDED` | Estornada por inteiro.                       |
| `EXPIRED`  | Venceu sem pagamento. Não volta a `PENDING`. |

Depois do pagamento, `payer` mostra quem de fato pagou, com o CPF mascarado ou o CNPJ formatado, e `pix.conciliationId` traz o end-to-end do Pix. `customer` continua sendo o cliente que você informou.

## Pedido repetido [#pedido-repetido]

| Você manda                                                   | A API responde                                                                       |
| ------------------------------------------------------------ | ------------------------------------------------------------------------------------ |
| O mesmo `externalRef` com os mesmos dados                    | `200` com a cobrança que já existe.                                                  |
| O mesmo `externalRef` com algum dado diferente               | `409` `PAYMENT_EXTERNAL_REF_MISMATCH`. Os campos diferentes vêm em `details.fields`. |
| O mesmo `externalRef` enquanto a primeira ainda é processada | `412` `PAYMENT_CREATION_IN_FLIGHT`. Repita em alguns segundos.                       |

A comparação usa valor, método, descrição, `metadata` e os dados do cliente. `callbackUrl` e `ipAddress` ficam de fora. Não ponha em `metadata` nada que mude a cada tentativa.

## Consultar e comprovar [#consultar-e-comprovar]

* **Listar:** [`GET /transactions/payment`](/docs/conta-digital/endpoints/charges/get_payments), com filtros de status, período, `externalRef` e cliente.
* **Comprovante:** [`GET /transactions/payment/{paymentId}/receipt`](/docs/conta-digital/endpoints/charges/get_payment_receipt) devolve o PDF em base64, para cobrança paga ou estornada.

## Estornar [#estornar]

[`POST /transactions/payment/{paymentId}/refund`](/docs/conta-digital/endpoints/charges/post_payment_refund), escopo `REFUND`. Mande `amount` para devolver parte; sem `amount`, devolve tudo o que resta.

```json
{ "amount": 1000 }
```

* A tarifa de estorno é cobrada à parte, além do valor devolvido.
* O valor e a tarifa saem do saldo disponível na hora do pedido e voltam se o estorno falhar.
* Um estorno por vez em cada cobrança. Estornos parciais podem se repetir até o valor total.
* Com contestação MED aberta na cobrança, o estorno é recusado (`REFUND_INFRACTION_OPEN`).
* O resultado chega pelos webhooks `REFUND_COMPLETED` ou `REFUND_FAILED`.
* A rota não aceita `Idempotency-Key`. Num `502`, o estorno pode ter saído: consulte a cobrança antes de pedir de novo.

## Limites [#limites]

* O valor fica entre o mínimo e o máximo da conta e precisa ser maior que a tarifa. Veja os seus em [limites](/docs/conta-digital/statement#limites).
* Até 60 cobranças por minuto por credencial e 120 por conta. Acima disso, a API responde `429` com `Retry-After`.
* Estornos contam no mesmo limite de saques: 5 por minuto por credencial e 10 por conta.

As recusas de cada rota, com o `code`, estão em [Criar cobrança Pix](/docs/conta-digital/endpoints/charges/post_payment) e [Estornar cobrança](/docs/conta-digital/endpoints/charges/post_payment_refund).