Skip to content

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.inputs and quote.preview.outputs also carry USD values such as userPaysUsd and userReceivesUsd.
  • fees is a sibling of quote, 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 check outputAmount at open time — but fill always reverts with FullSettler__InvalidAmount on a zero output. The order can never be filled and sits until it is refunded after fillDeadline. 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