Quotes
Request ranked, executable candidates for a trade intent. The router fans one intent out across direct DEX liquidity, the RFQ venue, bridges, issuers, and fiat rails, and every candidate comes back with its own stated guarantees: execution mode, guaranteed minimum output, fees, and expiry.
curl --request POST \
--url https://api.tetrafi.io/api/v1/rfq/quotes \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <api-key>' \
--data '
{
"user": "0x2e7E7cc62919eAf4c502dAC34753cFc5A29e9693",
"intent": {
"intentType": "swap",
"inputs": [
{
"user": "0x2e7E7cc62919eAf4c502dAC34753cFc5A29e9693",
"asset": {
"chainId": 10,
"address": "0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85"
},
"amount": "25000000"
}
],
"outputs": [
{
"receiver": "0x2e7E7cc62919eAf4c502dAC34753cFc5A29e9693",
"asset": {
"chainId": 8453,
"address": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"
}
}
],
"swapType": "ExactInput"
},
"supportedTypes": [
"escrow-v0"
]
}
'{
"quotes": [
{
"quoteId": "q_01J2M8W3N9RQK5T7V1X4Z6B8D0",
"solverId": "lp-atlas",
"executionMode": "apiSubmit",
"order": {
"type": "escrow-v0",
"payload": {
"...": "EIP-712 typed data - sign verbatim"
}
},
"validUntil": 1784560045,
"eta": 40,
"validity": {
"validUntil": 1784560045,
"minValidUntil": null
},
"preview": {
"inputs": [
{
"asset": "eip155:10/erc20:0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85",
"amount": "25000000",
"decimals": 6,
"symbol": "USDC",
"priceUsd": 0.9998
}
],
"outputs": [
{
"asset": "eip155:8453/erc20:0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"amount": "24987500",
"minimumAmount": "24987500",
"decimals": 6,
"symbol": "USDC",
"priceUsd": 0.9998,
"receiver": "0x2e7E7cc62919eAf4c502dAC34753cFc5A29e9693",
"amountBeforeFees": "25007500",
"deltaFromMid": -0.00011
}
]
},
"integrityChecksum": "9c41f2e8b06d5a73",
"routingPath": "direct",
"platformFeeBps": 5,
"lpSpreadBps": 3,
"splitFill": null,
"gas": {
"native": "0",
"usd": 0
},
"warnings": []
},
{
"quoteId": "q_01J2M8X0F2H4K6M8P0R2T4V6X8",
"solverId": "lp-meridian",
"executionMode": "walletBroadcast",
"order": {
"type": "escrow-v0",
"payload": {
"...": "EIP-712 typed data - sign verbatim"
}
},
"validUntil": 1784560032,
"eta": 55,
"validity": {
"validUntil": 1784560032,
"minValidUntil": null
},
"preview": {
"inputs": [
{
"asset": "eip155:10/erc20:0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85",
"amount": "25000000",
"decimals": 6,
"symbol": "USDC",
"priceUsd": 0.9998
}
],
"outputs": [
{
"asset": "eip155:8453/erc20:0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"amount": "24981200",
"minimumAmount": "24981200",
"decimals": 6,
"symbol": "USDC",
"priceUsd": 0.9998,
"receiver": "0x2e7E7cc62919eAf4c502dAC34753cFc5A29e9693",
"amountBeforeFees": "25001200",
"deltaFromMid": -0.00036
}
]
},
"integrityChecksum": "0f83aa517c2d9b64",
"routingPath": "direct",
"platformFeeBps": 5,
"lpSpreadBps": 4,
"splitFill": null,
"gas": {
"native": "391000000000000",
"usd": 1.31
},
"warnings": []
}
],
"totalQuotes": 2,
"metadata": {
"totalDurationMs": 380,
"solversQueried": 5,
"solversSuccess": 2
}
}OpenAPI
openapi: 3.1.0
info:
title: TetraFi Router API
version: '1'
description: >-
Multi-source routing over every eligible execution source. One intent fans out across
direct DEX liquidity, the RFQ venue, bridges, issuers, and fiat rails, and comes back
as ranked executable candidates - each stating its own guarantees.
servers:
- url: https://api.tetrafi.io/api/v1/router
description: >-
Router namespace base URL. The chain is no longer part of the URL - every asset in an
intent names its network via chainId. The same host serves the sandbox: authenticate
with a tfk_test_ key to route against test corridors, tfk_live_ for production.
security:
- apiKeyAuth: []
paths:
/quotes:
post:
summary: Quotes
description: >-
Request ranked, executable candidates for a trade intent. The router sweeps every
eligible source - direct DEX liquidity, the RFQ venue, bridges, issuers, and fiat
rails - and returns each candidate with its own stated guarantees. Several knobs from
older quote APIs are deliberately absent here: there is no sponsored-gas flag (who
lands the transaction is the per-candidate `executionMode`: `apiSubmit` | `walletBroadcast`),
no slippage parameter (each candidate prints guaranteed minimum outputs instead),
no approval-type choice (preflight selects the funding lock - Permit2, EIP-3009, or
resource lock - that the corridor and token support), and no per-request fee fields
(monetization is the `platformFeeBps` configured on your workspace, echoed on every
candidate).
operationId: requestQuotes
requestBody:
required: true
content:
application/json:
schema:
type: object
title: QuotesRequest
properties:
user:
type: string
title: User
description: >-
Wallet initiating the trade. It signs the order payload and, on walletBroadcast
candidates, broadcasts the prepared transactions.
example: '0x2e7E7cc62919eAf4c502dAC34753cFc5A29e9693'
intent:
type: object
title: Intent
description: >-
Declares what goes in and what must come out, rather than a fixed route.
Each asset carries its own chainId, so a single intent can span networks.
properties:
intentType:
type: string
title: Intent Type
description: Kind of intent; `swap` for a token-for-token trade.
default: swap
inputs:
type: array
title: Inputs
description: Asset(s) the user supplies. Ordered; multi-input intents
escrow each entry.
items:
type: object
title: IntentInput
properties:
user:
type: string
title: User
description: >-
Wallet that funds and signs this input. Usually identical to
the top-level user; it differs only in delegated flows.
asset:
type: object
title: Asset
description: >-
Asset reference: chainId names the network (this replaces the
per-chain base URL of earlier APIs) and address the token contract.
properties:
chainId:
type: integer
title: Chainid
description: Chain ID, e.g. 10 for Optimism.
address:
type: string
title: Address
description: Token contract address on that chain.
required:
- chainId
- address
amount:
anyOf:
- type: string
- type: 'null'
title: Amount
description: >-
Base-unit amount to send. Required when swapType is ExactInput;
leave unset with ExactOutput, where the router computes the
input needed.
required:
- user
- asset
outputs:
type: array
title: Outputs
description: Asset(s) that must be delivered, each with its own receiver.
items:
type: object
title: IntentOutput
properties:
receiver:
anyOf:
- type: string
- type: 'null'
title: Receiver
description: >-
Wallet that receives this output. Defaults to the top-level
user when unset; set a different address for swap-and-send.
Works in both execution modes.
asset:
type: object
title: Asset
description: >-
Asset reference: chainId names the destination network and address
the token contract.
properties:
chainId:
type: integer
title: Chainid
description: Chain ID, e.g. 8453 for Base.
address:
type: string
title: Address
description: Token contract address on that chain.
required:
- chainId
- address
amount:
anyOf:
- type: string
- type: 'null'
title: Amount
description: >-
Base-unit amount that must arrive. Set only when swapType is
ExactOutput; with ExactInput, delivery is whatever each candidate
prints in its preview.
required:
- asset
swapType:
type: string
enum:
- ExactInput
- ExactOutput
title: Swap Type
description: >-
Which side is fixed. ExactInput pins the amounts you send (amounts
live on inputs); ExactOutput pins what must arrive (amounts live on
outputs). This one switch replaces the older choose-one convention
between sell and buy amounts.
default: ExactInput
preference:
type: string
enum:
- Price
- Speed
- InputPriority
- TrustMinimization
title: Preference
description: >-
Ranking bias for the candidate list: best net price, fastest settlement,
input-order priority, or fewest trust assumptions.
default: Price
partialFill:
type: boolean
title: Partial Fill
description: >-
Allow the order to settle partially when the full size is not available
from a single candidate.
default: false
required:
- inputs
- outputs
supportedTypes:
type: array
items:
type: string
title: Supported Types
description: >-
Order payload types your signer can handle. `escrow-v0` is the current
settlement payload - send `["escrow-v0"]`.
example:
- escrow-v0
minValidUntil:
anyOf:
- type: integer
- type: 'null'
title: Min Valid Until
description: >-
Earliest acceptable candidate expiry (unix seconds). Candidates whose
firmness window closes sooner are filtered out - useful when your flow
needs time between quoting and submission.
solverOptions:
anyOf:
- type: object
- type: 'null'
title: Solver Options
description: >-
Per-request solver tuning: include or exclude specific solvers and adjust
sweep timeouts. Server-managed defaults apply when omitted.
routingOptions:
anyOf:
- type: object
- type: 'null'
title: Routing Options
description: >-
Multi-leg planner controls such as `routes` and `maxRouteLegs`. Server-managed
defaults apply when omitted.
required:
- user
- intent
- supportedTypes
examples:
ExactInput:
summary: Fix the input
description: Send exactly 25 USDC on Optimism; receive whatever that buys
on Base.
value:
user: '0x2e7E7cc62919eAf4c502dAC34753cFc5A29e9693'
intent:
intentType: swap
inputs:
- user: '0x2e7E7cc62919eAf4c502dAC34753cFc5A29e9693'
asset:
chainId: 10
address: '0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85'
amount: '25000000'
outputs:
- receiver: '0x2e7E7cc62919eAf4c502dAC34753cFc5A29e9693'
asset:
chainId: 8453
address: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913'
swapType: ExactInput
supportedTypes:
- escrow-v0
ExactOutput:
summary: Fix the output
description: >-
Deliver exactly 20 USDC on Base; the router works out the required input
on Optimism.
value:
user: '0x2e7E7cc62919eAf4c502dAC34753cFc5A29e9693'
intent:
intentType: swap
inputs:
- user: '0x2e7E7cc62919eAf4c502dAC34753cFc5A29e9693'
asset:
chainId: 10
address: '0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85'
outputs:
- receiver: '0x2e7E7cc62919eAf4c502dAC34753cFc5A29e9693'
asset:
chainId: 8453
address: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913'
amount: '20000000'
swapType: ExactOutput
supportedTypes:
- escrow-v0
responses:
'200':
description: Successful Response
content:
application/json:
schema:
$ref: '#/components/schemas/QuotesResponse'
examples:
Default:
summary: Move 25 USDC on Optimism into USDC on Base
value:
quotes:
- quoteId: q_01HZXK7Q9R2M4T6V8W0Y2A4C6E
solverId: tetrafi-native
executionMode: apiSubmit
order:
type: escrow-v0
payload:
'...': EIP-712 typed data - sign verbatim
validUntil: 1784560000
eta: 45
preview:
inputs:
- asset: eip155:10/erc20:0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85
amount: '25000000'
decimals: 6
symbol: USDC
priceUsd: 0.9998
outputs:
- asset: eip155:8453/erc20:0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913
amount: '24987500'
minimumAmount: '24950000'
decimals: 6
symbol: USDC
priceUsd: 0.9998
receiver: '0x2e7E7cc62919eAf4c502dAC34753cFc5A29e9693'
integrityChecksum: b74d21c09a4e5f38
routingPath: direct
platformFeeBps: 5
lpSpreadBps: 3
composite: null
gas:
native: '0'
usd: 0
warnings: []
- quoteId: q_01HZYA3B5D7F9H1J3L5N7P9R1T
solverId: bridge-route
executionMode: walletBroadcast
order: null
validUntil: 1784559900
eta: 180
preview:
inputs:
- asset: eip155:10/erc20:0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85
amount: '25000000'
decimals: 6
symbol: USDC
priceUsd: 0.9998
outputs:
- asset: eip155:8453/erc20:0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913
amount: '24924100'
minimumAmount: '24875000'
decimals: 6
symbol: USDC
priceUsd: 0.9998
receiver: '0x2e7E7cc62919eAf4c502dAC34753cFc5A29e9693'
integrityChecksum: 0f83aa517c2d9b64
routingPath: multiLeg
platformFeeBps: 5
lpSpreadBps: null
composite:
legs:
- kind: bridgeBurnMint
chainId: 10
- kind: sameChainSwap
chainId: 8453
executionModel: sequential
gas:
native: '412000000000000'
usd: 1.38
warnings: []
totalQuotes: 2
metadata:
totalDurationMs: 412
solversQueried: 6
solversSuccess: 2
routes:
plannerPasses: 1
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
components:
schemas:
GasEstimate:
properties:
native:
type: string
title: Native
description: >-
Estimated gas cost in the execution chain's native currency, base units. Zero
on apiSubmit candidates, where TetraFi carries the gas.
usd:
anyOf:
- type: number
- type: 'null'
title: Usd
description: The same estimate in US dollars, when a price is available.
type: object
required:
- native
title: GasEstimate
HTTPValidationError:
properties:
detail:
items:
$ref: '#/components/schemas/ValidationError'
type: array
title: Detail
type: object
title: HTTPValidationError
StandardOrder:
properties:
type:
type: string
title: Type
description: Order payload type; escrow-v0 for the current settlement contract.
payload:
type: object
title: Payload
description: >-
Complete EIP-712 envelope - domain, types, and the StandardOrder message - delivered
verbatim by the API. Treat it as opaque: sign exactly what arrives in quote.order
(or the typedData on preflight's orderSignature action) and never assemble or
edit it locally. The signed terms cover the parties, the inputs you escrow, the
minimum outputs that must be delivered, an expiry after which the unfilled order
refunds, and a domain-scoped nonce; they are bound to your submission by the integrityChecksum.
type: object
required:
- type
- payload
title: StandardOrder
description: >-
The escrow-v0 order payload a candidate asks you to sign. Anything you would want
different - receiver, amounts, expiry - changes at quote time, not signing time.
PriceWarning:
properties:
code:
type: integer
title: Code
description: Numeric warning identifier.
message:
type: string
title: Message
description: What the warning flags - unusual pricing, thin liquidity, or similar.
type: object
required:
- code
- message
title: PriceWarning
description: >-
Non-blocking warning attached to a candidate's warnings array so unusual conditions
surface before you select it.
QuotesResponse:
properties:
quotes:
items:
$ref: '#/components/schemas/QuoteCandidate'
type: array
title: Quotes
description: >-
Ranked executable candidates, best first under the requested preference. Every
entry is independently executable and states its own guarantees; one source being
down, slow, or empty never suppresses candidates from the others.
totalQuotes:
type: integer
title: Totalquotes
description: Number of candidates returned.
metadata:
type: object
title: Metadata
description: >-
How the sweep went - aggregation stats across sources plus the planner's route
detail.
properties:
totalDurationMs:
type: integer
title: Totaldurationms
description: Wall-clock milliseconds for the full sweep.
solversQueried:
type: integer
title: Solversqueried
description: Sources the request fanned out to.
solversSuccess:
type: integer
title: Solverssuccess
description: Sources that returned at least one usable candidate.
routes:
type: object
title: Routes
description: Multi-leg planner pass details.
type: object
required:
- quotes
- totalQuotes
title: QuotesResponse
PreviewOutput:
properties:
asset:
type: string
title: Asset
description: >-
Delivered asset in CAIP-19 form, e.g. eip155:8453/erc20:0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913.
amount:
type: string
title: Amount
description: Base-unit amount delivered if the candidate executes exactly as quoted.
minimumAmount:
anyOf:
- type: string
- type: 'null'
title: Minimumamount
description: >-
Floor the settlement must deliver - the per-candidate guarantee that replaces
a request-level slippage parameter.
decimals:
anyOf:
- type: integer
- type: 'null'
title: Decimals
description: Token decimals, for converting base units to a display amount.
symbol:
anyOf:
- type: string
- type: 'null'
title: Symbol
description: Token ticker symbol.
priceUsd:
anyOf:
- type: number
- type: 'null'
title: Priceusd
description: Reference US-dollar price per whole token, when available.
receiver:
anyOf:
- type: string
- type: 'null'
title: Receiver
description: Wallet this output is delivered to.
type: object
required:
- asset
- amount
title: PreviewOutput
PreviewInput:
properties:
asset:
type: string
title: Asset
description: >-
Escrowed asset in CAIP-19 form, e.g. eip155:10/erc20:0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85.
amount:
type: string
title: Amount
description: Base-unit amount the user sends.
decimals:
anyOf:
- type: integer
- type: 'null'
title: Decimals
description: Token decimals, for converting base units to a display amount.
symbol:
anyOf:
- type: string
- type: 'null'
title: Symbol
description: Token ticker symbol.
priceUsd:
anyOf:
- type: number
- type: 'null'
title: Priceusd
description: Reference US-dollar price per whole token, when available.
type: object
required:
- asset
- amount
title: PreviewInput
QuoteCandidate:
properties:
quoteId:
type: string
title: Quoteid
description: Identifier that follows the candidate through preflight, submission,
and status.
solverId:
type: string
title: Solverid
description: >-
Source that produced the candidate - e.g. tetrafi-native, a DEX adapter, or a
bridge route.
executionMode:
type: string
enum:
- apiSubmit
- walletBroadcast
title: Executionmode
description: >-
Who lands the transaction on-chain: apiSubmit means TetraFi submits the settlement
after you sign; walletBroadcast means you broadcast a prepared transaction yourself.
This per-candidate property replaces a request-level sponsored-gas flag.
order:
anyOf:
- $ref: '#/components/schemas/StandardOrder'
- type: 'null'
description: >-
The escrow-v0 payload to sign, present on direct candidates. Composite planner
routes carry prepared transactions via preflight instead.
validUntil:
type: integer
title: Validuntil
description: Unix timestamp ending the firmness window; the candidate expires at
this moment.
eta:
anyOf:
- type: integer
- type: 'null'
title: Eta
description: Expected seconds until settlement.
preview:
type: object
title: Preview
description: >-
Human-readable ins and outs - what the user sends and what arrives if the candidate
executes as quoted.
properties:
inputs:
items:
$ref: '#/components/schemas/PreviewInput'
type: array
title: Inputs
outputs:
items:
$ref: '#/components/schemas/PreviewOutput'
type: array
title: Outputs
required:
- inputs
- outputs
integrityChecksum:
type: string
title: Integritychecksum
description: >-
Tamper-evidence binding the terms you were shown to the terms you submit; any
drift between them is rejected.
routingPath:
type: string
title: Routingpath
description: >-
Route shape - direct for a single-source fill; multi-leg routes describe their
legs in composite.
platformFeeBps:
anyOf:
- type: integer
- type: 'null'
title: Platformfeebps
description: >-
Platform fee applied to this candidate, in basis points. Monetization is configured
per workspace, not passed per request.
lpSpreadBps:
anyOf:
- type: integer
- type: 'null'
title: Lpspreadbps
description: Spread earned by the liquidity provider on this candidate, in basis
points.
composite:
anyOf:
- type: object
properties:
legs:
type: array
items:
type: object
title: Legs
description: Ordered legs of the planner route, each naming its kind and
chain.
executionModel:
type: string
title: Executionmodel
description: How the legs run, e.g. sequential.
- type: 'null'
title: Composite
description: >-
Present on planner-assembled multi-leg routes; absent on direct single-source
quotes.
gas:
anyOf:
- $ref: '#/components/schemas/GasEstimate'
- type: 'null'
description: >-
Gas context for the candidate; the ranking already compares candidates net of
gas and explicit fees.
warnings:
items:
$ref: '#/components/schemas/PriceWarning'
type: array
title: Warnings
description: Non-blocking warnings attached to the candidate.
default: []
type: object
required:
- quoteId
- solverId
- executionMode
- validUntil
- preview
- integrityChecksum
title: QuoteCandidate
ValidationError:
properties:
loc:
items:
anyOf:
- type: string
- type: integer
type: array
title: Location
msg:
type: string
title: Message
type:
type: string
title: Error Type
type: object
required:
- loc
- msg
- type
title: ValidationError
securitySchemes:
apiKeyAuth:
type: apiKey
in: header
name: X-API-Key
description: Service-account API key (tfk_test_/tfk_live_).
Authorizations
Service-account API key (tfk_test_/tfk_live_).
Body
Wallet that signs the order and funds the trade. On walletBroadcast quotes it also broadcasts the prepared settlement transaction.
"0x2e7E7cc62919eAf4c502dAC34753cFc5A29e9693"
States what must go in and what must come out - not a route. Every asset carries its own chainId, so one intent can cross networks; multi-token shapes use multiple entries in inputs or outputs.
Show child attributes
Show child attributes
Order payload types your signer understands. The current settlement payload is escrow-v0 - pass ["escrow-v0"].
["escrow-v0"]
Earliest quote expiry (unix seconds) you will accept. Firm quotes whose window closes sooner are dropped before ranking - set it when your flow needs headroom between quoting and signing.
Per-request solver tuning: pin or exclude specific roster ids from GET /solvers, or adjust the sweep timeout. Server-managed defaults apply when omitted.
Response
Successful Response
Firm quotes ranked best price first. Every entry is a signed, executable commitment from a competing solver or LP - never a DEX, bridge, issuer, or indicative price. When no eligible counterparty can quote, the API returns a typed productUnavailable error instead of padding this list from another source.
Show child attributes
Show child attributes
Number of firm quotes returned.
How the sweep went - the competition behind the response, at a glance.
Show child attributes
Show child attributes