RFQs and quotes¶
POST /rfqs¶
Use this to create a quote request.
Header:
Idempotency-Key(required)
Semantics:
- RFQ expires at
created_at_ms + ttl_ms - Quote expiry must be within RFQ TTL
Core request fields:
account_id(required whenmode=firm)from_asset_key|from_symbol(one required)to_asset_key|to_symbol(one required)side:exact_inorexact_out- amount:
- exact-in:
amount_in_atomsoramount_in_ui - exact-out:
amount_out_atomsoramount_out_ui mode:indicativeorfirm
When using *_ui fields, enforce decimal precision from the asset's decimals value. Too many fractional digits will return 400 ui_precision_exceeded.
Destinations must be pre-registered via the address book. Trade requests reference a destination_id — inline addresses are not accepted.
Exception: recovery claims use inline destination details on POST /public/recover-funds.
Parameters¶
| Parameter | Type | Required | Description |
|---|---|---|---|
account_id |
string | Required when mode=firm |
Account identifier for firm quotes |
from_asset_key |
string | One of from_asset_key or from_symbol required |
Source asset by key |
from_symbol |
string | One of from_asset_key or from_symbol required |
Source asset by partner symbol |
to_asset_key |
string | One of to_asset_key or to_symbol required |
Destination asset by key |
to_symbol |
string | One of to_asset_key or to_symbol required |
Destination asset by partner symbol |
side |
enum | Yes | exact_in or exact_out |
amount_in_atoms |
string | One of amount_in_atoms or amount_in_ui required when side=exact_in |
Amount in atomic units (exact-in) |
amount_in_ui |
string | One of amount_in_atoms or amount_in_ui required when side=exact_in |
Amount in UI units (exact-in). Enforce decimal precision from asset decimals value; too many fractional digits returns 400 ui_precision_exceeded |
amount_out_atoms |
string | One of amount_out_atoms or amount_out_ui required when side=exact_out |
Amount in atomic units (exact-out) |
amount_out_ui |
string | One of amount_out_atoms or amount_out_ui required when side=exact_out |
Amount in UI units (exact-out). Enforce decimal precision from asset decimals value |
mode |
enum | Yes | indicative or firm |
ttl_ms |
integer | No | RFQ time-to-live in milliseconds. Default: 1000 |
wait_ms |
integer | No | Time to wait for quotes before returning. Default: 250 |
destination_id |
string | Required when mode=firm |
Pre-registered destination for the output asset. Optional for indicative quotes. |
credit_id |
string | Required when mode=firm |
Credit to source funds from. Each trade draws from exactly one credit. |
integrator_fee_bps |
string | No | Integrator markup in basis points (supports decimals, e.g. "2.5"), added on top of platform fee. Overrides organization default. See Fees. |
Indicative vs firm TTL¶
For indicative quotes displayed in a UI, use a longer ttl_ms (e.g. 5000–10000) to reduce request volume. The default 1000 is tuned for firm execution. Indicative quotes are not executable — a separate firm RFQ is required to trade.
Example request:
curl -X POST https://routes.srcry.xyz/v1/rfqs \
-H "Authorization: Bearer $ROUTES_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: unique-key-123" \
-d '{
"account_id": "acct_01J...",
"credit_id": "cred_01J...",
"from_asset_key": "spl.solana:XYZMINT...",
"to_asset_key": "native.zec",
"side": "exact_in",
"amount_in_ui": "1000",
"mode": "firm",
"ttl_ms": 1000,
"wait_ms": 250,
"destination_id": "dest_01J..."
}'
import httpx
response = httpx.post(
"https://routes.srcry.xyz/v1/rfqs",
headers={
"Authorization": f"Bearer {api_key}",
"Idempotency-Key": "unique-key-123",
},
json={
"account_id": "acct_01J...",
"credit_id": "cred_01J...",
"from_asset_key": "spl.solana:XYZMINT...",
"to_asset_key": "native.zec",
"side": "exact_in",
"amount_in_ui": "1000",
"mode": "firm",
"ttl_ms": 1000,
"wait_ms": 250,
"destination_id": "dest_01J..."
},
)
const response = await fetch("https://routes.srcry.xyz/v1/rfqs", {
method: "POST",
headers: {
"Authorization": `Bearer ${apiKey}`,
"Content-Type": "application/json",
"Idempotency-Key": "unique-key-123",
},
body: JSON.stringify({
account_id: "acct_01J...",
credit_id: "cred_01J...",
from_asset_key: "spl.solana:XYZMINT...",
to_asset_key: "native.zec",
side: "exact_in",
amount_in_ui: "1000",
mode: "firm",
ttl_ms: 1000,
wait_ms: 250,
destination_id: "dest_01J..."
}),
});
{
"account_id": "acct_01J...",
"credit_id": "cred_01J...",
"from_asset_key": "spl.solana:XYZMINT...",
"to_asset_key": "native.zec",
"side": "exact_in",
"amount_in_ui": "1000",
"mode": "firm",
"ttl_ms": 1000,
"wait_ms": 250,
"destination_id": "dest_01J..."
}
Response behavior:
200 readyincludesbest_quote_idwhen ready withinwait_ms- otherwise
202 pendingincludesrfq_idandpoll_after_ms
200 example:
{
"request_id": "req_01J...",
"rfq": {
"rfq_id": "rfq_01J...",
"status": "ready",
"best_quote_id": "qt_01J..."
}
}
Response fields (200)¶
| Field | Type | Description |
|---|---|---|
request_id |
string | Request identifier |
rfq.rfq_id |
string | RFQ identifier |
rfq.status |
string | ready |
rfq.best_quote_id |
string | Best quote identifier |
202 example:
{
"request_id": "req_01J...",
"rfq": {
"rfq_id": "rfq_01J...",
"status": "pending",
"poll_after_ms": 250
}
}
Response fields (202)¶
| Field | Type | Description |
|---|---|---|
request_id |
string | Request identifier |
rfq.rfq_id |
string | RFQ identifier |
rfq.status |
string | pending |
rfq.poll_after_ms |
integer | Milliseconds until next poll |
Idempotency semantics:
- same key + same payload -> same
rfq_idand stable logical response - same key + different payload ->
409 idempotency_key_reuse - replay while in-flight ->
202with samerfq_id
GET /rfqs/{rfq_id}¶
Use this to poll an RFQ until ready.
Example response:
{
"request_id": "req_01J...",
"rfq": {
"rfq_id": "rfq_01J...",
"status": "ready",
"best_quote_id": "qt_01J..."
}
}
GET /quotes/{quote_id}¶
Use this to retrieve a selected quote and route metadata. This endpoint does not expose solver execution plans.
Documented route metadata:
route_type:INTENTS_ONLY,HYBRID_SOLANA_TO_INTENTS,LOCAL_CHAIN_SWAPsettlement_domainsfees— platform and integrator fee breakdown (see Fees)route_requirements(for examplemin_intermediate_out)
Example response:
{
"request_id": "req_01J...",
"quote": {
"quote_id": "qt_01J...",
"rfq_id": "rfq_01J...",
"mode": "firm",
"expires_at_ms": 1730000010000,
"route_type": "HYBRID_SOLANA_TO_INTENTS",
"settlement_domains": [
"solana",
"destination_settlement"
],
"from_asset_key": "spl.solana:XYZMINT...",
"to_asset_key": "native.zec",
"side": "exact_in",
"amount_in_atoms": "1000000000",
"expected_out_atoms": "100000000",
"fees": {
"platform_bps": "5",
"integrator_bps": "10",
"total_bps": "15",
"platform_atoms": "50000",
"integrator_atoms": "100000",
"total_atoms": "150000"
},
"route_requirements": {
"min_intermediate_out": {
"asset_key": "spl.solana:USDCMINT...",
"min_out_atoms": "123450000"
}
}
}
}
Response fields¶
| Field | Type | Description |
|---|---|---|
request_id |
string | Request identifier |
quote.quote_id |
string | Quote identifier |
quote.rfq_id |
string | Parent RFQ identifier |
quote.mode |
string | indicative or firm |
quote.expires_at_ms |
integer | Quote expiry timestamp |
quote.route_type |
string | Route execution strategy |
quote.settlement_domains |
array | Settlement chain domains |
quote.from_asset_key |
string | Source asset key |
quote.to_asset_key |
string | Destination asset key |
quote.side |
string | exact_in or exact_out |
quote.amount_in_atoms |
string | Input amount in atoms |
quote.expected_out_atoms |
string | Expected output in atoms (net of all fees) |
quote.fees.platform_bps |
string | Platform fee in basis points |
quote.fees.integrator_bps |
string | Integrator fee in basis points |
quote.fees.total_bps |
string | Combined fee in basis points |
quote.fees.platform_atoms |
string | Platform fee in output asset atoms |
quote.fees.integrator_atoms |
string | Integrator fee in output asset atoms |
quote.fees.total_atoms |
string | Total fee in output asset atoms |
quote.route_requirements |
object | Route-specific constraints |