{"openapi":"3.0.0","info":{"title":"Swap API","version":"1.0.0","description":"DEX aggregator quote fetching, ranking, and execution scaffolding: prepare, relay, assemble, status."},"components":{"schemas":{},"parameters":{}},"paths":{"/quote":{"post":{"summary":"Fetch quote from a specific adapter","description":"Fetches a swap quote from the specified aggregator. When side=buy, the amount represents the desired output and the adapter returns the required input.","parameters":[{"schema":{"type":"string","description":"Adapter ID (e.g. cowswap, 0x)"},"required":true,"name":"protocol","in":"query"},{"schema":{"type":"string","description":"EVM chain ID"},"required":true,"name":"chainId","in":"query"},{"schema":{"type":"string","description":"Sell token address"},"required":true,"name":"from","in":"query"},{"schema":{"type":"string","description":"Buy token address"},"required":true,"name":"to","in":"query"},{"schema":{"type":"string","description":"Token amount in smallest unit (wei)"},"required":true,"name":"amount","in":"query"},{"schema":{"type":"string","enum":["buy","sell"],"default":"sell","description":"Trade direction. Defaults to sell"},"required":false,"name":"side","in":"query"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"userAddress":{"type":"string","description":"User wallet address"},"slippage":{"type":"number","description":"Slippage tolerance as percentage (e.g. 0.5)"},"fromToken":{"type":"object","properties":{"decimals":{"type":"number"}},"required":["decimals"]},"toToken":{"type":"object","properties":{"decimals":{"type":"number"}},"required":["decimals"]}},"required":["userAddress","slippage"]}}}},"responses":{"200":{"description":"Quote fetched successfully"},"400":{"description":"Invalid request parameters or unsupported operation"},"404":{"description":"Adapter not found or no quote available"},"500":{"description":"Quote fetch failed"}}}},"/rank":{"get":{"summary":"Rank quotes from all adapters","description":"Fetches quotes from all enabled adapters in parallel and returns them ranked. Sell-side ranks by highest output. Buy-side ranks by lowest input cost. Buy-side only queries adapters with native exactOutput support.","parameters":[{"schema":{"type":"string","description":"EVM chain ID"},"required":true,"name":"chainId","in":"query"},{"schema":{"type":"string","description":"Sell token address"},"required":true,"name":"from","in":"query"},{"schema":{"type":"string","description":"Buy token address"},"required":true,"name":"to","in":"query"},{"schema":{"type":"string","description":"Token amount in smallest unit (wei)"},"required":true,"name":"amount","in":"query"},{"schema":{"type":"string","description":"User wallet address"},"required":true,"name":"userAddress","in":"query"},{"schema":{"type":"string","description":"Slippage tolerance as percentage (e.g. 0.5)"},"required":true,"name":"slippage","in":"query"},{"schema":{"type":"string","enum":["buy","sell"],"default":"sell","description":"Trade direction. buy = exact output, sell = exact input"},"required":false,"name":"side","in":"query"},{"schema":{"type":"string","description":"Quote timeout in ms (1000-15000)"},"required":false,"name":"timeout","in":"query"},{"schema":{"type":"string","description":"Source token decimals"},"required":false,"name":"fromDecimals","in":"query"},{"schema":{"type":"string","description":"Destination token decimals"},"required":false,"name":"toDecimals","in":"query"},{"schema":{"type":"string","description":"Comma-separated adapter IDs to filter"},"required":false,"name":"aggregators","in":"query"}],"responses":{"200":{"description":"Ranked quotes with metadata"},"400":{"description":"Invalid request parameters"}}}},"/swap/prepare":{"post":{"summary":"Prepare an off-chain order or meta-transaction for signing","description":"Returns a discriminated payload (typed-data-intent, typed-data-meta-tx, permit2-assemble, or ethflow) describing what the client must sign or broadcast. Regular-flow quotes broadcast straight from /rank using tx.recommendedGasLimit and do not need this endpoint - calling it with such a quote returns 400.","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"quote":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"amountIn":{"type":"string"},"amountOut":{"type":"string"},"tx":{"nullable":true},"approval":{"type":"object","nullable":true,"properties":{"token":{"type":"string","pattern":"^0x[a-fA-F0-9]{40}$"},"spender":{"type":"string","pattern":"^0x[a-fA-F0-9]{40}$"},"amount":{"type":"string"},"supportsInfinite":{"type":"boolean"},"supportsGasless":{"type":"boolean"},"permit":{"type":"object","properties":{"deadline":{"type":"number"},"nonce":{"type":"number"},"domain":{"nullable":true},"types":{"nullable":true},"message":{"nullable":true}},"required":["deadline"]}},"required":["token","spender","amount","supportsInfinite","supportsGasless"]},"signature":{"type":"object","nullable":true,"properties":{"purpose":{"type":"string","enum":["intent-order","permit2-swap","meta-transaction"]},"standard":{"type":"string","enum":["EIP-712","ERC-1271"]},"domain":{"nullable":true},"types":{"nullable":true},"primaryType":{"type":"string"},"message":{"nullable":true},"validUntil":{"type":"number"}},"required":["purpose","standard","primaryType"]},"metadata":{"type":"object","properties":{"adapter":{"type":"string"},"provider":{"type":"string"},"name":{"type":"string"},"method":{"type":"string"},"logo":{"type":"string"},"isMevProtected":{"type":"boolean"}},"required":["adapter","provider","name","method","logo","isMevProtected"]},"raw":{"nullable":true}},"required":["id","name","amountIn","amountOut","approval","signature","metadata"]},"chainId":{"type":"integer","minimum":0,"exclusiveMinimum":true},"userAddress":{"type":"string","pattern":"^0x[a-fA-F0-9]{40}$"}},"required":["quote","chainId","userAddress"]}}}},"responses":{"200":{"description":"Prepared payload returned"},"400":{"description":"Invalid request body or regular-flow quote"},"500":{"description":"Vendor rejected the prepare request"},"501":{"description":"Vendor or quote kind not implemented yet"}}}},"/swap/relay":{"post":{"summary":"Submit a signed order or meta-transaction to the vendor relayer","description":"Forwards the signed payload to the appropriate vendor relayer and returns the order identifier. Supports CowSwap (intent orders) and 0x Gasless (Permit2 meta-transactions).","requestBody":{"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"adapter":{"type":"string","enum":["cowswap"]},"chainId":{"type":"integer","minimum":0,"exclusiveMinimum":true},"userAddress":{"type":"string","pattern":"^0x[a-fA-F0-9]{40}$"},"rawQuote":{},"signature":{"type":"string","pattern":"^0x[a-fA-F0-9]+$"},"isSmartContractWallet":{"type":"boolean"}},"required":["adapter","chainId","userAddress","rawQuote","signature"]},{"type":"object","properties":{"adapter":{"type":"string","enum":["0x-gasless"]},"chainId":{"type":"integer","minimum":0,"exclusiveMinimum":true},"rawQuote":{},"tradeSignature":{"type":"string","pattern":"^0x[a-fA-F0-9]+$"},"approvalSignature":{"type":"string","pattern":"^0x[a-fA-F0-9]+$"}},"required":["adapter","chainId","rawQuote","tradeSignature"]}]}}}},"responses":{"200":{"description":"Order accepted by vendor relayer"},"400":{"description":"Invalid request body"},"500":{"description":"Vendor relayer rejected the request"}}}},"/swap/assemble":{"post":{"summary":"Build the executable transaction for a signed Permit2 quote","description":"Takes a signed Permit2 message and produces the final executable transaction. Odos and OpenOcean call the vendor's assemble/build endpoint; 0x v2 appends the signature to the existing calldata locally. Returns { adapter, tx } for the client to broadcast.","requestBody":{"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"adapter":{"type":"string","enum":["odos"]},"chainId":{"type":"integer","minimum":0,"exclusiveMinimum":true},"userAddress":{"type":"string","pattern":"^0x[a-fA-F0-9]{40}$"},"rawQuote":{},"permit2Signature":{"type":"string","pattern":"^0x[a-fA-F0-9]+$"}},"required":["adapter","chainId","userAddress","rawQuote","permit2Signature"]},{"type":"object","properties":{"adapter":{"type":"string","enum":["openocean-permit2"]},"chainId":{"type":"integer","minimum":0,"exclusiveMinimum":true},"userAddress":{"type":"string","pattern":"^0x[a-fA-F0-9]{40}$"},"rawQuote":{},"permit2Signature":{"type":"string","pattern":"^0x[a-fA-F0-9]+$"}},"required":["adapter","chainId","userAddress","rawQuote","permit2Signature"]},{"type":"object","properties":{"adapter":{"type":"string","enum":["0x"]},"chainId":{"type":"integer","minimum":0,"exclusiveMinimum":true},"userAddress":{"type":"string","pattern":"^0x[a-fA-F0-9]{40}$"},"rawQuote":{},"permit2Signature":{"type":"string","pattern":"^0x[a-fA-F0-9]+$"}},"required":["adapter","chainId","userAddress","rawQuote","permit2Signature"]}]}}}},"responses":{"200":{"description":"Executable transaction returned"},"400":{"description":"Invalid request body"},"500":{"description":"Vendor rejected the assemble request"}}}},"/swap/status":{"get":{"summary":"Poll vendor status for an off-chain order or trade","description":"Returns a unified { adapter, status, vendorState } shape. Status is one of pending|filled|failed|cancelled. The full vendor response is preserved under vendorState so callers with vendor-specific UI can read what they need.","parameters":[{"schema":{"type":"string","enum":["cowswap","0x-gasless"]},"required":true,"name":"adapter","in":"query"},{"schema":{"type":"string","minLength":1},"required":true,"name":"orderId","in":"query"},{"schema":{"type":"integer","minimum":0,"exclusiveMinimum":true},"required":true,"name":"chainId","in":"query"}],"responses":{"200":{"description":"Unified status returned"},"400":{"description":"Invalid query parameters or unsupported adapter"},"500":{"description":"Vendor status call failed"}}}}}}