Chord Quote and swap API
Best-route quotes across every venue on the chain, and the unsigned transaction to execute them.
Best-route quotes across every venue on the chain, and the unsigned transaction to execute them.
Every API here is available over the APIs.io API and to AI agents over MCP.
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
find_apisBrowse and filter every API in the catalog.get_api_artifactsOne API's artifacts, grouped by type.get_openapiThe primary OpenAPI for this API.find_similar_apisAPIs that look like this one.apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.resolveTurn a domain, URL or GitHub org into the provider it belongs to.find_cohortsEvery scored population of providers in the catalog.curl "https://apis.io/api/v1/apis/getchord-xyz:getchord-xyz-quote-and-swap-api"
curl "https://apis.io/api/v1/apis?limit=25"
Calls without X-API-Key need no key. Calls with it need a paid plan — get a key.
Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.
A second provider on the same verified email joins the account you already have.
openapi: 3.2.0
info:
title: Chord Quote and swap API
version: '2026-10-05'
summary: Trade, data and agent endpoints for eight EVM chains (Ethereum 1, Arbitrum One 42161, Base 8453, BNB Chain 56, Avalanche 43114, Monad 143, Arc 5042, Robinhood Chain 4663) and Solana (data and swaps).
description: 'Chord is a non-custodial trading app and on-chain data index. The API has three kinds of endpoint:
- **Trade**: `/quote` finds the best route across every venue on the chain; `/swap` turns it into a transaction you sign yourself. Chord never holds funds or keys.
- **Read**: every swap on the chain, rolled up by token, venue and hour, from Chord''s own index — tokens, launches, holders, top wallets, portfolio PnL, liquidity positions and pools. No key needed. Avalanche, Base, BNB Chain, Arbitrum One and Ethereum have the same rollups under `/chains/{chain}/*`; Solana has its own data family under `/chains/solana/*` (base58 addresses, case-sensitive) and its swaps under `/sol/trade/*`.
- **Agent**: the analyst (`/ask`) and the streams.
Amounts are decimal strings in the token''s smallest unit. Timestamps are Unix seconds unless the field is `updatedAt` (milliseconds). `GET /portfolio/{wallet}` and `/portfolio/{wallet}/activity` differ on both: amounts there are in whole tokens and every time is in milliseconds. Reads answer anonymous callers at 60 requests a minute per IP; an `X-API-Key` header raises that to your plan. Every non-2xx body is `{ error, message }`.'
contact:
name: Chord
url: https://getchord.xyz/developer
x-logo:
url: https://getchord.xyz/chord/pwa-192x192.png?v=20261019
servers:
- url: https://api.getchord.xyz/v1
description: Production
tags:
- name: Quote and swap
description: Best-route quotes across every venue on the chain, and the unsigned transaction to execute them.
paths:
/quote:
get:
tags:
- Quote and swap
operationId: getQuote
summary: Best route for a swap
description: 'Quotes every venue on the chain in parallel, splits the order across venues when that improves the output, composes a two-hop route through the chain''s anchors when no direct pool wins, and returns the best.
**Use it for**: a price before a trade, a route card, an agent deciding whether to buy, a bot comparing venues.
**Notes**
- Amounts are strings in the token''s smallest unit. On Arc the USDC predeploy has 6 decimals, native USDC 18 — send the predeploy address `0x3600…0000` (the zero address is an alias for it on 5042).
- A quote is a live read of the venues and is good for about 30 seconds. Re-quote before you build if you waited longer.
- `fast=1` returns a single-hop answer in about 400 ms marked `preliminary`; run the full quote alongside and replace it.
- `only=` pins one venue and bypasses the routing safety gates — it needs an API key.
- An empty `routePlan` is a real answer (no route at this size); read `noRouteReason`.'
parameters:
- name: chain
in: query
required: false
schema:
type: integer
enum:
- 5042
- 4663
- 143
- 43114
- 8453
- 56
- 42161
- 1
default: 143
description: 'Chain id: `5042` Arc · `4663` Robinhood Chain · `143` Monad · `43114` Avalanche C-Chain · `8453` Base · `56` BNB Chain · `42161` Arbitrum One · `1` Ethereum. Omitted = 143. Always pass it.'
- name: inputMint
in: query
required: true
schema:
type: string
pattern: ^0x[a-fA-F0-9]{40}$
description: EVM address, hex, case-insensitive.
description: Token you sell. The zero address means the native unit (an alias for the USDC predeploy on Arc; ETH on Robinhood Chain).
- name: outputMint
in: query
required: true
schema:
type: string
pattern: ^0x[a-fA-F0-9]{40}$
description: EVM address, hex, case-insensitive.
description: Token you buy.
- name: amount
in: query
required: true
schema:
type: string
pattern: ^\d+$
description: Amount in the token's smallest unit, as a decimal string. Never a float.
description: Input amount, smallest unit.
- name: slippageBps
in: query
required: false
schema:
type: integer
minimum: 1
maximum: 5000
default: 50
description: Slippage tolerance in basis points; sets `otherAmountThreshold`.
- name: fast
in: query
required: false
schema:
type: integer
enum:
- 0
- 1
description: '1 = progressive first frame (single-hop, ~400 ms, `preliminary: true`).'
- name: only
in: query
required: false
schema:
type: string
pattern: ^[a-z0-9_]+$
description: 'Debug: restrict routing to one venue id. Requires `X-API-Key`.'
responses:
'200':
description: The best route. `routePlan` empty + `outputAmount` "0" = no route.
content:
application/json:
schema:
$ref: '#/components/schemas/QuoteResponse'
example:
inputMint: '0x3600000000000000000000000000000000000000'
outputMint: '0x171a4217b86a807a64eb94757db6849fb4bdbaa0'
inputAmount: '5000000'
outputAmount: '465'
otherAmountThreshold: '460'
slippageBps: 100
priceImpactPct: '92.51'
routePlan:
- percent: 100
swapInfo:
dex: uniswap_v4
pool: '0xdd9da42901118c475e6efb78117100e611c675e2c53bc801c4d2bfdd504b2e8d'
inputMint: '0x3600000000000000000000000000000000000000'
outputMint: '0x171a4217b86a807a64eb94757db6849fb4bdbaa0'
inputAmount: '5000000'
outputAmount: '465'
adapter: '0xd1d86d370f40471B79D9938B27F6ea040EbD6888'
extraData: '0x000000000000000000000000171a4217b86a807a64eb94757db6849fb4bdbaa00000000000000000000000003600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000017700000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000'
gasEstimate: '318189'
gasCostUSD: '0'
blockNumber: 21808240
timeTaken: 0.643
feeBps: 25
feeAmount: '1'
feeMint: '0x171a4217b86a807a64eb94757db6849fb4bdbaa0'
feeTier: meme
'400':
description: Invalid parameters — `error` names the check that failed (`INVALID_PARAMS`, `BAD_ADDRESS`, `BAD_LIMIT`, `BAD_HOURS`, …).
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'429':
description: Over the per-minute limit (`RATE_LIMIT_EXCEEDED`). Read `X-RateLimit-Reset` and back off.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'502':
description: The routing engine or an upstream did not answer (`ENGINE_ERROR`, `ROUTE_ERROR`).
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'503':
description: The lane behind this endpoint is not ready or not enabled here (`NOT_READY`, `CHAIN_NOT_ENABLED`, `NOT_ENABLED`, `*_UNAVAILABLE`). Retry later; do not treat it as an empty answer.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/swap:
post:
tags:
- Quote and swap
operationId: buildSwap
summary: Build an unsigned swap transaction
description: 'Turns a quote into a transaction against the Chord router. You sign it and broadcast it; Chord never sees a key and never holds funds.
**Notes**
- Send the `/quote` body back unmodified. `chain` must match the quote.
- For an ERC-20 input, approve the router (`transaction.to`) for at least `inputAmount` first — or run `/swap/simulate` and let it tell you.
- `slippageBps` is a consistency check only: the signed minimum output is the quote''s `otherAmountThreshold`. A different value is refused with `SLIPPAGE_MISMATCH` — re-quote at the slippage you want.
- On Arc the native sentinel aliases to the USDC predeploy: a "native" input is pulled by `transferFrom`, a "native" output is delivered as the predeploy, and `value` is always 0.
- `batch: "7702"` is Monad-only (EIP-7702 one-signature approve+swap); it is ignored on every other chain.'
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
quoteResponse:
$ref: '#/components/schemas/QuoteResponse'
userPublicKey:
type: string
pattern: ^0x[a-fA-F0-9]{40}$
description: Wallet that signs and receives the output.
chain:
type: integer
enum:
- 5042
- 4663
- 143
- 43114
- 8453
- 56
- 42161
- 1
default: 143
description: Must match the quote.
slippageBps:
type: integer
minimum: 1
maximum: 5000
description: Optional consistency check — same value the quote was requested with.
feeAccount:
type: string
pattern: ^0x[a-fA-F0-9]{40}$
description: Referrer credited with the referral share of the protocol fee.
wrapUnwrapMON:
type: boolean
default: true
description: Wrap / unwrap the native unit around the swap where the chain has a wrapped native (not Arc).
usePermit2:
type: boolean
default: false
batch:
type: string
enum:
- '7702'
required:
- quoteResponse
- userPublicKey
example:
quoteResponse:
…: the /v1/quote body
userPublicKey: '0xb145400da27a2497d9fc2cd5621f2bfd37617af4'
chain: 5042
responses:
'200':
description: Sign `transaction` with any wallet library and submit it to the chain in `chainId`.
content:
application/json:
schema:
type: object
properties:
transaction:
$ref: '#/components/schemas/SwapTx'
lastValidBlockHeight:
type: integer
description: Block after which the quote should be considered stale.
batch7702:
type: object
additionalProperties: true
description: Monad only — the one-signature approve+swap plan.
example:
transaction:
to: '0x1b1fee89a381e595fe6536b99ba91f3e16e9601a'
data: 0xdc72a437…
value: '0'
gasLimit: '1500000'
chainId: 5042
lastValidBlockHeight: 21808340
'400':
description: Invalid parameters — `error` names the check that failed (`INVALID_PARAMS`, `BAD_ADDRESS`, `BAD_LIMIT`, `BAD_HOURS`, …).
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'429':
description: Over the per-minute limit (`RATE_LIMIT_EXCEEDED`). Read `X-RateLimit-Reset` and back off.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'502':
description: The routing engine or an upstream did not answer (`ENGINE_ERROR`, `ROUTE_ERROR`).
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/swap/calldata:
get:
tags:
- Quote and swap
operationId: swapCalldata
summary: Quote and build in one call
description: 'For contracts and bots that call the router directly: routes and encodes in a single request. The output goes to `msg.sender`; the caller approves the router for `tokenIn` and sends the calldata.'
parameters:
- name: chain
in: query
required: false
schema:
type: integer
enum:
- 5042
- 4663
- 143
- 43114
- 8453
- 56
- 42161
- 1
default: 143
description: 'Chain id: `5042` Arc · `4663` Robinhood Chain · `143` Monad · `43114` Avalanche C-Chain · `8453` Base · `56` BNB Chain · `42161` Arbitrum One · `1` Ethereum. Omitted = 143.'
- name: tokenIn
in: query
required: true
schema:
type: string
pattern: ^0x[a-fA-F0-9]{40}$
description: EVM address, hex, case-insensitive.
description: Token the caller approves and sends.
- name: tokenOut
in: query
required: true
schema:
type: string
pattern: ^0x[a-fA-F0-9]{40}$
description: EVM address, hex, case-insensitive.
description: Token returned to msg.sender.
- name: amountIn
in: query
required: true
schema:
type: string
pattern: ^\d+$
description: Amount in the token's smallest unit, as a decimal string. Never a float.
description: ''
- name: slippageBps
in: query
required: false
schema:
type: integer
minimum: 1
maximum: 5000
default: 100
description: Sets `minOut` on the returned calldata.
responses:
'200':
description: Router call.
content:
application/json:
schema:
type: object
properties:
to:
type: string
pattern: ^0x[a-fA-F0-9]{40}$
description: EVM address, hex, case-insensitive.
data:
type: string
description: ''
value:
type: string
pattern: ^\d+$
description: Amount in the token's smallest unit, as a decimal string. Never a float.
minOut:
type: string
description: Minimum output, human units.
expectedOut:
type: string
description: Quoted output, human units.
gasLimit:
type: string
description: ''
example:
to: '0x1b1fee89a381e595fe6536b99ba91f3e16e9601a'
data: 0x…
value: '0'
minOut: '0.0942'
expectedOut: '0.0951'
gasLimit: '1000000'
'400':
description: Invalid parameters — `error` names the check that failed (`INVALID_PARAMS`, `BAD_ADDRESS`, `BAD_LIMIT`, `BAD_HOURS`, …).
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Nothing at this identity (`NOT_FOUND`, `UNKNOWN_TOKEN`, `NO_ROUTE`).
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'429':
description: Over the per-minute limit (`RATE_LIMIT_EXCEEDED`). Read `X-RateLimit-Reset` and back off.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'502':
description: The routing engine or an upstream did not answer (`ENGINE_ERROR`, `ROUTE_ERROR`).
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/swap/simulate:
post:
tags:
- Quote and swap
operationId: simulateSwap
summary: Simulate a built transaction before signing
description: '`eth_call`s the built calldata from the user''s address and estimates gas, so a revert is caught before the wallet opens. Known selectors are decoded (`NotRouter`, a paused Kuru market, allowance and balance errors). An allowance revert is advisory: approve first, then swap.'
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
chain:
type: integer
enum:
- 5042
- 4663
- 143
- 43114
- 8453
- 56
- 42161
- 1
from:
type: string
pattern: ^0x[a-fA-F0-9]{40}$
description: EVM address, hex, case-insensitive.
to:
type: string
pattern: ^0x[a-fA-F0-9]{40}$
description: EVM address, hex, case-insensitive.
data:
type: string
description: Calldata from `/swap`.
value:
type: string
pattern: ^\d+$
description: Amount in the token's smallest unit, as a decimal string. Never a float.
required:
- from
- to
- data
- value
example:
chain: 5042
from: '0xb145400da27a2497d9fc2cd5621f2bfd37617af4'
to: '0x1b1fee89a381e595fe6536b99ba91f3e16e9601a'
data: 0xdc72a437…
value: '0'
responses:
'200':
description: '`ok: true` with the simulated output and gas, or `ok: false` with the decoded revert.'
content:
application/json:
schema:
type: object
properties:
ok:
type: boolean
description: ''
amountOut:
type:
- string
- 'null'
description: Simulated output, smallest unit.
gas:
type:
- integer
- 'null'
description: Estimated gas units.
revert:
type: string
description: Decoded reason (when `ok` is false).
selector:
type:
- string
- 'null'
description: 4-byte error selector.
example:
ok: true
amountOut: '465'
gas: 318189
'400':
description: Invalid parameters — `error` names the check that failed (`INVALID_PARAMS`, `BAD_ADDRESS`, `BAD_LIMIT`, `BAD_HOURS`, …).
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'503':
description: The lane behind this endpoint is not ready or not enabled here (`NOT_READY`, `CHAIN_NOT_ENABLED`, `NOT_ENABLED`, `*_UNAVAILABLE`). Retry later; do not treat it as an empty answer.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
components:
schemas:
SwapTx:
type: object
properties:
to:
type: string
pattern: ^0x[a-fA-F0-9]{40}$
description: EVM address, hex, case-insensitive.
data:
type: string
description: Calldata.
value:
type: string
pattern: ^\d+$
description: Amount in the token's smallest unit, as a decimal string. Never a float.
gasLimit:
type: string
description: ''
chainId:
type: integer
description: ''
description: Unsigned transaction against the router.
Error:
type: object
properties:
error:
type: string
description: Stable machine code, e.g. `INVALID_PARAMS`, `NOT_READY`, `RATE_LIMIT_EXCEEDED`.
message:
type: string
description: For humans.
statusCode:
type: integer
description: HTTP status, when included.
description: Every non-2xx body.
required:
- error
example:
error: INVALID_PARAMS
message: amount must be an integer string in the token's smallest unit
QuoteResponse:
type: object
properties:
inputMint:
type: string
pattern: ^0x[a-fA-F0-9]{40}$
description: EVM address, hex, case-insensitive.
outputMint:
type: string
pattern: ^0x[a-fA-F0-9]{40}$
description: EVM address, hex, case-insensitive.
inputAmount:
type: string
pattern: ^\d+$
description: Amount in the token's smallest unit, as a decimal string. Never a float.
outputAmount:
type: string
pattern: ^\d+$
description: Amount in the token's smallest unit, as a decimal string. Never a float.
otherAmountThreshold:
type: string
pattern: ^\d+$
description: Minimum output after fee and slippage — the number the transaction enforces.
slippageBps:
type: integer
description: ''
priceImpactPct:
type: string
description: Percent, as a string, against the spot rate of the same route.
routePlan:
type: array
items:
$ref: '#/components/schemas/RouteLeg'
description: Empty with `outputAmount` "0" = no route (an honest answer, never a fabricated price).
noRouteReason:
type: string
description: 'Only when `routePlan` is empty: `INSUFFICIENT_LIQUIDITY` (try a smaller amount) or `NO_POOLS`.'
gasEstimate:
type: string
description: Gas units, from the venue quoter or the RPC.
gasCostUSD:
type: string
description: ''
blockNumber:
type: integer
description: ''
timeTaken:
type: number
description: Engine seconds.
feeBps:
type: integer
description: 'Protocol fee on the output token, per token on-chain (`FeeCollector.feeBpsFor`): 5 bps by default on every chain, 0 on the stablecoins and majors a chain exempts (USDC / EURC on Arc, WETH / USDG and stocks on Robinhood Chain), capped at 100.'
feeAmount:
type: string
pattern: ^\d+$
description: Amount in the token's smallest unit, as a decimal string. Never a float.
feeMint:
type: string
pattern: ^0x[a-fA-F0-9]{40}$
description: EVM address, hex, case-insensitive.
feeTier:
type: string
description: '`major` · `stable` · `standard` · `meme` · `new`.'
preliminary:
type: boolean
description: 'Present only on `fast=1` answers: single-hop, ~400 ms, replace it with the full quote.'
RouteLeg:
type: object
properties:
percent:
type: integer
description: Share of the input this leg carries.
swapInfo:
type: object
properties:
dex:
type: string
description: Venue id (see Resources → Venue ids).
pool:
type: string
description: Pool address, or the 32-byte pool id on Uniswap V4.
inputMint:
type: string
pattern: ^0x[a-fA-F0-9]{40}$
description: EVM address, hex, case-insensitive.
outputMint:
type: string
pattern: ^0x[a-fA-F0-9]{40}$
description: EVM address, hex, case-insensitive.
inputAmount:
type: string
pattern: ^\d+$
description: Amount in the token's smallest unit, as a decimal string. Never a float.
outputAmount:
type: string
pattern: ^\d+$
description: Amount in the token's smallest unit, as a decimal string. Never a float.
adapter:
type: string
description: The router adapter that executes this leg — from the engine, never hardcode.
extraData:
type: string
description: Adapter-specific calldata for the leg.
feeAmount:
type: string
pattern: ^\d+$
description: Amount in the token's smallest unit, as a decimal string. Never a float.
feeMint:
type: string
pattern: ^0x[a-fA-F0-9]{40}$
description: EVM address, hex, case-insensitive.
description: One leg of the route.
securitySchemes:
ApiKey:
type: apiKey
in: header
name: X-API-Key
description: Optional on every read. A key from getchord.xyz/developer raises the rate limit to your plan and meters usage per key. Required for `?only=` on quotes and for the Ask agent API.
Session:
type: http
scheme: bearer
description: A Google sign-in session minted by the app (`nts_…`). Only the browser surfaces use it; agents use `ApiKey`.