> ## Documentation Index
> Fetch the complete documentation index at: https://docs.rampapay.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Payment flow

> Three calls from scan to paid: read the QR, get a firm quote for it, then pay.

The payment is made at once, and the answer says how it ended.

**1. Read — POST /payouts/qr/resolve**

The scanned QR's `content`. You get the merchant, the amount (`target.amount`, or `null` for an open-amount QR) and an `id`. [Reference](/api-reference/payouts/resolve-qr)

**2. Quote — POST /fx/quotes**

USDT → BOB, `target_amount` the QR's amount, `resolution_id` the read's `id`. Show `source.amount` with a countdown to `expires_at`; the end user accepts, or you drop it. [Reference](/api-reference/payouts/create-fx-quote)

**3. Pay — POST /payouts**

`type` `qr` with the QR, your `transaction_id` and the `quote_id`. Answers `completed`, or why not. [Reference](/api-reference/payouts/create-payout)

**4. Rarely — payout.completed**

If it answered `processing`: the result arrives by [webhook](/webhooks), or poll [`GET /payouts/{id}`](/api-reference/payouts/get-payout).

> [!NOTE]
>
> **Open-amount QRs.** Some QRs carry no amount. Ask the end user for it first, quote that amount, and send the QR with the quote: it is paid the quote's `target.amount`.

> [!WARNING]
>
> **Quotes expire.** A quote is valid for 3 minutes at most (`expires_at`) and pays one payment. Paying after that answers `409 QUOTE_EXPIRED` and nothing is attempted — get a new quote and show it. A QR for another amount than the quote ends `cancelled` with `QUOTE_AMOUNT_MISMATCH`, and the quote can still be used.

## Worked example

A Bs 1,000.00 QR at Bs 10.00 per USDT (an example price) is 100 USDT; with our 50 bps markup the rate is 9.9500 — 100.50 USDT — plus a 100 bps fee of 1.00 USDT: **101.50 USDT**. Paying debits exactly 101.50 USDT.

## Statuses

| Status | Who acts | Meaning |
| - | - | - |
| `processing` | Wait | Sent to the network; its answer is late. Your USDT is held. Poll, or wait for the webhook. |
| `completed` | Final | The merchant was paid. Your USDT was debited: exactly the quote's `source.amount`. |
| `failed` | Final | The network refused the payment. The held USDT is released. See `error`. |
| `rejected` | Final | The network refused the QR (unreadable, or not payable). Nothing was debited; the quote can still be used. See `error`. |
| `cancelled` | Final | Ended before paying: the QR did not match the quote, a balance fell short, or the quote expired. Nothing was debited. See `error`. |

The `error.code` values are in [Failure codes](/webhooks#failure-codes).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.