Build an unsigned swap transaction
const url = 'https://api.getchord.xyz/v1/swap';const options = { method: 'POST', headers: {'Content-Type': 'application/json'}, body: '{"quoteResponse":{"…":"the /v1/quote body"},"userPublicKey":"0xb145400da27a2497d9fc2cd5621f2bfd37617af4","chain":5042}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request POST \ --url https://api.getchord.xyz/v1/swap \ --header 'Content-Type: application/json' \ --data '{ "quoteResponse": { "…": "the /v1/quote body" }, "userPublicKey": "0xb145400da27a2497d9fc2cd5621f2bfd37617af4", "chain": 5042 }'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
/quotebody back unmodified.chainmust match the quote. - For an ERC-20 input, approve the router (
transaction.to) for at leastinputAmountfirst — or run/swap/simulateand let it tell you. slippageBpsis a consistency check only: the signed minimum output is the quote’sotherAmountThreshold. A different value is refused withSLIPPAGE_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, andvalueis always 0. batch: "7702"is Monad-only (EIP-7702 one-signature approve+swap); it is ignored on every other chain.
Request Bodyrequired
Section titled “Request Bodyrequired”object
object
EVM address, hex, case-insensitive.
EVM address, hex, case-insensitive.
Amount in the token’s smallest unit, as a decimal string. Never a float.
Amount in the token’s smallest unit, as a decimal string. Never a float.
Minimum output after fee and slippage — the number the transaction enforces.
Percent, as a string, against the spot rate of the same route.
Empty with outputAmount “0” = no route (an honest answer, never a fabricated price).
One leg of the route.
object
Share of the input this leg carries.
object
Venue id (see Resources → Venue ids).
Pool address, or the 32-byte pool id on Uniswap V4.
EVM address, hex, case-insensitive.
EVM address, hex, case-insensitive.
Amount in the token’s smallest unit, as a decimal string. Never a float.
Amount in the token’s smallest unit, as a decimal string. Never a float.
The router adapter that executes this leg — from the engine, never hardcode.
Adapter-specific calldata for the leg.
Amount in the token’s smallest unit, as a decimal string. Never a float.
EVM address, hex, case-insensitive.
Only when routePlan is empty: INSUFFICIENT_LIQUIDITY (try a smaller amount) or NO_POOLS.
Gas units, from the venue quoter or the RPC.
Engine seconds.
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.
Amount in the token’s smallest unit, as a decimal string. Never a float.
EVM address, hex, case-insensitive.
major · stable · standard · meme · new.
Present only on fast=1 answers: single-hop, ~400 ms, replace it with the full quote.
Wallet that signs and receives the output.
Must match the quote.
Optional consistency check — same value the quote was requested with.
Referrer credited with the referral share of the protocol fee.
Wrap / unwrap the native unit around the swap where the chain has a wrapped native (not Arc).
Example
{ "quoteResponse": { "…": "the /v1/quote body" }, "userPublicKey": "0xb145400da27a2497d9fc2cd5621f2bfd37617af4", "chain": 5042}Responses
Section titled “ Responses ”Sign transaction with any wallet library and submit it to the chain in chainId.
object
Unsigned transaction against the router.
object
EVM address, hex, case-insensitive.
Calldata.
Amount in the token’s smallest unit, as a decimal string. Never a float.
Block after which the quote should be considered stale.
Monad only — the one-signature approve+swap plan.
object
Example
{ "transaction": { "to": "0x1b1fee89a381e595fe6536b99ba91f3e16e9601a", "data": "0xdc72a437…", "value": "0", "gasLimit": "1500000", "chainId": 5042 }, "lastValidBlockHeight": 21808340}Invalid parameters — error names the check that failed (INVALID_PARAMS, BAD_ADDRESS, BAD_LIMIT, BAD_HOURS, …).
Every non-2xx body.
object
Stable machine code, e.g. INVALID_PARAMS, NOT_READY, RATE_LIMIT_EXCEEDED.
For humans.
HTTP status, when included.
Example
{ "error": "INVALID_PARAMS", "message": "amount must be an integer string in the token's smallest unit"}Over the per-minute limit (RATE_LIMIT_EXCEEDED). Read X-RateLimit-Reset and back off.
Every non-2xx body.
object
Stable machine code, e.g. INVALID_PARAMS, NOT_READY, RATE_LIMIT_EXCEEDED.
For humans.
HTTP status, when included.
Example
{ "error": "INVALID_PARAMS", "message": "amount must be an integer string in the token's smallest unit"}The routing engine or an upstream did not answer (ENGINE_ERROR, ROUTE_ERROR).
Every non-2xx body.
object
Stable machine code, e.g. INVALID_PARAMS, NOT_READY, RATE_LIMIT_EXCEEDED.
For humans.
HTTP status, when included.
Example
{ "error": "INVALID_PARAMS", "message": "amount must be an integer string in the token's smallest unit"}