> For the complete documentation index, see [llms.txt](https://plexo.gitbook.io/rest-api/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://plexo.gitbook.io/rest-api/pos-payments/pix-qr-pos.md).

# PIX QR Payments for POS

Use this guide when you want to create a PIX payment through the public Payments API, show a QR code at the point of sale, and confirm the result from your backend.

In this guide you will:

* create a PIX POS payment with `POST /v1/payments`
* display the QR code returned in the payment response
* confirm the final result through `callbackUrl` or by polling the payment

**Time to complete:** 15 minutes

## Before you start

Make sure you have:

* HTTP Basic API credentials
* a merchant ID with PIX enabled in **PayFac** mode
* the PIX payment method identifier configured for that merchant, commonly `pix`
* a backend endpoint that can receive payment callbacks, or a process that can poll payment status

{% hint style="warning" %}
The current PIX POS provider flow expects `amount.currency = "USD"`. If you send another currency, the payment request can fail with a currency-not-supported error.
{% endhint %}

{% hint style="info" %}
PIX is available in the merchant setup guide only for PayFac mode. If PIX is not configured for your merchant, the payment creation request can fail with a payment method or merchant payment method error.
{% endhint %}

## Flow overview

```
Create PIX POS payment
    ↓
Receive pending payment with QR payload in payment.code
    ↓
Show QR to the payer
    ↓
Wait for callback or poll GET /v1/payments/{paymentId}
    ↓
Handle approved, denied, expired, cancelled, or failed result
```

## Step 1: Create the PIX POS payment

Use the standard payment creation route:

```
POST /v1/payments
```

For the POS flow, set `flow` to `pos` and pass the merchant's PIX payment method identifier in `paymentMethod.id`.

Example request body:

```json
{
  "merchantId": 12345,
  "flow": "pos",
  "referenceId": "pix-pos-1001",
  "invoiceNumber": "POS-1001",
  "amount": {
    "total": 20.00,
    "currency": "USD",
    "details": {
      "tax": {
        "type": "17934",
        "amount": 2.20,
        "rate": 0.22
      },
      "taxedAmount": 10.00
    }
  },
  "paymentMethod": {
    "id": "pix",
    "source": "bank-transfer"
  },
  "callbackUrl": "https://merchant.example.com/callbacks/payments",
  "metadata": {
    "terminalId": "store-01-pos-03",
    "cashierId": "cashier-17"
  }
}
```

Request notes:

* `invoiceNumber` should be treated as required for this flow
* `paymentMethod.id` must match the PIX method configured for your merchant
* `paymentMethod.source = "bank-transfer"` makes the alternative-payment intent explicit in the current API shape
* `amount.details` groups optional amount-breakdown data such as taxes, tips, discounts, and shipping
* `amount.details.tax.type` identifies the tax regime and is limited to `17934`, `19210`, or `none`
* `amount.details.tax.amount` is the tax amount included in the payment breakdown
* `amount.details.tax.rate` is an optional decimal tax rate, for example `0.22` for 22%
* `amount.details.taxedAmount` is the taxable portion of the payment amount and must not be greater than `amount.total`
* `callbackUrl` is optional but recommended for faster status updates
* `referenceId` must stay unique per payment attempt

Example cURL request:

```bash
AUTH=$(printf '%s:%s' "$CLIENT_ID" "$API_KEY" | base64)

curl --request POST \
  --url https://api.testing.plexo.com.uy/v1/payments \
  --header "Authorization: Basic $AUTH" \
  --header "Content-Type: application/json" \
  --data '{
    "merchantId": 12345,
    "flow": "pos",
    "referenceId": "pix-pos-1001",
    "invoiceNumber": "POS-1001",
    "amount": {
      "total": 20.00,
      "currency": "USD",
      "details": {
        "tax": {
          "type": "17934",
          "amount": 2.20,
          "rate": 0.22
        },
        "taxedAmount": 10.00
      }
    },
    "paymentMethod": {
      "id": "pix",
      "source": "bank-transfer"
    },
    "callbackUrl": "https://merchant.example.com/callbacks/payments",
    "metadata": {
      "terminalId": "store-01-pos-03"
    }
  }'
```

## Step 2: Read the pending payment response

On success, Plexo returns `200 OK` with a `PaymentDto`. For PIX POS, the initial response is typically `pending` and includes the QR payload in `payment.code`.

Example response:

```json
{
  "id": "550e8400e29b41d4a716446655440000",
  "referenceId": "pix-pos-1001",
  "invoiceNumber": "POS-1001",
  "status": "pending",
  "flow": "pos",
  "processingMethod": "api",
  "createdAt": "2026-03-27T12:00:00Z",
  "processedAt": "2026-03-27T12:00:01Z",
  "expiresAt": "2026-03-27T12:30:00Z",
  "amount": {
    "total": 20.00,
    "currency": "USD"
  },
  "paymentMethod": {
    "id": "pix",
    "name": "PIX",
    "type": "bank-transfer"
  },
  "code": {
    "type": "qrcode",
    "url": "https://payment.example.com/qr/abc123",
    "value": "00020101021226580014BR.GOV.BCB.PIX...",
    "base64Image": "iVBORw0KGgoAAAANSUhEUgAA..."
  },
  "transactions": [
    {
      "referenceId": "pix-pos-1001",
      "type": "purchase",
      "status": "pending",
      "resultCode": "1",
      "resultMessage": "Pendiente",
      "ticket": "TICKET123"
    }
  ]
}
```

Focus on these fields:

* `id`: Plexo payment identifier you use for later lookups or cancellations
* `status`: current payment state
* `expiresAt`: when the QR should no longer be presented
* `code.value`: raw PIX payload string
* `code.base64Image`: ready-to-render QR image
* `transactions`: processor-side attempt and ticket details

## Step 3: Show the QR code at the POS

You can present the PIX QR in either of these ways:

* Render `payment.code.base64Image` directly in your POS UI
* Persist `payment.code.value` and regenerate the QR later with `GET /v1/codes?paymentMethod=pix&value=...`

Example HTML image source:

```html
<img src="data:image/png;base64,{{payment.code.base64Image}}" alt="PIX QR code" />
```

If your POS app is not browser-based, use `code.value` or `code.base64Image` in the native UI that displays the payment QR to the payer.

## Step 4: Confirm the final payment result

There are two supported confirmation patterns.

### Option A: Receive asynchronous updates

Provide `callbackUrl` in the original request. Plexo sends payment updates to that URL as the PIX payment changes state.

### Option B: Poll the payment

Retrieve the payment by ID until `status` is no longer `pending`.

```bash
curl --request GET \
  --url https://api.testing.plexo.com.uy/v1/payments/550e8400-e29b-41d4-a716-446655440000 \
  --header "Authorization: Basic $AUTH"
```

Recommended handling:

* treat `approved` as a successful paid PIX transaction
* keep the QR visible while the payment remains `pending`
* stop accepting the QR when the payment becomes `expired`, `cancelled`, `denied`, or `failed`

## Step 5: Handle abandoned or expired QR payments

If the payer does not complete the PIX payment before expiration:

* stop showing the old QR
* create a new payment with a new `referenceId`

If you need to stop a still-pending PIX payment before it expires, use:

```
POST /v1/payments/{paymentId}/cancellations
```

The current backend cancellation rules allow cancellation for non-card payments, including PIX, while the payment is `pending` or `approved`.

## Common errors

| Status | What it usually means                                                                                   |
| ------ | ------------------------------------------------------------------------------------------------------- |
| `400`  | Invalid merchant, missing `invoiceNumber`, unsupported currency, or PIX not configured for the merchant |
| `401`  | Invalid API credentials                                                                                 |
| `403`  | The authenticated client cannot use the merchant                                                        |
| `409`  | Duplicate `referenceId`                                                                                 |
| `422`  | Processor-side rejection or business-rule failure                                                       |

## Related guides

* [Payment Processing](/rest-api/payments/payment-processing.md)
* [Payment Methods Setup Guide](/rest-api/merchant-configuration/payment-methods-setup.md)
* [Testing](/rest-api/operations/testing.md)
