# Fetch a quote collection (v3)

Before you can create a payment, you request a **quote collection**: a set of priced quotes for a proposed transfer. With `/v3/quotes`, the collection contains one quote for each payment rail available for the corridor. Each quote has its own exchange rate and fee breakdown, and all quotes in the collection have the same expiry time. Review the terms and choose a quote before you commit to a payment.

This guide uses `/v3/quotes`. To request quotes with `/v2/quotes`, see [Fetch a quote collection (v2)](/pt-br/products/payments-direct-2/api-docs/developer-guides/fetch-a-quote-collection). To decide which version to use, see [Choose a quote version](/pt-br/products/payments-direct-2/api-docs/developer-guides/choose-a-quote-version).

This guide covers:

1. Creating a quote collection, quoting by source or destination amount.
2. Reading the response and choosing a quote.
3. Handling quote expiry.
4. Requesting a quote for one payment rail.
5. Retrieving a quote collection or individual quote after creation.


For conceptual background, see [Quotes and exchange rates](/pt-br/products/payments-direct-2/introduction/concepts/quotes).

## Before you begin

To follow this guide, you need:

- Access to the Payments Direct API UAT environment.
- A valid OAuth2 **access token** with the `quote_collection:quote:create` scope to create quote collections, and the `quote_collection:quote:read` and `quote:quote:read` scopes to retrieve them. See [Request an access token](/pt-br/products/payments-direct-2/api-docs/developer-guides/request-an-access-token).
- The source and destination currencies and countries for the proposed payment.
- A `payinCategory` that matches your funding model (`PRE_FUNDING`, `CREDIT_FUNDING`, or `JIT_FUNDING`). See [Funding methods](/pt-br/products/payments-direct-2/introduction/concepts/funding-methods).
- Identities created with the v3 identity operations, which `/v3/quotes` requires. This version of the API documents only those operations, so you already meet this unless you integrated against an earlier version. See [Create and manage identities](/pt-br/products/payments-direct-2/api-docs/developer-guides/create-and-manage-identities).


## Step 1: Create a quote collection

`POST /v3/quotes/quote-collection`

A quote collection request specifies the corridor and amount you want to price. The response contains one quote for each payment rail available for that corridor, leaving out any that Ripple can't price. Not every payment rail for a corridor is available with `/v3/quotes`.

### Request parameters

| Parameter | Required | Description |
|  --- | --- | --- |
| `quoteAmount` | Yes | The amount to quote. |
| `quoteAmountType` | Yes | Whether `quoteAmount` is the send amount (`SOURCE_AMOUNT`) or the receive amount (`DESTINATION_AMOUNT`). |
| `sourceCurrency` | Yes | The currency you are sending (ISO 4217, 3–5 characters). |
| `destinationCurrency` | Yes | The currency the beneficiary receives (ISO 4217, 3–5 characters). For a stablecoin payout, the stablecoin. |
| `payinCategory` | Yes | Your funding model: `PRE_FUNDING`, `CREDIT_FUNDING`, or `JIT_FUNDING`. |
| `destinationCountry` | For a fiat payout | The beneficiary country (ISO 3166-1 alpha-2). Omitting it from a fiat payout request returns `USR_017`. Omit it for a stablecoin payout. |
| `sourceCountry` | No | The sender country (ISO 3166-1 alpha-2). |
| `paymentRail` | No | Requests a quote for this payment rail only. When omitted, the collection contains a quote for each payment rail available for the corridor. See [Payment rail reference](/pt-br/products/payments-direct-2/api-docs/integration-resources/payment-rail-reference). |


For a stablecoin payout, each quote's payment rail is a blockchain network, such as `ETHEREUM`, and quotes are returned only for the networks enabled for your account. Don't include `destinationCountry`: with it, no payment rail matches, and the request fails with `SYS_017`, or with `USR_024` if you also sent `paymentRail`. If you request a network that isn't enabled for your account, the request fails with `SYS_017`. A payment created from a stablecoin quote records the network in `destination.selectedPaymentRail` and has no `destination.destinationBlockchainNetwork` value.

Quote by source amount
Use `SOURCE_AMOUNT` when you control how much you want to send. The API calculates how much the beneficiary receives after applying the exchange rate and fees.

In this example, the sender wants to send **1,000 USD** to a beneficiary in Germany who receives EUR.

```bash
curl -i -X POST \
  https://api.test.ripple.com/v3/quotes/quote-collection \
  -H "Authorization: Bearer <YOUR_JWT_HERE>" \
  -H "Content-Type: application/json" \
  -d '{
    "quoteAmount": 1000.00,
    "quoteAmountType": "SOURCE_AMOUNT",
    "sourceCurrency": "USD",
    "destinationCurrency": "EUR",
    "sourceCountry": "US",
    "destinationCountry": "DE",
    "payinCategory": "PRE_FUNDING"
  }'
```

Quote by destination amount
Use `DESTINATION_AMOUNT` when the beneficiary must receive a precise amount, for example when paying a foreign-currency invoice. The API calculates the amount you send to cover the exchange and fees.

In this example, the beneficiary must receive exactly **20,000 MXN**.

```bash
curl -i -X POST \
  https://api.test.ripple.com/v3/quotes/quote-collection \
  -H "Authorization: Bearer <YOUR_JWT_HERE>" \
  -H "Content-Type: application/json" \
  -d '{
    "quoteAmount": 20000.00,
    "quoteAmountType": "DESTINATION_AMOUNT",
    "sourceCurrency": "USD",
    "destinationCurrency": "MXN",
    "sourceCountry": "US",
    "destinationCountry": "MX",
    "payinCategory": "PRE_FUNDING"
  }'
```

## Step 2: Review the response and choose a quote

A successful request returns HTTP `201` with a quote collection. The top-level `quoteCollectionId` identifies the collection, and the `quotes` array contains one quote for each payment rail Ripple priced. The example shows two payment rails with different fees, and so different destination amounts.

```json
{
  "quoteCollectionId": "11111111-aaaa-2222-bbbb-222222222222",
  "quotes": [
    {
      "quoteId": "7ea3399c-1234-5678-8d8f-d320ea406630",
      "quoteStatus": "ACTIVE",
      "quoteAmountType": "SOURCE_AMOUNT",
      "sourceAmount": 1000.00,
      "destinationAmount": 915.95,
      "sourceCurrency": "USD",
      "destinationCurrency": "EUR",
      "destinationCountry": "DE",
      "payinCategory": "PRE_FUNDING",
      "paymentRail": "SEPA_INSTANT",
      "adjustedExchangeRate": {
        "adjustedRate": 0.9238
      },
      "fees": [
        {
          "totalFee": 8.50,
          "feeCurrency": "USD",
          "feeBreakdown": [
            {
              "calculatedFee": 0.50,
              "feeName": "Fixed service fee",
              "feeDescription": "Fixed service fee for payment rail SEPA_INSTANT.",
              "paymentRail": "SEPA_INSTANT"
            },
            {
              "calculatedFee": 8.00,
              "feeName": "Variable service fee",
              "feeDescription": "Variable service fee for payment rail SEPA_INSTANT.",
              "paymentRail": "SEPA_INSTANT"
            }
          ]
        }
      ],
      "createdAt": "2025-11-02T18:26:00.000Z",
      "expiresAt": "2025-11-02T18:41:00.318Z"
    },
    {
      "quoteId": "9fb4500d-2345-6789-ae9f-e431fb517741",
      "quoteStatus": "ACTIVE",
      "quoteAmountType": "SOURCE_AMOUNT",
      "sourceAmount": 1000.00,
      "destinationAmount": 918.95,
      "sourceCurrency": "USD",
      "destinationCurrency": "EUR",
      "destinationCountry": "DE",
      "payinCategory": "PRE_FUNDING",
      "paymentRail": "SEPA_STANDARD",
      "adjustedExchangeRate": {
        "adjustedRate": 0.9238
      },
      "fees": [
        {
          "totalFee": 5.25,
          "feeCurrency": "USD",
          "feeBreakdown": [
            {
              "calculatedFee": 0.25,
              "feeName": "Fixed service fee",
              "feeDescription": "Fixed service fee for payment rail SEPA_STANDARD.",
              "paymentRail": "SEPA_STANDARD"
            },
            {
              "calculatedFee": 5.00,
              "feeName": "Variable service fee",
              "feeDescription": "Variable service fee for payment rail SEPA_STANDARD.",
              "paymentRail": "SEPA_STANDARD"
            }
          ]
        }
      ],
      "createdAt": "2025-11-02T18:26:00.041Z",
      "expiresAt": "2025-11-02T18:41:00.318Z"
    }
  ]
}
```

### Key fields

| Field | Description |
|  --- | --- |
| `quoteCollectionId` | The ID of this collection. Use it to retrieve the collection later with `GET /v3/quotes/quote-collection/{quote-collection-id}`. |
| `quoteId` | The ID of an individual quote. Use the `quoteId` of the quote you choose to create a payment. |
| `quoteStatus` | `ACTIVE` means the quote can be used. `EXPIRED` means the validity window has passed and a new quote collection is required. |
| `paymentRail` | The payment rail for this quote, for example `SEPA_INSTANT` or `SPEI`. Each quote in the collection is for a different payment rail. |
| `adjustedExchangeRate.adjustedRate` | The FX rate Ripple applies to the payment. The rate is locked during the quote's validity window. |
| `fees[].totalFee` / `feeBreakdown` | Total service fee and a line-item breakdown. A line item can include the `paymentRail` it applies to. |
| `taxes` | Applicable consumption taxes on Ripple's fees, such as VAT or GST. Absent when no taxes apply. |
| `createdAt` / `expiresAt` | The quote's validity window. By default, quotes are valid for 15 minutes. |


### Choose a quote

Each quote in the collection is for one payment rail and has its own exchange rate and fees. All quotes in the collection expire at the same time. Review the quotes and choose the one that fits the payment. The payment records the payment rail of the quote you choose in `destination.selectedPaymentRail`. When present, `payoutExecutionDetails.paymentRailUsed` reports the rail used for the payout, which can differ. For each payment rail's delivery speed, see [Payment rail reference](/pt-br/products/payments-direct-2/api-docs/integration-resources/payment-rail-reference).

If Ripple can't price a payment rail for the request, the collection doesn't include a quote for it. If no payment rail can be priced, the request fails, usually with `SYS_018`, or with `USR_013` when the quote amount isn't enough to cover the transaction fees.

quoteId and paymentId
The `quoteId` you choose becomes the `paymentId` when you create the payment. Store it before moving to the next step.

## Step 3: Handle quote expiry

Quotes are valid for a limited time (15 minutes by default). Before creating a payment, check that the `quoteStatus` of the quote you chose is `ACTIVE`.

- If `quoteStatus` is `ACTIVE`, the quote can be used to create a payment.
- If `quoteStatus` is `EXPIRED`, the quote can no longer be used. Request a new quote collection, which reflects the current exchange rate and fees.


Use `expiresAt` to implement client-side refresh logic, for example, prompting a user to confirm before the quote lapses, or automatically re-quoting when the remaining time falls below a threshold.

```
remainingSeconds = expiresAt - now()
if remainingSeconds <= 0:
    request a new quote collection
```

All quotes in a collection have the same `expiresAt`. Re-quoting generates a new `quoteCollectionId` and new `quoteId` values.

## Step 4: Request a quote for one payment rail

If you already know which payment rail you want to use, include `paymentRail` in the request to receive a collection with one quote. This simplifies response handling when your integration always uses the same payment rail.

```bash
curl -i -X POST \
  https://api.test.ripple.com/v3/quotes/quote-collection \
  -H "Authorization: Bearer <YOUR_JWT_HERE>" \
  -H "Content-Type: application/json" \
  -d '{
    "quoteAmount": 10000,
    "quoteAmountType": "SOURCE_AMOUNT",
    "sourceCurrency": "USD",
    "destinationCurrency": "MXN",
    "sourceCountry": "US",
    "destinationCountry": "MX",
    "payinCategory": "PRE_FUNDING",
    "paymentRail": "SPEI"
  }'
```

The response contains a `quotes` array with one quote, for the `SPEI` payment rail. If the corridor doesn't offer the payment rail, the request fails with `USR_024`, and the error description lists the payment rails `/v3/quotes` offers for the corridor. If the corridor offers the payment rail, but not with `/v3/quotes`, the request fails with `USR_026`.

For valid `paymentRail` values, see [Payment rail reference](/pt-br/products/payments-direct-2/api-docs/integration-resources/payment-rail-reference).

## Step 5: Retrieve a quote collection

`GET /v3/quotes/quote-collection/{quote-collection-id}`

Use this endpoint to retrieve a quote collection you created earlier, for example in an async flow where you stored the `quoteCollectionId` and are checking quote status before initiating a payment.

```bash
curl -i -X GET \
  https://api.test.ripple.com/v3/quotes/quote-collection/11111111-aaaa-2222-bbbb-222222222222 \
  -H "Authorization: Bearer <YOUR_JWT_HERE>"
```

The response schema is identical to the `POST` response. Check the `quoteStatus` of the quote you want to use before proceeding, because it may have expired since it was created.

## Step 6: Retrieve an individual quote

`GET /v3/quotes/{quote-id}`

Use this endpoint to retrieve a specific quote by ID.

```bash
curl -i -X GET \
  https://api.test.ripple.com/v3/quotes/7ea3399c-1234-5678-8d8f-d320ea406630 \
  -H "Authorization: Bearer <YOUR_JWT_HERE>"
```

The response contains the same fields as a single entry from the `quotes` array, without the `quoteCollectionId` wrapper.

## Error handling

Quote errors return a structured response with a `status` and an `errors` array. Each error includes `code`, `title`, `type`, `description`, and `timestamp`.

Error codes use three prefixes:

| Prefix | Category | Common causes |
|  --- | --- | --- |
| `USR_` | Validation error | Missing required fields, invalid currency or country codes, an amount outside the allowed range, a `paymentRail` that isn't available for the corridor, the deprecated `payinCategory` values, or a corridor that isn't available with `/v3/quotes`. |
| `CFG_` | Configuration error | Missing or incomplete configuration for your account. Contact your Ripple representative if the error persists. |
| `SYS_` | System error | An internal or upstream failure. This includes `SYS_018` when no payment rail could be priced, and `SYS_017` when `/v3/quotes` finds no payment rail for the request: the corridor isn't available with `/v3/quotes`, or, for a stablecoin payout, no requested network is enabled for your account. Retrying doesn't change a `SYS_017` result; for a fiat corridor, try `/v2/quotes`. For other system errors, retry the request and contact support if the error persists. |


### Common validation errors

**Deprecated `payinCategory` values (`USR_025`)**: `/v3/quotes` doesn't accept `FUNDED` or `T_PLUS_ONE`. Use `PRE_FUNDING` in place of `FUNDED`, and `CREDIT_FUNDING` in place of `T_PLUS_ONE`.

**Payment rail not offered (`USR_024`)**: The corridor doesn't offer the `paymentRail` you sent. The error description lists the payment rails `/v3/quotes` offers for the corridor.

**Not available with `/v3/quotes` (`USR_026`)**: If you sent `paymentRail`, retry without it, because a payment rail that isn't available with `/v3/quotes` returns `USR_026` even when other payment rails for the corridor are. Otherwise, use `/v2/quotes` for this corridor. See [Fetch a quote collection (v2)](/pt-br/products/payments-direct-2/api-docs/developer-guides/fetch-a-quote-collection).

**Missing `destinationCountry` (`USR_017`)**: A fiat payout request must include `destinationCountry`. A stablecoin payout request must not include it.

**Invalid currency or country codes**: `sourceCurrency` and `destinationCurrency` must be 3–5 alphabetical characters. `sourceCountry` and `destinationCountry` must be ISO 3166-1 alpha-2 codes (exactly 2 characters).

For every error code, see [API errors](/pt-br/products/payments-direct-2/api-docs/error-handling/api-errors).

## What's next

After you have an `ACTIVE` quote and have chosen a `quoteId`, you are ready to create a payment.

See [Create a payment](/pt-br/products/payments-direct-2/api-docs/developer-guides/create-a-payment) for a complete walkthrough of the payment creation step, including how to pass the `quoteId` alongside beneficiary identity and financial instrument IDs.