RFQ trading is available to UK customers.
Revolut X lets you trade large blocks of crypto that would otherwise cause significant price impact on the exchange order book.
How it works
Request for Quote (RFQ) trading happens off the order book: the trade is agreed directly between you and a market maker, so it doesn't go through the normal trading channels — that's why RFQ trading has its own set of endpoints.
The flow has three steps:
- Request an RFQ quote for a currency pair, side, and size.
- Receive an executable price with a short-lived signed quote token.
- Accept the quote to place the order, at exactly the quoted price.
If you are rate-limited, use the Retry-After response header, which specifies the delay in milliseconds.
See rate limits below.
All three RFQ endpoints are part of the Crypto Exchange REST API and use the same authentication: an API key with Ed25519 request signing. See Create an API key and Authenticate requests.
Before you begin
Before you start, make sure you have:
- An API key with RFQ permissions. Create an API key in the Revolut X web app with
rest.otc.viewto request quotes and view limits, andrest.otc.tradeto accept quotes. Agentic clients can use the correspondingagent.otc.viewandagent.otc.tradescopes. - Passed KYC (retail) or KYB (business) verification.
- High Net Worth categorisation (UK retail clients only). UK retail clients must be categorised as High Net Worth investors to use RFQ trading.
Check the minimum trade size before quoting. RFQ trades have a minimum in the pair's counter currency (e.g., USD for BTC/USD). Use Get RFQ limits to retrieve the exact minimum for a pair.
1. Request a quote
Request a quote by sending this request:
POST https://revx.revolut.com/api/1.0/otc/quotes HTTP/1.1
X-Revx-API-Key: <API_KEY>
X-Revx-Timestamp: <TIMESTAMP>
X-Revx-Signature: <SIGNATURE>
Content-Type: application/json
{
"symbol": "BTC/USD",
"side": "buy",
"qty": "2.5"
}Set side to buy or sell, and provide exactly one of:
qty: The quantity to trade, in the pair's base currency (BTC inBTC/USD).amount: The amount to spend or receive, in the pair's counter currency (USD inBTC/USD).
The response contains the executable price, the order book reference price, and the signed quote token:
{
"data": {
"quote_id": "550e8400-e29b-41d4-a716-446655440000",
"symbol": "BTC/USD",
"side": "buy",
"price": "79979.90",
"qty": "2.5",
"order_book_price": "80100",
"expires_at": 1785313438816,
"signature": "eyJxdW90ZV9lbnRyeV9pZCI6...",
"liquidity_status": "filled"
},
"metadata": {
"timestamp": 1785313433816
}
}The table below describes the fields of the data object.
| Field | Description |
|---|---|
quote_id | The unique identifier of the quote. |
symbol | The trading pair, in BASE/COUNTER format. |
side | The trade direction: buy or sell. |
price | The executable unit price, adjusted for fees. |
qty | The requested quantity in the base currency, included when the quote was requested by quantity. |
amount | The requested amount in the counter currency, included when the quote was requested by amount. |
order_book_price | The Volume Weighted Average Price (VWAP) of the exchange order book for the requested size — your reference for the quote's quality. |
expires_at | The quote's expiry as Unix epoch milliseconds. |
signature | The signed quote token. Pass it verbatim to accept the quote. |
liquidity_status | Whether the requested size was fully or partially covered by the order book: filled or partially_filled. |
All financial decimal values are returned as strings.
The response contains only the applicable qty or amount; fields with no value are omitted rather than returned as null.
Request a quote only when you are ready to trade, and accept it immediately. If the token expires, request a new quote — expired tokens are rejected.
2. Accept the quote
Accept the quote and place the order by sending this request:
POST https://revx.revolut.com/api/1.0/otc/orders HTTP/1.1
X-Revx-API-Key: <API_KEY>
X-Revx-Timestamp: <TIMESTAMP>
X-Revx-Signature: <SIGNATURE>
Content-Type: application/json
{
"signature": "eyJxdW90ZV9lbnRyeV9pZCI6..."
}The quote's terms (pair, side, size, price) are bound to the signed token and cannot be modified. The token is tied to your account. Treat it as single-use: once the downstream order has been submitted, retrying it does not create a second order. If acceptance fails before submission, request a new quote rather than relying on replay.
The response returns the placed RFQ order and its immediate execution status:
{
"data": {
"transaction_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"status": "filled"
},
"metadata": {
"timestamp": 1785313433816
}
}The table below describes the fields of the data object:
| Field | Description |
|---|---|
transaction_id | The unique identifier of the RFQ order returned by the flow. This is not necessarily the final ledger transaction ID. Settlement and finalisation can continue asynchronously. |
status | The immediate execution status of the RFQ order: filled or rejected. A rejected result comes with a reason and is terminal for that quote — request a new quote and retry. |
reason | Why the order was rejected. Present only when status is rejected, and omitted otherwise. |
A rejected response represents an immediate execution or fincrime decision.
Insufficient balance and other processing failures are returned as HTTP errors instead.
3. Check RFQ limits
Check the limits by sending this request:
GET https://revx.revolut.com/api/1.0/otc/limits?symbol=BTC/USD HTTP/1.1
X-Revx-API-Key: <API_KEY>
X-Revx-Timestamp: <TIMESTAMP>
X-Revx-Signature: <SIGNATURE>The response contains the minimum trade amount for the pair:
{
"data": {
"min_amount": "100000",
"symbol": "BTC/USD"
},
"metadata": {
"timestamp": 1785313433816
}
}The table below describes the fields of the data object:
| Field | Description |
|---|---|
min_amount | The minimum trade size in the pair's counter currency, returned as a decimal string. Quote requests below this minimum are rejected. |
symbol | The trading pair, in BASE/COUNTER format. |
Rate limits
| Endpoint | Per-second limit |
|---|---|
| Request a quote | 10 |
| Accept a quote | 5 |
| Check RFQ limits | 10 |
If you are rate-limited, use the Retry-After response header, which specifies the delay in milliseconds.
Errors
RFQ errors use the standard error response:
| HTTP | Description | Where |
|---|---|---|
| 403 | User with id <REGISTERED_IDENTITY_ID> cannot accept quote with id <QUOTE_ID> | Accept a quote |
| 422 | Quote expired or does not exist | Accept a quote |
| 400 | Quote token is invalid or tampered | Accept a quote |
| 403 | Sell temporarily unavailable | Request a quote |
| 422 | The quote cannot be served at this time | Request a quote |
| 400 | OTC quote amount is below minimum trade amount for BTC/USD: <MIN_AMOUNT> | Request a quote |
What's next
For the full request and response schemas, rate limits, and error samples, see the RFQ trading section of the Crypto Exchange REST API reference.