Before you can create a payment, you request a quote collection: a set of priced quotes for a proposed transfer, one for each payment rail supported for the requested corridor. Each quote locks in an exchange rate, fee breakdown, and validity window so you can review the terms before committing to a payment.
This guide covers:
- Creating a quote collection, quoting by source or destination amount.
- Reading and comparing the response across multiple payment rails.
- Handling quote expiry.
- Filtering to a specific payment rail.
- Retrieving a quote collection or individual quote after creation.
For conceptual background, see Quotes and exchange rates.
To follow this guide, you need:
- Access to the Payments Direct API UAT environment.
- A valid OAuth2 access token with the
quote_collections:writescope. See Request an access token. - The source and destination currencies and countries for the proposed payment.
- A
payinCategorythat matches your funding model (PRE_FUNDING,CREDIT_FUNDING, orJIT_FUNDING). See Funding methods.
Access to the /v3/quotes/quote-collection endpoint requires explicit enablement by Ripple. If you attempt to use this endpoint before enablement is complete, requests will fail. Contact your Ripple representative to confirm your account is configured for V3 quotes before beginning integration.
POST /v3/quotes/quote-collection
A quote collection request specifies the corridor and amount you want to price. The response contains one quote per payment rail supported for that corridor.
| 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). |
payinCategory | Yes | Your funding model: PRE_FUNDING, CREDIT_FUNDING, or JIT_FUNDING. |
sourceCountry | No | The sender country (ISO 3166-1 alpha-2). |
destinationCountry | No | The beneficiary country (ISO 3166-1 alpha-2). |
paymentRail | No | Filter quotes to a specific rail. When omitted, all supported rails are returned. |
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.
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"
}'A successful request returns HTTP 201 with a quote collection. The top-level quoteCollectionId identifies the collection; the quotes array contains one entry per supported payment rail.
{
"quoteCollectionId": "11111111-aaaa-2222-bbbb-222222222222",
"quotes": [
{
"quoteId": "7ea3399c-1234-5678-8d8f-d320ea406630",
"quoteStatus": "ACTIVE",
"quoteAmountType": "SOURCE_AMOUNT",
"sourceAmount": 1000.00,
"destinationAmount": 921.45,
"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.000Z"
},
{
"quoteId": "9fb4500d-2345-6789-ae9f-e431fb517741",
"quoteStatus": "ACTIVE",
"quoteAmountType": "SOURCE_AMOUNT",
"sourceAmount": 1000.00,
"destinationAmount": 921.45,
"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.000Z",
"expiresAt": "2025-11-02T18:41:00.000Z"
}
]
}| 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 you select 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 network for this quote (for example, SEPA_INSTANT, SEPA_STANDARD, SPEI, US_ACH). Each rail in the collection has its own quote. |
adjustedExchangeRate.adjustedRate | The FX rate Ripple will apply. This rate is locked for the duration of the quote's validity window. |
fees[].totalFee / feeBreakdown | Total service fee and a line-item breakdown. Fees vary by rail. |
taxes | Applicable consumption taxes on Ripple's fees (VAT, GST, and so on). Absent when no taxes apply. |
createdAt / expiresAt | The quote's validity window. By default, quotes are valid for 15 minutes. |
When a corridor supports multiple rails, the quotes share the same exchange rate but typically differ in fees and processing speed. Use the totalFee and paymentRail values to select the quote that best fits your needs.
In the example above:
| Rail | Total fee | Speed |
|---|---|---|
SEPA_INSTANT | $8.50 USD | Seconds |
SEPA_STANDARD | $5.25 USD | 1 business day |
Select the quoteId for the rail you want to use and pass it to the Create payment operation.
The quoteId you select becomes the paymentId when you create the payment. Store it before moving to the next step.
Quotes are valid for a limited time (15 minutes by default). Before creating a payment, check that quoteStatus is ACTIVE.
- If
quoteStatusisACTIVE, the quote can be used to create a payment. - If
quoteStatusisEXPIRED, the quote can no longer be used. Request a new quote collection, which will reflect 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 collectionEach quote in a collection shares the same expiresAt. Re-quoting generates a new quoteCollectionId and new quoteId values.
If you already know which rail you want to use, include paymentRail in the request to receive a single-item collection. This simplifies response handling when rail selection is fixed by your integration.
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 a single entry for the SPEI rail. If the specified rail is not supported for the requested corridor, the API returns a CFG_ error.
For a full list of valid paymentRail values, see Payment rail reference.
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.
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 each quote's quoteStatus before proceeding; any quotes in the collection may have expired since they were created.
GET /v3/quotes/{quote-id}
Use this endpoint to retrieve a specific quote by ID.
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.
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 codes, amounts outside the allowed range (1–100,000,000), or deprecated payinCategory values. |
CFG_ | Configuration error | Unsupported corridor, missing tenant configuration, or a paymentRail value not supported for the requested corridor. |
SYS_ | System error | Internal or upstream FX pricing failure. Retry the request; contact support if the error persists. |
Deprecated payinCategory values: The v3 endpoint does not accept FUNDED or T_PLUS_ONE. Use PRE_FUNDING in place of FUNDED, and CREDIT_FUNDING in place of T_PLUS_ONE.
Invalid currency or country codes: sourceCurrency and destinationCurrency must be 3–5 alphabetic characters. sourceCountry and destinationCountry must be ISO 3166-1 alpha-2 codes (exactly 2 characters).
Unsupported corridor: If the currency pair is not configured for your tenant, the API returns a CFG_ error. Verify the corridor is listed in the Payment rail reference and contact your Ripple representative if the error persists.
Once you have an ACTIVE quote and have selected a quoteId, you are ready to create a payment.
See 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.