# Receive Pix payment (/en/docs/pix-processamento/tutoriais/receive-pix)

<QuickLinks>
  <QuickLink href="/docs/pix-processamento/endpoints/pix-operations/post_pix" title="POST /pix" />

  <QuickLink href="/docs/pix-processamento/endpoints/pix-operations/get_pix" title="GET /pix" />

  <QuickLink href="/docs/pix-processamento/webhooks" title="Webhooks" />

  <QuickLink href="/docs/pix-processamento/glossary" title="Glossary" />
</QuickLinks>

<Mermaid
  chart="`
flowchart LR
  A[&#x22;Create charge&#x22;] --> B[&#x22;Display QR to customer&#x22;]
  B --> C[&#x22;Customer pays at their bank&#x22;]
  C --> D[&#x22;COMPLETED callback&#x22;]
  D --> E[&#x22;Mark order as paid&#x22;]

  click A &#x22;/en/docs/pix-processamento/endpoints/pix-operations/post_pix&#x22; &#x22;POST /pix&#x22;
  click B &#x22;/en/docs/pix-processamento/endpoints/pix-operations/get_pix_qrcode&#x22; &#x22;GET /pix/qr-code&#x22;
  click D &#x22;/en/docs/pix-processamento/webhooks&#x22; &#x22;Webhooks&#x22;
  click E &#x22;/en/docs/pix-processamento/best-practices/idempotency&#x22; &#x22;Idempotency&#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>
    ### Generate charge [#generate-charge]

    Endpoint: [`POST /pix`](/docs/pix-processamento/endpoints/pix-operations/post_pix). Only `amount` is required, [in reais](/docs/pix-processamento/best-practices/money) and never in cents; the other fields enrich the QR and reconciliation.

    <Tabs items="['curl', 'Node.js']">
      <Tab value="curl">
        ```bash
        curl -X POST https://api.payzu.processamento.com/v1/pix \
          -H "Authorization: Bearer $TOKEN" \
          -H "Content-Type: application/json" \
          -d '{
            "amount": 99.90,
            "generatedName": "João da Silva",
            "generatedDocument": "12345678909",
            "callbackUrl": "https://seusite.com.br/webhooks/payzu",
            "clientReference": "pedido-2025-001",
            "virtualAccount": "loja-rj-01",
            "expiresIn": 600
          }'
        ```
      </Tab>

      <Tab value="Node.js">
        ```ts
        const res = await fetch('https://api.payzu.processamento.com/v1/pix', {
          method: 'POST',
          headers: {
            Authorization: `Bearer ${process.env.PAYZU_TOKEN}`,
            'Content-Type': 'application/json',
          },
          body: JSON.stringify({
            amount: 99.90,
            generatedName: 'João da Silva',
            generatedDocument: '12345678909',
            callbackUrl: 'https://seusite.com.br/webhooks/payzu',
            clientReference: 'pedido-2025-001',
            virtualAccount: 'loja-rj-01',
            expiresIn: 600,
          }),
        });
        const charge = await res.json();
        ```
      </Tab>
    </Tabs>

    Response:

    ```json
    {
      "id": "PAYZU20260811R4TZ8WD1NC000000",
      "status": "PENDING",
      "amount": 99.90,
      "qrCodeText": "00020126870014br.gov.bcb.pix...",
      "qrCodeUrl": "https://api.payzu.processamento.com/v1/pix/qr-code/PAYZU20260811R4TZ8WD1NC000000",
      "clientReference": "pedido-2025-001",
      "virtualAccount": "loja-rj-01",
      "expiresAt": "2025-08-17T22:00:00.000Z"
    }
    ```
  </Step>

  <Step>
    ### Display QR Code to customer [#display-qr-code-to-customer]

    Two ways:

    **Direct image**, use `qrCodeUrl` in `<img>`:

    ```html
    <img src="https://api.payzu.processamento.com/v1/pix/qr-code/PAYZU2025..." />
    ```

    **Copy-and-paste**, display `qrCodeText` in an input with a button:

    ```html
    <input value="00020126870014br.gov.bcb.pix2565..." readonly />
    <button onclick="navigator.clipboard.writeText(qrCodeText)">Copy</button>
    ```

    <Callout type="info">
      PayZu generates a **dynamic** QR per charge.
    </Callout>
  </Step>

  <Step>
    ### Receive callback when paid [#receive-callback-when-paid]

    When the customer completes the Pix, PayZu sends a `POST` to your `callbackUrl`:

    ```json
    {
      "id": "PAYZU20260811R4TZ8WD1NC000000",
      "type": "DEPOSIT",
      "status": "COMPLETED",
      "amount": 99.90,
      "clientReference": "pedido-2025-001",
      "virtualAccount": "loja-rj-01",
      "endToEndId": "E60746948202508172200X7H4K2P9M5Q",
      "paidAt": "2025-08-17T22:00:12.000Z"
    }
    ```

    Sample handler:

    <Tabs items="['Node.js (Express)', 'Python (Flask)']">
      <Tab value="Node.js (Express)">
        ```ts
        import express from 'express';
        const app = express();

        app.post('/webhooks/payzu', express.json(), async (req, res) => {
          const tx = req.body;

          if (await isProcessed(tx.id, tx.status)) return res.status(200).end();

          if (tx.type === 'DEPOSIT' && tx.status === 'COMPLETED') {
            await markOrderPaid(tx.clientReference, tx);
          }

          res.status(204).end();
        });
        ```
      </Tab>

      <Tab value="Python (Flask)">
        ```python
        from flask import Flask, request
        app = Flask(__name__)

        @app.post('/webhooks/payzu')
        def payzu_webhook():
            tx = request.get_json()
            if is_processed(tx['id'], tx['status']):
                return '', 200
            if tx['type'] == 'DEPOSIT' and tx['status'] == 'COMPLETED':
                mark_order_paid(tx['clientReference'], tx)
            return '', 204
        ```
      </Tab>
    </Tabs>

    <Callout type="warn">
      Respond within **5 seconds** with `2xx`; the full retry policy is in [Webhooks](/docs/pix-processamento/webhooks#retry-system).
    </Callout>
  </Step>

  <Step>
    ### Polling fallback [#polling-fallback]

    If the callback does not arrive, query directly via [`GET /pix`](/docs/pix-processamento/endpoints/pix-operations/get_pix). It accepts `id`, `clientReference`, `endToEndId` or `virtualAccount`, **use only one**.

    <Tabs items="['curl', 'Node.js']">
      <Tab value="curl">
        ```bash
        curl "https://api.payzu.processamento.com/v1/pix?clientReference=pedido-2025-001" \
          -H "Authorization: Bearer $TOKEN" \
          -H "Content-Type: application/json"
        ```
      </Tab>

      <Tab value="Node.js">
        ```ts
        const res = await fetch(
          `https://api.payzu.processamento.com/v1/pix?clientReference=pedido-2025-001`,
          {
            headers: {
              Authorization: `Bearer ${process.env.PAYZU_TOKEN}`,
              'Content-Type': 'application/json',
            },
          },
        );
        const charge = await res.json();
        ```
      </Tab>
    </Tabs>

    <Callout type="info">
      Polling should be a fallback. Configure the callback as the primary source.
    </Callout>
  </Step>

  <Step>
    ### Receipt [#receipt]

    After payment, download the official receipt via [`GET /proof/{id}`](/docs/pix-processamento/endpoints/pix-operations/get_proof):

    ```bash
    curl "https://api.payzu.processamento.com/v1/proof/PAYZU20260811R4TZ8WD1NC000000" \
      -H "Authorization: Bearer $TOKEN" \
      -H "Content-Type: application/json"
    ```
  </Step>
</Steps>

## Next steps [#next-steps]

<QuickLinks>
  <QuickLink href="/docs/pix-processamento/webhooks" title="Webhooks" />

  <QuickLink href="/docs/pix-processamento/error-codes" title="Error codes" />
</QuickLinks>