Skip to main content

What an FX Swap is

An FX Swap converts funds between two accounts of the same user that hold different currencies. It is an internal wallet-to-wallet operation: the origin account is debited in its currency and the destination account is credited in its currency at an exchange rate supplied by an external liquidity provider (e.g. EUR/USD).
The exchange rate is always set by the external provider — RalioPay never quotes its own rates. RalioPay’s margin is applied as an explicit fee over the origin amount (see Fees), never as a hidden spread on the rate.

Two ways to execute

1

Quote first (guaranteed rate)

Call Create FX quote to lock a rate. The quote returns a quoteId valid for 60 seconds (quote.validUntil). Then call Execute FX swap with that quoteId — the locked rate and amounts are used. A quote can be used only once.
2

Direct execution (market rate)

Skip the quote and call Execute FX swap directly with recipient and an amount. The swap executes at the provider’s market rate at that moment.
When executing with a quoteId, do not send fromAmount, toAmount, or recipient — they are already fixed by the quote. When executing without a quoteId, recipient is required along with exactly one amount field. ownReference and description are always required.

Amount direction: fromAmount vs toAmount

Both the quote and the direct execution accept exactly one of two amount fields, which determines the conversion direction: The response always carries a single rate field (the applicable provider rate for the chosen direction) together with the currency pair (e.g. "EUR/USD").

Lifecycle

Execution is asynchronous: the creation response returns the order in PENDING state while the origin funds are placed on hold and the swap is delegated to the provider.
Track progress by polling Get FX swap order details (detailUrl in the creation response) or, preferably, by subscribing to the FX swap webhook events.
The REST state field uses PENDING / SETTLED / FAILED, while webhook payloads report progress in data.status as PROCESSING / COMPLETED / FAILED. They describe the same lifecycle with different vocabularies — do not mix them.

Fees

The total fee is charged in the origin currency over the origin amount and is returned in the fee object with its breakdown:
For a SELL swap the fee is deducted from fromAmount before conversion; for a BUY swap it is added on top of the derived origin amount. The provider’s rate is passed through unchanged.

Amounts

All monetary amounts are expressed in minor units (e.g. cents): 100000 with currency EUR means 1000.00 EUR. Request amounts (fromAmount, toAmount) and every { "amount", "currency" } object in responses follow this rule.

Available endpoints

Errors

Error responses follow the standard shape:
QUOTE_EXPIRED is the only dedicated machine-readable error code for FX swaps. For every other case, key your handling off the HTTP status and the message field rather than the generic code.