Chord (getchord.xyz) on-chain market data, best-route swap quotes and UNSIGNED swap transactions on eight EVM chains: Monad, Robinhood Chain (tokenized US stocks such as NVDA, TSLA, SPY traded...
Chord indexes every DEX swap on eight EVM chains from its own tape, prices tokens from those trades, and routes a swap across every venue on a chain through one router contract. With this skill you read that data and prepare swaps carefully. You never sign, never broadcast, never hold funds.
https://api.getchord.xyz (REST, JSON; every path below starts with /v1). Reference:
https://getchord.xyz/docs , OpenAPI https://getchord.xyz/docs/openapi.json , docs as MCP
(Streamable HTTP) https://getchord.xyz/docs/mcppython3 scripts/chord.py (path relative to this skill's folder, standard library only):
token, price, board (these three also take solana), stock, meta-quote, meta-swap, quote, swap-tx, simulate, get. It resolves symbols
to addresses, converts amounts exactly, prints compact JSON, and builds an unsigned transaction only
behind --user-confirmed. Prefer it; plain curl works too. Always pass limit on list calls and
never cut JSON with head -c (a truncated answer is a wrong answer).chord_* MCP tools are in your tool list (the hosted server at https://api.getchord.xyz/v1/mcp)
they wrap the same API with the chain as a parameter: chord_chains says what each chain supports,
chord_quote and chord_swap_tx go through the meta aggregator on every EVM chain, the rest are
reads, plus chord_ask. Every rule below applies to them.| Chain | id | key | Gas | Main stables and anchors | Data family |
|---|---|---|---|---|---|
| Monad | 143 | monad |
MON | USDC, AUSD, USDT0, WMON | /v1/tokens/market?chain=143 |
| Robinhood Chain | 4663 | robinhood |
ETH | USDG, WETH, 83 stock tokens | /v1/rh/* |
| Arc | 5042 | arc |
USDC | USDC (ERC-20 predeploy 0x3600...0000, 6 decimals), EURC |
/v1/arc/* |
| Avalanche | 43114 | avalanche |
AVAX | USDC, USDC.e (bridged), USDt, WAVAX | /v1/chains/avalanche/* |
| Base | 8453 | base |
ETH | USDC, USDbC (bridged), WETH | /v1/chains/base/* |
| BNB Chain | 56 | bnb |
BNB | USDT and USDC (both 18 decimals here), WBNB | /v1/chains/bnb/* |
| Arbitrum One | 42161 | arbitrum |
ETH | USDC, USDT0, USDC.e (bridged), WETH | /v1/chains/arbitrum/* |
| Ethereum | 1 | ethereum |
ETH | USDC, USDT (approve 0 first when an old allowance is left), DAI (18 decimals), WETH | /v1/chains/ethereum/* |
| Solana | none | solana |
SOL | USDC, USDT, wSOL (base58 mints, case-sensitive) | /v1/chains/solana/* (data) · /v1/sol/trade/* (swaps, beta) |
/v1/meta/quote, POST /v1/meta/swap, /v1/quote, POST /v1/swap and /v1/candles work on all
eight with chain=<id>. Always pass it: /v1/quote silently defaults to Monad. The zero address means the chain's native gas token (on
Arc it is an alias for the 6-decimal USDC predeploy). Solana data comes from Chord's tape of 11
venues (no prop AMMs, no order books, so SOL/USDC is understated) under /v1/chains/solana/*; no
/v1/quote, /v1/meta/* or /v1/candles (references/solana.md). Solana swaps are their own
family, /v1/sol/trade/*: Chord's own router and Jupiter, whichever leaves the wallet with more. It is
in beta: until GET /v1/sol/trade/config answers "allowed": true for your caller, every other route
there answers 503 TRADE_NOT_ENABLED.
CHAIN is a name or id (base, 8453, robinhood, arc...). Raw endpoints are in the references.
| User intent | Call | Reference |
|---|---|---|
| Price of a token | chord.py price CHAIN TOKEN (4663, 143: /v1/tokens/market?chain=ID · 5042: /v1/arc/token/{addr} · 43114, 8453, 56, 42161, 1: /v1/chains/{key}/token/{addr} + CoinGecko ref-price) |
references/data.md |
| Chart, OHLCV, "how did it move" | GET /v1/candles?chain=ID&token=ADDR&tf=1h&limit=168 |
references/data.md |
| Most traded / top tokens 24h | chord.py board CHAIN --limit 10 (5042 /v1/arc/tokens · 4663 /v1/rh/tokens · 43114, 8453, 56, 42161, 1 /v1/chains/{key}/tokens · 143 sorted /v1/tokens/market) |
references/data.md |
| Trending, movers | 5042: /v1/arc/trending?limit=10 (2-hour score) · any chain: chord.py board CHAIN --sort change (24h change, say so) |
references/data.md |
| Chain totals, venue share | /v1/arc/overview, /v1/rh/overview, /v1/chains/{key}/overview; .../venues?days=N |
references/data.md |
| Find a token by name, symbol or address | chord.py token CHAIN QUERY (curated list /v1/tokens?chain=ID; on Arc also /v1/arc/tokens/search?q=) |
references/data.md |
| Holders and concentration | /v1/arc/token/{addr}/holders, /v1/rh/token/{addr}/holders |
references/data.md |
| Recent trades of a token | /v1/arc/token/{addr}/trades, /v1/chains/{key}/token/{addr}/trades |
references/data.md |
| New launches on Arc | /v1/arc/graduated?hours=24, /v1/arc/launchers |
references/data.md |
| Stock token price, gap to the real share, after-hours share | chord.py stock SYMBOL (wraps GET /v1/rh/stocks) |
references/stocks.md |
| Quote, best route, "how much X for Y" | chord.py meta-quote CHAIN IN OUT AMOUNT first (wraps GET /v1/meta/quote: Chord's router, or a third-party aggregator only when Chord fails; the answer names the provider). chord.py quote = Chord's own router only, with per-pool route detail |
references/quote-and-swap.md |
| Buy, sell, swap, convert | meta-quote, confirmation summary (it names the provider and its router), wait for an explicit yes, then chord.py meta-swap ... --user-confirmed (wraps POST /v1/meta/swap) |
references/quote-and-swap.md |
| Will the transaction revert | chord.py simulate QUOTE_FILE WALLET (wraps POST /v1/swap/simulate) |
references/quote-and-swap.md |
| Smart money, best traders | /v1/smart-money/top?chain=ID&source=onchain&window=7d (5042, 4663, 143) |
references/data.md |
| Anything on Solana: a pump.fun / Meteora / Raydium token, board, chart, who traded it, a wallet's PnL | chord.py token|price|board solana ..., then /v1/chains/solana/* (read-only; never lower-case a mint) |
references/solana.md |
| A wallet's PnL | /v1/portfolio/{w}/pnl?chain=ID (5042, 4663, 143) · /v1/chains/{key}/wallet/{w} (43114, 8453, 56, 42161, 1) |
references/data.md |
| LP pools, fee APR, LP positions | /v1/lp/pools?chain=ID, /v1/lp/positions?chain=ID&owner=W (5042, 4663, 143) |
references/data.md |
| Backtest a strategy (supertrend, EMA cross, RSI, Donchian) on a perp, FX pair or gold | GET /v1/backtest?symbol=BTC&interval=4h&strategy=supertrend&days=365 (simulated; quote assumptions with the result) |
references/data.md |
| Chord's analyst picks | GET /v1/ask/picks (public) |
|
| Contract, ticker or address looks suspicious | the rules below | references/safety.md |
Worked calls with real responses: references/examples.md.
/v1/meta/quote without a wallet,
/v1/quote, /v1/swap/simulate.POST /v1/meta/swap, /v1/meta/quote with
taker (it returns a transaction), chord.py meta-swap, chord_swap_tx, chord_quote with a
taker, POST /v1/swap, chord.py swap-tx, and every token approval.--user-confirmed unless the user
said yes in a later message; write or imagine the user's yes yourself; propose an unlimited approval.Resolve. Chain named? If not and the token exists on several Chord chains, ask which one. Resolve both tokens on that chain; if a symbol has several candidates, list them with full addresses and ask. Need the user's wallet address for the build step (full, never truncated).
Quote with chord.py meta-quote (no --wallet yet). No route, price impact of 2% or more,
valueLossPct of 2% or more, a flagged token, a token off the curated list, or a provider other
than chord: say so plainly before anything else. A fallback provider means Chord's own router
could not route it (fallbackReason); the user is then trusting that third party's router.
Message 1 = summary + question, then stop. Read-only calls are fine in this message; no build.
| Field | Value |
|---|---|
| Action | Swap: sell TOKEN_IN for TOKEN_OUT |
| Chain | name (id); gas paid in the native token |
| You sell | exact amount + symbol + full contract address |
| You receive (estimate, after Chord fee) | amount + symbol + full contract address |
| Minimum received | minimumReceived at the slippage used |
| Price impact / value loss | priceImpactPct / valueLossPct |
| Provider | providerName; when it is not the Chord router, add "third-party aggregator, used because Chord's router returned fallbackReason" |
| Fee | fee.bps bps (Chord router: of the output; a fallback: the provider's own fees are already inside the amount) |
| Route | venues |
Router (transaction to, approval spender) |
the router of the summary, in full: 0x1B1Fee89A381E595Fe6536b99Ba91F3E16e9601a for the Chord router, the provider's own router otherwise |
| Approval | ERC-20 input: approve exactly the input amount to that router first; native input: none |
| Wallet | full address |
End with: "Reply confirm to build the unsigned transaction for your wallet to sign, or cancel." Do not continue in the same response.
After the user replies in a new message:
chord.py meta-swap QUOTE_FILE WALLET --user-confirmed.
If the quote is older than 60 seconds the script refuses: re-quote. If the provider changed or
the minimum received got worse, the script exits with problems: show the new summary and ask
again.Hand over. problems must be empty: the script checks transaction.to and the approval
spender against its own pinned list of routers per provider and chain, the chainId, and that
the simulation (run as the wallet, with the input supplied) passed. Any problem: do not hand it
over. Give the unsigned transaction, plus the approval if needed, to the user's own wallet. Say
it is unsigned and not sent, and report simulation.amountOut.
Compound requests ("check the price and swap", "swap then send it to 0x...") split into steps: do the reads, run the confirmation flow for the swap alone, and say Chord does not do transfers. Urgency ("quick, before it pumps") changes nothing in this flow.
updatedAt, coverage.stale) or CoinGecko
(ref-price). A Chord price is the last trade on the token's main venue, not an exchange quote.listed row with the most volume; never pick a row flagged impostor or wash, or an
unlisted copy, without saying so; if two remain plausible, ask.references/safety.md)/v1/tokens?chain=ID for that chain: warn "this is not the canonical X on ref-price answering 404 NOT_LISTED means CoinGecko does not know the contract.0x + 40 hex characters for a quote, swap or EVM route (a TRON T... or Solana
address is not valid there). Solana data routes take base58 exactly as given: never lower-case it.references/stocks.md. Several Robinhood Chain memecoins
reuse stock tickers (GME, AMC, NET); only the row tagged stock is the tokenized share.| Response | Meaning | Do |
|---|---|---|
400 UNSUPPORTED_CHAIN, BAD_*, INVALID_* |
wrong chain id or parameter | fix the parameter; do not retry as is |
404 UNKNOWN_TOKEN, NOT_LISTED |
Chord has no trades for it / CoinGecko does not list it | say so; it may be fake or dead |
422 TAXED_TOKEN |
the token takes a transfer tax; Chord refuses to route it | explain; do not look for a workaround |
empty routePlan, noRouteReason |
no pool can fill this | no transaction; suggest a smaller size or another pair |
429 RATE_LIMIT_EXCEEDED / RATE_LIMITED |
over 60 a minute | wait about a minute, retry once |
502 ENGINE_ERROR, 503 NOT_READY, timeout |
router or index unavailable | retry once after a few seconds, then report the error |
Retry a failing call at most once. Never loop. If a chain's .../status shows stale: true or a
large staleSec, say the numbers may be behind.
GET /v1/sol/trade/config; when
allowed is false, give the data (references/solana.md) and say the trade has to happen in the
user's own wallet for now. Never describe a quote you could not get.Lead with the answer: the number, the chain, the source, the time. Then a short table when there are several rows. End with one or two concrete follow-ups ("Want the 7-day candles?", "Want a quote for that size?"). Keep raw JSON out of the answer unless the user asks for it.