# Get All Blockchains
Source: https://docs.uatu.dev/api-reference/catalogue/get-all-blockchains
/api-reference/openapi.json get /blockchains
Returns every chain the catalogue knows about, each with its embedded
token definitions.
# Get All Tokens
Source: https://docs.uatu.dev/api-reference/catalogue/get-all-tokens
/api-reference/openapi.json get /blockchains/tokens
Returns the known tokens. Omit chainId to list tokens across every chain.
# Get DEXes
Source: https://docs.uatu.dev/api-reference/catalogue/get-dexes
/api-reference/openapi.json get /blockchains/dex
Returns the seeded DEXes, including the router, factory, quoter and
settlement addresses used to price and encode a swap. Filter by chainId,
by slug, or by both; omit both to list every DEX. A slug identifies a DEX
only within one chain, so pass chainId alongside it for a single result.
# Get Pools for a Chain
Source: https://docs.uatu.dev/api-reference/catalogue/get-pools-for-a-chain
/api-reference/openapi.json get /blockchains/pools
Returns the liquidity pools discovered by the seeder for the given chain,
optionally filtered to a single DEX. Unlike the token endpoint, chainId
is required here.
# Compare same-chain DEX quotes
Source: https://docs.uatu.dev/api-reference/quotes/compare-same-chain-dex-quotes
/api-reference/openapi.json post /quotes/routes
Returns the best acceptable quote per DEX, sorted by output amount descending. Both chain IDs must match.
Estimates are not saved and contain no transaction steps. Use `POST /quotes` to get a fresh executable quote; prices and the selected route may change.
Input `amount` uses whole-token units; response amounts use integer strings in each token's smallest units.
# Create a swap or bridge quote
Source: https://docs.uatu.dev/api-reference/quotes/create-a-swap-or-bridge-quote
/api-reference/openapi.json post /quotes
Returns the best available DEX route for matching chain IDs, or a bridge route for different chains.
Returns a saved, pending quote with ordered transaction steps. Submit the steps yourself before the five-minute deadline (Unix seconds).
Input `amount` uses whole-token units; response amounts use integer strings in each token's smallest units.
# Catalogue
Source: https://docs.uatu.dev/concepts/catalogue
Chains, tokens, DEXes and pools, and how they're discovered.
The catalogue is uatu's view of what is swappable where. It is populated by the
seeding CLI and read back through the `/blockchains` endpoints.
## The four objects
A network uatu supports. Carries `name`, `slug`, `chainId`, `symbol`,
`nativeToken`, `blockExplorer`, `rpcUrl`, `ecosystem` and `blockChainLogo`, plus
the `tokens` array embedded within it.
The chain object does **not** carry its DEXes. Use `GET /blockchains/dex` for
those.
`ecosystem` says which virtual machine the chain runs: `evm`, `tvm` for TRON or
`svm` for Solana. It is what tells you how to read the chain's addresses.
`rpcUrl` comes back empty from the hosted API. The endpoint a deployment prices
against is its own configuration, not public data.
An ERC-20 or native asset: `address`, `symbol`, `name`, `slug`, `decimals`,
`logo` and the `blockchainId` it belongs to. `decimals` is what converts between
the integer and display amounts on a quote.
A protocol deployment on one chain. Beyond `name`, `slug` and `version`, it holds
the contract addresses uatu prices and encodes against: `v2FactoryAddress`,
`v2RouterAddress`, `v3FactoryAddress`, `v3RouterAddress`, `v3QuoterAddress`,
`universalRouterAddress`, `permit2Address` and `settlementAddress`.
A discovered liquidity pool: `pairAddress`, `poolType`, `poolFee`, `tickSpacing`,
the `baseToken` / `quoteToken` pair with their balances, `liquidity` and
`liquidityInUsd` breakdowns, `marketCap` and `isActivePool`.
## Reading the catalogue
| Endpoint | Returns | `chainId` filter |
| ------------------------- | ---------------------------------------- | ---------------------- |
| `GET /blockchains` | Chains, with embedded tokens | optional, as is `slug` |
| `GET /blockchains/tokens` | Tokens; omit the filter for all chains | optional |
| `GET /blockchains/pools` | Pools, optionally filtered by `dex` slug | required |
| `GET /blockchains/dex` | DEXes and their contract addresses | optional, as is `slug` |
`GET /blockchains` filters by `chainId`, by `slug`, or by both, and omitting both
lists every chain. Either one identifies a single chain on its own.
`GET /blockchains/dex` takes the same two filters, but there you want both: a slug
identifies a DEX only within a single chain, so `uniswap` on Ethereum and `uniswap`
on Base are different deployments with different addresses.
The result is always an array, and a protocol appears once per version, so
`chainId=1&slug=uniswap` returns two entries: Uniswap v2 and v3.
## The response envelope
Every endpoint wraps its payload in the same shape:
```json theme={null}
{
"code": 200,
"message": "Blockchains fetched successfully",
"data": []
}
```
`message` is always present and describes what was fetched, such as `Tokens fetched
successfully` or `Pools fetched successfully`. `data` holds the result, an object or
an array depending on the endpoint, and is absent on errors, where `message` carries
the reason and `code` mirrors the HTTP status.
## How pools get there
Chains, tokens and DEXes are declared in JSON definitions embedded into the binary at
build time. Pools are not: the `seed` command walks each chain's token list, queries
the v2 and v3 factories over RPC to find pools that actually exist, and persists what
it finds.
That means the catalogue reflects the last seed run, so what you can quote is what the
seeder found on-chain at that point.
# Supported chains
Source: https://docs.uatu.dev/concepts/chains
Every network in the catalogue, with its chain ID, native token and token count.
uatu supports 21 networks across EVM, Solana and TRON.
## Query the API
`GET /blockchains` returns the definitions your deployment is actually running, each
chain with its embedded tokens:
```sh theme={null}
curl https://api.uatu.dev/blockchains
```
## Chain reference
A snapshot of the shipped definitions:
| Chain | Native | VM | Tokens | Chain ID |
| --------------- | ------ | --- | ------ | ---------------- |
| Arbitrum | ETH | EVM | 7 | `42161` |
| Avalanche | AVAX | EVM | 7 | `43114` |
| Base | ETH | EVM | 6 | `8453` |
| BNB Smart Chain | BNB | EVM | 7 | `56` |
| Celo | CELO | EVM | 5 | `42220` |
| Ethereum | ETH | EVM | 6 | `1` |
| Gnosis | XDAI | EVM | 7 | `100` |
| Ink | ETH | EVM | 5 | `57073` |
| Linea | ETH | EVM | 6 | `59144` |
| Mantle | MNT | EVM | 6 | `5000` |
| Monad | MON | EVM | 5 | `143` |
| Optimism | ETH | EVM | 7 | `10` |
| Plasma | XPL | EVM | 4 | `9745` |
| Polygon | POL | EVM | 8 | `137` |
| Robinhood Chain | ETH | EVM | 4 | `4663` |
| Solana | SOL | SVM | 4 | `34268394551451` |
| Stable | STABLE | EVM | 5 | `988` |
| Tempo Mainnet | USDT0 | EVM | 3 | `4217` |
| TRON | TRX | TVM | 9 | `728126428` |
| Unichain | ETH | EVM | 8 | `130` |
| World Chain | ETH | EVM | 5 | `480` |
# Quotes
Source: https://docs.uatu.dev/concepts/quotes
Understand quote requests, amounts, slippage, and executable steps.
`POST /quotes` finds the best available DEX route when the origin and destination
chain IDs match, or a bridge route when they differ. It returns the transactions
needed to execute the quote. uatu prepares the route and calldata; your wallet signs
and broadcasts each transaction.
A quote does not reserve liquidity. Use it promptly and request a new one after its
`deadline` passes.
## Request a quote
Chain ID of the input token, for example `1` for Ethereum.
Chain ID of the output token. Use the same value as `originChainId` for a swap
on one chain, or a different value to request a bridge route.
Address of the token being sold on the origin chain.
Address of the token being received on the destination chain.
Amount of `tokenIn` to sell, supplied as a decimal string in display units,
such as `"1.5"`.
Address that receives `tokenOut`.
Maximum price movement you will accept, in basis points. If omitted, the
server default applies. See [Slippage](#slippage).
Missing, malformed, or incompatible values return a `400` response. See
[Errors](/guides/errors) for the response format.
Quote requests use `originChainId` and `destinationChainId` in place of `chain` and
`chainId`. The catalogue endpoints still use `chainId` as a query filter.
`POST /quotes/routes` accepts the same request fields, but both chain IDs must match.
## Read the response
The quote is returned in the response's `data` object. These are the fields most
integrations use:
| Field | Meaning |
| ------------------ | ------------------------------------------------------- |
| `quoteId` | Unique ID for the persisted quote |
| `route` | DEX selected for the swap |
| `amountIn` | Input amount in the token's smallest unit |
| `amountOut` | Quoted output in the token's smallest unit |
| `amountOutMinimum` | Lowest output the swap is allowed to return |
| `slippageBps` | Slippage tolerance applied to the quote |
| `steps` | Ordered transactions to sign and submit |
| `deadline` | Unix timestamp after which the quote should not be used |
| `status` | Quote status; a new quote starts as `pending` |
## Amounts
Input and output amounts are each represented in two forms:
| Fields | Format | Use |
| --------------------------------- | -------------------------------------------- | --------------------- |
| `amountIn`, `amountOut` | Integer strings in the token's smallest unit | On-chain calculations |
| `amountInFloat`, `amountOutFloat` | Decimal strings in display units | User interfaces |
Keep both forms as strings. Token amounts can exceed JavaScript's safe integer range,
and converting them to JSON numbers can silently lose precision.
## Execute the steps
`steps` contains the transactions required to execute the quote. Depending on the
input token and its existing allowances, a quote can include token approval, Permit2
approval, and swap steps.
Human-readable description of the step, such as a token approval.
Address that initiates the transaction.
Exexuting address/contract.
encoded calldata for the transaction.
Native-token value to attach to the transaction, when required.
Amount moved or approved by the step, in the token's smallest unit.
Contract receiving an allowance on approval steps, when provided.
Chain on which the transaction must be submitted.
Submit the steps in their returned order and wait for each transaction to confirm
before submitting the next one. Before asking the user to sign, verify that:
* the wallet is connected to the step's `chainId`;
* the connected account matches `from`;
* the quote's `deadline` has not passed; and
* the transaction includes `value` when one is provided.
Treat every step as an untrusted transaction request: show the destination,
value, and action to the user before signing. uatu never signs or broadcasts
transactions.
## Slippage
Pool prices can change between quote creation and execution. `slippageBps` controls
how much movement the swap accepts, where `100` basis points equals `1%`.
| Field | Meaning |
| ---------------------- | ------------------------------------------------------ |
| Request `slippageBps` | Optional tolerance requested by your client |
| Response `slippageBps` | Tolerance actually applied to the quote |
| `amountOutMinimum` | Minimum acceptable output in the token's smallest unit |
The swap calldata enforces `amountOutMinimum`. If the available output falls below
that value, the transaction reverts instead of completing at a worse price.
The default tolerance and maximum accepted value are configured per
deployment. A request above the configured maximum is rejected.
## Expiration
Each quote includes a `deadline` Unix timestamp, currently set five minutes after the
quote is created. If the deadline has passed, discard the steps and request a fresh
quote.
Always read `deadline` from the response instead of hard-coding the quote
lifetime.
Request a quote and execute its transaction steps.
# Create your first quote
Source: https://docs.uatu.dev/concepts/quotes/create-your-first-quote
Discover a token pair and request an executable swap quote.
Use the hosted API to find a token pair and create an executable WETH-to-USDC quote
on Ethereum. The catalogue endpoints are public; quote endpoints require an API key.
## Before you start
Create an API key in the [uatu console](/console), then store it in an environment
variable:
```sh theme={null}
export UATU_API_KEY="uatu_live_..."
```
Keep your API key on the server. Do not commit it or expose it in browser or mobile
application code.
All requests below use the hosted API at `https://api.uatu.dev`.
## 1. Choose a chain
`GET /blockchains` returns every supported chain and its token definitions. This
endpoint does not require authentication.
```sh theme={null}
curl https://api.uatu.dev/blockchains
```
Every response uses the same envelope: `code` mirrors the HTTP status, `message`
describes the result, and `data` contains the payload. Here is the Ethereum entry,
shortened for clarity:
```json theme={null}
{
"code": 200,
"message": "Blockchains fetched successfully",
"data": [
{
"name": "Ethereum",
"slug": "ethereum",
"chainId": 1,
"symbol": "ETH",
"nativeToken": "ETH",
"ecosystem": "evm",
"blockExplorer": "https://etherscan.io"
}
]
}
```
Save the chain's `chainId`. For this Ethereum swap, use `1` for both
`originChainId` and `destinationChainId` in the quote request.
## 2. Choose the tokens
Filter the token catalogue by the selected chain. Omit `chainId` to list tokens on
every chain.
```sh theme={null}
curl "https://api.uatu.dev/blockchains/tokens?chainId=1"
```
The response's `data` field is an array:
```json theme={null}
{
"code": 200,
"message": "Tokens fetched successfully",
"data": [
{
"name": "Wrapped Ether",
"symbol": "WETH",
"address": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
"decimals": 18,
"slug": "weth",
"blockchainId": 1
},
{
"name": "USD Coin",
"symbol": "USDC",
"address": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
"decimals": 6,
"slug": "usdc",
"blockchainId": 1
}
]
}
```
You need each token's `address` for the quote. Keep `decimals` as well: raw amounts
in the response use the token's smallest unit.
## 3. Request a quote
`POST /quotes` prices the pair across the available DEX routes and returns the best
route with ready-to-sign transaction data.
Replace `0xYourRecipientAddress` with the address that will receive USDC:
```sh theme={null}
curl -X POST https://api.uatu.dev/quotes \
-H "Authorization: Bearer ${UATU_API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"originChainId": 1,
"destinationChainId": 1,
"tokenIn": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
"tokenOut": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
"amount": "1",
"recipientAddress": "0xYourRecipientAddress",
"slippageBps": 50
}'
```
The first six fields are required. `amount` is a decimal string in the input token's
display units, so `"1"` means 1 WETH—not 1 wei. `slippageBps` is optional; `50`
allows 0.5% slippage. If omitted, the server default applies. See
[Slippage](/concepts/quotes#slippage) for details.
## 4. Read and execute the quote
The response includes the chosen route, the minimum acceptable output, an expiry,
and the transactions your wallet must submit. This representative response is
shortened:
```json theme={null}
{
"code": 200,
"message": "Quote created successfully",
"data": {
"quoteId": "4d4cb5b4-6d7a-48ed-a7fd-b2e20c556fd8",
"amountIn": "1000000000000000000",
"amountOut": "2493777615",
"amountOutMinimum": "2481308726",
"amountInFloat": "1",
"amountOutFloat": "2493.777615",
"slippageBps": 50,
"route": {
"dex": "uniswap",
"name": "Uniswap",
"fees": "42207128027132"
},
"steps": [
{
"message": "Permit2 approval",
"from": "0x...",
"to": "0x...",
"amount": "1000000000000000000",
"data": "0x...",
"chainId": 1
},
{
"message": "Swap WETH to USDC",
"from": "0x...",
"to": "0x...",
"amount": "1000000000000000000",
"data": "0x...",
"chainId": 1
}
],
"deadline": 1787624479,
"status": "pending"
}
}
```
Before submitting anything:
* Display `amountOutFloat`, but use the integer amount fields for on-chain logic.
* Make sure the current Unix time is earlier than `deadline`; otherwise, request a
new quote.
* Submit every item in `steps` in order with the wallet in `from`, waiting for each
transaction to confirm before sending the next.
* Include a step's `value` when present. Native-token swaps use it to carry the
transaction's native value.
The swap calldata enforces `amountOutMinimum`. If the market moves below that floor,
the transaction reverts instead of filling at a worse price.
Send quote steps with viem or ethers.js and handle common edge cases.
Review every endpoint, parameter, and response schema.
# Console
Source: https://docs.uatu.dev/console
Create, secure, rotate, and monitor API keys.
Use the [uatu console](https://console.uatu.dev) to manage your organization's API
keys and members from one place.
Go to console.uatu.dev
## Create an API key
Open [console.uatu.dev](https://console.uatu.dev) and sign in to your
organization.
The **API keys** page lists your organization's keys, including their status,
creator, creation date, and last-used time.
Give the key a descriptive name, such as `checkout-production` or
`quotes-staging`. You can also set an optional expiration date; a key without
one does not expire automatically.
Keys start with `uatu_live_`. Copy the new key directly into your secret manager
or deployment environment.
The complete key is shown only once. The console stores a hash and cannot
reveal the value later. If you lose it, revoke the key and create a new one.
## Authenticate a request
Load the key from an environment variable instead of placing it directly in source
code:
```sh theme={null}
export UATU_API_KEY="uatu_live_..."
```
Send it as a bearer token when requesting a quote:
```sh theme={null}
curl -X POST https://api.uatu.dev/quotes \
-H "Authorization: Bearer ${UATU_API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"chain": "ethereum",
"chainId": 1,
"tokenIn": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
"tokenOut": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
"amount": "1",
"recipientAddress": "0xYourRecipientAddress"
}'
```
## Which endpoints need a key?
Creating an executable quote requires an API key. The catalogue is public.
| Endpoint | Authentication |
| ------------------------- | -------------- |
| `POST /quotes` | **Required** |
| `GET /blockchains` | Not required |
| `GET /blockchains/tokens` | Not required |
| `GET /blockchains/pools` | Not required |
| `GET /blockchains/dex` | Not required |
Public catalogue requests let you discover chains, tokens, DEXes, and pools before
signing up.
## Rotate or revoke a key
Rotate a key without interrupting traffic:
Give the replacement a name that identifies the same service and environment.
Update your secret manager or deployment environment and verify that requests
are using the new key.
Wait until the old key's **Last used** value shows that traffic has moved. Allow
at least one minute for reporting to catch up.
Revocation takes effect immediately. A revoked key remains in the console for
audit history but can no longer authenticate requests.
## Keep keys safe
* Keep keys in server-side secret storage. Anything in a browser bundle or mobile
application can be extracted.
* Use a separate key for each service and environment to limit the impact of a leak
and make rotation or revocation more precise.
* Set an expiration date when a key is only needed temporarily.
* Revoke keys you no longer recognize or use.
* Never commit a key to version control or include it in logs and error messages.
# Build with AI agents
Source: https://docs.uatu.dev/guides/ai-agents
Give coding agents accurate uatu context through Markdown, MCP, or OpenAPI.
uatu publishes its documentation in formats that coding agents can read directly.
Use a Markdown page for a focused task, `llms.txt` for documentation discovery, MCP
for ongoing search, or the OpenAPI document to generate a typed client.
The documentation is public. Your application still needs an [API key](/console) to
request a quote from `https://api.uatu.dev`.
Do not paste an API key into a prompt or send it to the documentation MCP server.
Keep the key in server-side secret storage and load it at runtime.
## Choose a context source
| Need | Source |
| ---------------------------------------------- | ------------------------------------------------------------------ |
| Find the relevant documentation | [`llms.txt`](https://docs.uatu.dev/llms.txt) |
| Provide the complete documentation in one file | [`llms-full.txt`](https://docs.uatu.dev/llms-full.txt) |
| Explain the quote-to-transaction flow | [`integration.md`](https://docs.uatu.dev/guides/integration.md) |
| Generate types or a client | [`openapi.json`](https://docs.uatu.dev/api-reference/openapi.json) |
| Search the docs throughout a task | [uatu docs MCP](https://docs.uatu.dev/mcp) |
Start with `llms.txt` for most tasks. It is an index that lets the agent find and
read only the pages it needs. Use `llms-full.txt` when the agent cannot fetch linked
pages or when you need a single offline snapshot.
You can also append `.md` to an individual documentation URL to retrieve that page
as plain Markdown:
```text theme={null}
https://docs.uatu.dev/guides/integration.md
https://docs.uatu.dev/concepts/quotes.md
https://docs.uatu.dev/concepts/quotes/create-your-first-quote.md
```
A concise starting instruction is often enough:
```text theme={null}
Read https://docs.uatu.dev/llms.txt. Find the pages relevant to implementing a uatu
swap with viem, then follow those pages as the source of truth.
```
## Connect the documentation MCP server
Connect MCP when an agent needs to search and revisit the docs throughout a longer
task. The server is public and read-only with respect to the uatu API:
```text theme={null}
https://docs.uatu.dev/mcp
```
```sh theme={null}
claude mcp add --transport http uatu-docs https://docs.uatu.dev/mcp
```
Add this server to `~/.cursor/mcp.json`:
```json theme={null}
{
"mcpServers": {
"uatu-docs": {
"url": "https://docs.uatu.dev/mcp"
}
}
}
```
Add this server to `.vscode/mcp.json`:
```json theme={null}
{
"servers": {
"uatu-docs": {
"type": "http",
"url": "https://docs.uatu.dev/mcp"
}
}
}
```
Add this server to `claude_desktop_config.json`:
```json theme={null}
{
"mcpServers": {
"uatu-docs": {
"command": "npx",
"args": ["-y", "mcp-remote", "https://docs.uatu.dev/mcp"]
}
}
}
```
Once connected, the agent can search the documentation, read pages, and report
documentation feedback. The server cannot create quotes, sign transactions, or
access your API key.
## Generate a typed client
Use the OpenAPI document when the task is primarily about request and response
types:
```text theme={null}
https://docs.uatu.dev/api-reference/openapi.json
```
It defines the API endpoints and schemas consumed by tools such as
`openapi-typescript` and `openapi-generator`. Generated types help prevent agents
from borrowing incompatible field names from other swap APIs.
## Use a constrained implementation prompt
Tell the agent what to build and which safety boundaries it must preserve. Adapt
this template to your project:
```text theme={null}
Read https://docs.uatu.dev/llms.txt and use the linked uatu documentation as the
source of truth.
Implement a server-side swap flow using the uatu API at https://api.uatu.dev and
the conventions already used in this repository.
Requirements:
- use POST /quotes to get the best executable quote
- load UATU_API_KEY from the server environment and send it as a bearer token
- send `amount` as a decimal string in the input token's display units
- read the quote from the response's `data` field
- show `amountOutFloat` to the user and require confirmation before broadcasting
- reject an expired quote by checking `deadline` against the current Unix time
- submit every transaction in `steps` in order and wait for each receipt
- include `value` when a step provides it
- request a new quote after an expired quote or market-movement revert
- never invent endpoints, request fields, or response fields
Use viem. Keep signing in the wallet client; uatu only returns transaction data.
Run the relevant tests and report the files changed.
```
Documentation access and transaction authority are separate. An agent may read
these docs freely, but your application should still require explicit user
confirmation before a wallet signs or broadcasts a quote step.
# Errors
Source: https://docs.uatu.dev/guides/errors
Every response uses the same envelope. On success `data` carries the result; on
failure it is absent and `message` explains why.
```json theme={null}
{ "code": 400, "message": "invalid chain id" }
```
## Status codes
| Status | Meaning | What to do |
| ------ | ------------------------ | ------------------------------------------ |
| `200` | Success | Check `data` is not `null` before using it |
| `400` | The request was rejected | Fix the request, do not retry unchanged |
| `429` | Rate limited | Back off and retry |
| `500` | The service failed | Retry with backoff |
## Request validation
A quote request missing fields returns every problem at once, semicolon separated,
rather than failing on the first one:
```sh theme={null}
curl -X POST https://api.uatu.dev/quotes/routes \
-H "Authorization: Bearer ${UATU_API_KEY}" \
-H "Content-Type: application/json" \
-d '{"originChainId":1,"destinationChainId":1}'
```
```json theme={null}
{
"code": 400,
"message": "amount: is required; recipientAddress: is required; tokenIn: is required; tokenOut: is required"
}
```
`POST /quotes/routes` requires matching `originChainId` and `destinationChainId`.
Its API reference documents a `400` response for invalid requests or when no
acceptable same-chain quote is available.
## A 200 can still carry nothing
An unknown `chainId` on `/blockchains/pools` returns **`200` with `data: null`**,
not a `404`. Null-check every `data` before iterating, or you will crash on a
request that technically succeeded.
```sh theme={null}
curl "https://api.uatu.dev/blockchains/pools?chainId=999999"
```
```json theme={null}
{ "code": 200, "message": "Pools fetched successfully", "data": null }
```
Omitting `chainId` entirely is a different case and does fail properly:
```json theme={null}
{ "code": 400, "message": "invalid chain id" }
```
## Failures that are not HTTP errors
* **The swap reverts.** `amountOutMinimum` is enforced on-chain, so a market that
moved between quoting and broadcasting reverts the transaction rather than filling
at a worse price. Re-quote and retry.
# Integrate the API
Source: https://docs.uatu.dev/guides/integration
A working swap integration, from quote to execution.
Base URL is `https://api.uatu.dev`.
Quoting requires an API key, so create one in the [console](/console) first. The
catalogue endpoints are open.
## The flow
`POST /quotes` with the pair, the amount and who receives the output.
The response carries a `steps` array: an ordered list of ready-to-send
transactions, typically a Permit2 approval followed by the swap.
Sign and broadcast with your own wallet, waiting for each to confirm.
## Write the integration
```ts theme={null}
import { createWalletClient, createPublicClient, http } from "viem";
import { mainnet } from "viem/chains";
import { privateKeyToAccount } from "viem/accounts";
const UATU = "https://api.uatu.dev";
const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`);
const wallet = createWalletClient({ account, chain: mainnet, transport: http() });
const publicClient = createPublicClient({ chain: mainnet, transport: http() });
// 1. quote
const res = await fetch(`${UATU}/quotes`, {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.UATU_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
originChainId: 1,
destinationChainId: 1,
tokenIn: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", // WETH
tokenOut: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", // USDC
amount: "1",
recipientAddress: account.address,
slippageBps: 50, // optional, 0.5%
}),
});
const body = await res.json();
if (!res.ok) throw new Error(body.message);
const quote = body.data;
// 2. check the floor and the clock before spending gas
console.log(`out ${quote.amountOutFloat} USDC via ${quote.route.name}`);
console.log(`min ${quote.amountOutMinimum} (raw units)`);
if (Math.floor(Date.now() / 1000) >= Number(quote.deadline)) {
throw new Error("quote expired, request a new one");
}
// 3. send the steps in order
for (const step of quote.steps) {
const hash = await wallet.sendTransaction({
to: step.to as `0x${string}`,
data: step.data as `0x${string}`,
value: step.value ? BigInt(step.value) : 0n,
});
await publicClient.waitForTransactionReceipt({ hash });
console.log(`${step.message}: ${hash}`);
}
```
```ts theme={null}
import { JsonRpcProvider, Wallet } from "ethers";
const UATU = "https://api.uatu.dev";
const provider = new JsonRpcProvider(process.env.RPC_URL);
const wallet = new Wallet(process.env.PRIVATE_KEY!, provider);
// 1. quote
const res = await fetch(`${UATU}/quotes`, {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.UATU_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
originChainId: 1,
destinationChainId: 1,
tokenIn: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", // WETH
tokenOut: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", // USDC
amount: "1",
recipientAddress: wallet.address,
slippageBps: 50, // optional, 0.5%
}),
});
const body = await res.json();
if (!res.ok) throw new Error(body.message);
const quote = body.data;
// 2. check the floor and the clock before spending gas
console.log(`out ${quote.amountOutFloat} USDC via ${quote.route.name}`);
console.log(`min ${quote.amountOutMinimum} (raw units)`);
if (Math.floor(Date.now() / 1000) >= Number(quote.deadline)) {
throw new Error("quote expired, request a new one");
}
// 3. send the steps in order
for (const step of quote.steps) {
const tx = await wallet.sendTransaction({
to: step.to,
data: step.data,
value: step.value ? BigInt(step.value) : 0n,
});
await tx.wait();
console.log(`${step.message}: ${tx.hash}`);
}
```
## Get a read-only quote
`POST /quotes/routes` takes the same body, with matching `originChainId` and
`destinationChainId`, and returns the best acceptable quote per DEX, ordered by
output amount. Nothing is persisted and no transaction steps are returned. Use it
while a user is still choosing, then call `POST /quotes` for a fresh executable quote.
```sh theme={null}
curl -X POST https://api.uatu.dev/quotes/routes \
-H "Authorization: Bearer ${UATU_API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"originChainId": 1, "destinationChainId": 1,
"tokenIn": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
"tokenOut": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
"amount": "1",
"recipientAddress": "0xYourAddress"
}'
```
A real response, trimmed to one route:
```json theme={null}
{
"code": 200,
"message": "DEX quotes fetched successfully",
"data": [
{
"amountIn": "1000000000000000000",
"amountOut": "2493777615",
"amountOutMinimum": "2481308726",
"slippageBps": 50,
"deadline": 1787624479,
"route": { "name": "CowSwap", "dex": "cowswap", "fees": "42207128027132" }
}
]
}
```
## Common pitfalls
`amount` on the **request** is a decimal string in display units, so `"1"` means
one WETH. Amounts on the **response** are integer strings in the token's smallest
unit: `amountOut` of `"2493777615"` is 2493.777615 USDC at 6 decimals. Use
`amountOutFloat` for display and the raw integers for anything on-chain.
`deadline` is a Unix timestamp five minutes out. Check it before broadcasting,
especially if a user has been staring at a confirmation screen.
A swap usually needs its Permit2 approval mined before the swap itself. Wait
for each receipt rather than firing them together.
It is encoded into the calldata, so a fill worse than that floor reverts
rather than filling badly. A reverted swap that cost gas is usually a moved
market, not a bad request. Re-quote and retry.
When the input token is the chain's native asset, the step carries `value`. Send
it, or the swap reverts.
Every failure shape, with real responses.
# Overview
Source: https://docs.uatu.dev/index
A multichain DEX aggregation and swap-quote API spanning EVM, Solana and TRON.
Uatu aggregates tokens, DEXs, and liquidity pools across 21 blockchain networks to
deliver executable swap quotes through a single API.
```sh theme={null}
curl https://api.uatu.dev/blockchains
```
## What it does
Price a swap and get back the transactions your client needs to submit.
Discover which chains, tokens, DEXes and pools are swappable where.
See every EVM, Solana and TRON network in the catalogue and its DEXes.
## Supported protocols
Uniswap v2/v3 (plus Universal Router), PancakeSwap, SushiSwap, CowSwap, Aerodrome,
QuickSwap, OkuTrade, Agni Finance, Pharoah and SunSwap. Which protocols are available
is configured per chain; `GET /blockchains/dex` returns the DEXes on one chain. See
[Catalogue](/concepts/catalogue) for how to query them.
## Where to start
Get your first quote in a few `curl` calls.
Working TypeScript with viem or ethers, from quote to broadcast.
Every endpoint, parameter and response shape.
Connect these docs to Claude, Cursor or Copilot via MCP.
Create an API key and track your usage.
Amounts, steps, slippage and deadlines explained.
The 21 networks and their DEXes.