Quoter API¶
Use the SDK
Most integrations should use the SDK, which calls the Quoter API for you. Use this page if you can't use the SDK, for example because you aren't using TypeScript, or if you want to control every step yourself.
The Quoter API answers one question: if the user pays this much USDC on the origin chain, how much of the output token will they receive on the destination chain? The answer is the outputAmount you put in the order you send to the Intents contract.
POST https://www.tao.com/api/v1/intents/quotes
Content-Type: application/json
The endpoint needs no API key or access token.
Request¶
| Field | Required | Description |
|---|---|---|
originChainId |
Yes | Chain the user pays on, as a string. For example "1" for Ethereum. |
destinationChainId |
Yes | Chain the user receives on, as a string. Must differ from originChainId. |
inputTokenAddress |
Yes | USDC address on the origin chain. |
outputTokenAddress |
Yes | Token address the user should receive on the destination chain. Use 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE for the native token. |
inputAmount |
Yes | Amount the user pays, in the input token's base units, as a string. For USDC (6 decimals), 100 USDC is "100000000". |
userAddress |
Recommended | The address that will call open on the contract. Omit it only for an indicative price. |
recipient |
No | Address that receives the output on the destination chain. Defaults to userAddress. |
fillDeadline |
Recommended | Unix time in seconds by which the intent must be filled. Use the same value in the order you open. Enforced range: strictly after the current time, and at most 86,400 seconds (24 hours) later. The contract rejects a later deadline with FullSettler__FillDeadlineTooFar, even though the quoter still returns a quote for it. We recommend 5 minutes from now. |
Example¶
Quote 100 USDC on Ethereum into native TAO on Subtensor EVM. FILL_DEADLINE is 5 minutes from now:
FILL_DEADLINE=$(( $(date +%s) + 300 ))
curl -X POST https://www.tao.com/api/v1/intents/quotes \
-H "Content-Type: application/json" \
-d '{
"originChainId": "1",
"destinationChainId": "964",
"inputTokenAddress": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
"outputTokenAddress": "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",
"inputAmount": "100000000",
"userAddress": "0x1111111111111111111111111111111111111111",
"recipient": "0x1111111111111111111111111111111111111111",
"fillDeadline": '"$FILL_DEADLINE"'
}'
Response¶
{
"quote": {
"validUntil": 1790365985,
"preview": {
"inputs": [
{
"asset": "0x00010000010114a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
"amount": "100000000",
"userPaysUsd": "99.991607",
"userPaysUsdAfterSwap": "99.991607"
}
],
"outputs": [
{
"asset": "0x000100000203c414eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
"amount": "320584403022379535",
"userReceivesUsd": "98.036613"
}
]
}
},
"fees": {
"sellUsd": "100",
"totalUsd": "1.963386",
"effectiveRateBps": 196,
"totalInSellToken": "1963386",
"originNetworkFeeRao": "0",
"originNetworkFeeUsd": "0",
"poolFeeAndImpactUsd": "0.294994",
"spotBasisUsd": "0.008392",
"poolSlippageBps": 29,
"serviceUsd": "0.299974",
"solverUsd": "0.699941",
"fillGasUsd": "0.656925"
}
}
The fields you need:
| Field | Description |
|---|---|
quote.preview.outputs[0].amount |
The amount the user receives, in the output token's base units. Use it as outputAmount in the order. In this example it is about 0.32 TAO. |
quote.validUntil |
Unix time in seconds until which the quote holds. Quotes are valid for about 60 seconds. Open the intent before this time, and request a new quote afterwards. |
The other fields are informational and you should not depend on them:
quote.preview.inputsandquote.preview.outputsalso carry USD values such asuserPaysUsdanduserReceivesUsd.feesis a sibling ofquote, not part of it. It summarizes the cost of the transfer.
asset is not a token address
quote.preview.outputs[0].asset is a longer identifier that starts with a chain prefix, for example 0x000100000203c414eeee…. Do not use it as outputToken. Take the output token address from your own request.
Using the quote¶
Take the values you need from the quote and your own request:
| Order field | Value |
|---|---|
outputAmount |
quote.preview.outputs[0].amount, unchanged. |
inputAmount |
The inputAmount you sent in the request. |
fillDeadline |
The fillDeadline you sent in the request. |
outputToken, destinationChainId, recipient |
The same values you sent in the request. |
Use the quoted output amount as it is.
- An order that asks for more than the quote may not be filled, and it would then be refunded after the deadline.
- An order that asks for less than the quote can be filled, but the user receives only that lower amount, which leaves value on the table.
- An order that asks for zero is accepted by
open— the contract does not checkoutputAmountat open time — butfillalways reverts withFullSettler__InvalidAmounton a zero output. The order can never be filled and sits until it is refunded afterfillDeadline. Always send the quoted amount.
Errors¶
| Status | error |
Meaning |
|---|---|---|
400 |
Bad Request (with message: ["SAME_CHAIN_NOT_ALLOWED"] or another code), INVALID_FILL_DEADLINE |
The request failed validation. Examples: a malformed address, the same origin and destination chain, or a fillDeadline in the past. |
422 |
ALL_SOLVERS_FAILED |
Every quote provider rejected the request as invalid. failures[].code may carry a reason. |
429 |
RATE_LIMITED |
Too many requests. Retry after the delay in the message. |
502 |
ALL_SOLVERS_FAILED |
The quote could not be produced. failures entries can be missing a code. This is also the response for a token the route does not support, and for some amounts, such as a very small or a very large one, while other quotes succeed. Check the token addresses, try another amount or token, and retry later. |
502 |
SOLVER_FANOUT_FAILED |
An unexpected failure while requesting quotes. The body has a message. Retry shortly. |
503 |
SETTLER_PAUSED |
The Intents contract on this route is paused. New intents cannot be opened until it resumes. |
503 |
SETTLER_PAUSE_UNAVAILABLE, NO_SOLVERS_REGISTERED |
The quote service is temporarily unavailable. Retry shortly. |
504 |
ALL_SOLVERS_FAILED |
The quote request timed out. Retry shortly. |
ALL_SOLVERS_FAILED bodies also include polled (how many quote providers were asked) and failures, for example {"error":"ALL_SOLVERS_FAILED","polled":1,"failures":[{"solverId":1,"kind":"http_error","httpStatus":500}]}. Other errors use { "error", "message"?, "statusCode"? }.
Quotes do not depend on the user's balance or allowance, so you can request one before the user has funded their wallet.
Do not open an intent if you did not get a quote. The quote is your signal that a solver is able to fill the route at that price.
Rate limits¶
Quote requests are rate limited by source IP address, not by an API key or other client identity. If you call the endpoint from a shared IP, such as a backend serving many users or a NAT, all of that traffic shares one limit. Request a quote when the user is about to confirm, not on every keystroke, and reuse a quote until validUntil.
Next¶
- Smart Contract: submit the order.
- Integration Guide: a complete example that ties both steps together.
- Quoter API Reference: the OpenAPI reference for this endpoint.