For the complete documentation index, see llms.txt. This page is also available as Markdown.

Hosted Fynd API (Beta)

Get routing quotes in minutes from Propeller Heads' hosted Fynd API — no local setup required.

Fynd is an open-source DEX aggregator: you send it a token pair and amount, it finds the best on-chain route across the liquidity venues it tracks, and returns the expected output plus a ready-to-submit transaction. You can run Fynd on your own hardware (see Self-host quickstart) — or you can use our hosted API and skip the setup entirely. This page covers the hosted path: get an API key, send a request, get a route.

The hosted API runs the latest released Fynd with routing settings tuned per chain by the Fynd team, so you always track the newest routing improvements without managing releases or worker pools yourself.

Prefer a UI? A hosted web frontend is coming soon. Today the API is the integration surface.

What you get

  • One endpoint, all chains. https://fynd-api.propellerheads.xyz routes /v1/{chain}/… to a per-chain Fynd backend. No per-chain infrastructure on your side.

  • Latest Fynd version. The hosted backends track the newest Fynd release; you don't pin or upgrade anything. (During beta, the surface area may change — see the FAQ for version and deprecation notes.)

  • Optimized routing. Worker-pool and algorithm configuration are tuned per chain by the Fynd team. Hosted backends run the full default protocol set — see the list of supported protocols.

  • Same quote API as self-hosted. The per-chain request/response bodies are identical to running fynd serve yourself — see API reference. The hosted gateway adds a /{chain} path segment and API-key auth; a self-hosted instance serves one chain at /v1/… with no auth.

Get an API key

  1. Open @fynd_portal_bot on Telegram.

  2. Run /start and follow the prompts. You'll receive a Fynd API key (also valid for the Tycho liquidity indexer that feeds Fynd).

  3. Save the key immediately. The bot won't show it again, and you get 3 self-service revocations (rotations of your key) before you need to contact support in our Telegram group.

export FYND_API_KEY=your-api-key

The key is sent as the raw Authorization header value on every request — no Bearer prefix:

Quickstart

1. Health check

The -i flag also prints the response headers, including X-User-Plan: fynd-basic (your current plan) and Retry-After on 429s.

Health fields:

Field
Meaning

healthy

Overall solver readiness.

last_update_ms

Milliseconds since the last market-state update from Tycho. 0 means no update received yet (the stream is stalled — quotes will return no_route_found); non-zero and small is healthy.

num_solver_pools

Number of parallel algorithm worker pools running. Not liquidity pools — internal solver workers.

derived_data_ready

Whether derived graph data (token pairs, routes) is built and ready to serve.

gas_price_age_ms

Age of the cached gas price estimate, in milliseconds.

2. Instance info

  • chain_id — the EVM chain ID this backend serves (e.g. 1 for Ethereum). Corresponds to the chain path segment in the request URL.

  • router_address — the on-chain contract that executes swaps. Submit your encoded swap transaction to this address (it's already set as transaction.to in an encoded quote — you don't set it yourself). It is chain-specific: each chain returns its own router address.

  • permit2_address — the Permit2 contract address. Used for permit-based token approvals (see Approvals below).

  • version — the Fynd binary version serving this chain (the example value is illustrative). Hosted backends are updated on each production release, so the running version may lag the newest published Fynd release.

3. Request a quote

Sell 1 WETH for USDC on Ethereum. Amounts are in the token's smallest unit (wei for WETH, micro-units for USDC):

Sell orders only. Fynd currently supports side: "sell" (exact input). Buy orders (exact output) are not yet supported.

sender — the address that will submit the swap transaction. The quote (and any encoded calldata) is bound to this sender. The 0x0000…0001 above is a dummy; replace it with your wallet address for any quote you intend to execute.

Quote options (options field — all optional):

Option
Default
Meaning

timeout_ms

server default

Max time the solver spends finding a route. On timeout, the server returns the best route found so far (or a timeout status if none).

min_responses

server default

Minimum number of solver pools that must respond before the server returns. 1 returns as soon as one pool has a route (fastest). Higher values wait for more pools to compete, improving price at the cost of latency.

encoding_options

null

If set, the response includes a ready-to-submit transaction object. See step 4.

max_gas

null

Cap on gas units the route may use. Routes exceeding it are rejected.

The response contains the route, the expected amount_out, gas estimate, and the solve_time_ms the server spent finding the route:

Response fields:

Field
Meaning

solve_time_ms

Server-side time spent finding the route (excludes network/proxy overhead). Top-level, per response.

total_gas_estimate

Sum of gas_estimate across all orders in the response. Top-level, per response.

amount_in

The input amount for this order, in token_in's smallest unit (echoes the requested amount).

amount_out

Expected output, in the token_out's smallest unit.

amount_out_net_gas

amount_out minus the gas cost of executing the route, denominated in token_out. Use this to compare routes.

gas_estimate

Gas units the swap will consume.

gas_price

Gas price (wei) used for the amount_out_net_gas calculation.

price_impact_bps

Price impact of the swap in basis points (100 bps = 1%).

route.swaps[].component_id

Internal ID for the liquidity venue used (pool/curve/vault). Not directly an on-chain address.

route.swaps[].protocol

Protocol name. The vm: prefix denotes a virtual-machine venue. See supported protocols.

route.swaps[].split

Fraction of the input amount routed through this swap. "0" means "the remainder of the input" (the last leg of a split group), not 0%. A single-swap route shows split: "0".

block

The block the quote is valid against. Submit the encoded transaction promptly — see Quote validity.

transaction

null unless encoding_options is set. See step 4.

order_id

Correlation ID for this quote. Not queryable after the fact.

One order per request is the supported path today. The orders array shape exists for future batch quoting; for now, send exactly one order.

4. Encode and approve

To get a ready-to-submit transaction, pass encoding_options with your slippage tolerance (a fraction, as a string, e.g. "0.005" = 0.5%):

The response now includes a populated transaction and a fee_breakdown:

  • transaction.to is the chain's router_address (already set — submit as-is).

  • transaction.data is the calldata for the swap.

  • transaction.gas may or may not be populated — if absent, estimate gas separately with eth_estimateGas before submitting.

  • fee_breakdown.router_fee — the fee Fynd charges on the swap, in token_out units. The default Fynd fee is 0.1 bps (0.001%) of swap output; quotes are free. See Fynd Fees for volume discounts and the full fee arithmetic.

  • fee_breakdown.client_fee — integrator fee (0 unless you set client_fee_params in encoding_options; see Charge Fees on your Swaps).

  • fee_breakdown.max_slippage — the slippage allowance in token_out units, applied to the post-fee amount. min_amount_received = amount_out − router_fee − client_fee − max_slippage. Verify the settled output is ≥ min_amount_received after the transaction confirms.

Approvals

Before submitting the swap transaction, the token_in must be spendable by the router. The path depends on the transfer_type (default "transfer_from"):

  1. transfer_from (default) — standard ERC-20 approval. Call approve(router_address, amount) on the token_in contract, granting the Fynd router an allowance ≥ amount_in. The router pulls the exact amount_in at execution.

  2. transfer_from_permit2 — gasless Permit2 signature. Sign a PermitSingle off-chain and pass it via encoding_options.permit + permit2_signature. No on-chain approve() to the router is needed, but the token must first be approved to the Permit2 contract (permit2_address), not the router. See Encoding Options for the full Permit2 flow.

Native-token sells skip approval entirely. If token_in is the zero address (0x0000000000000000000000000000000000000000), the router wraps native ETH/BNB/POL for you — no approval needed.

Quick approval with cast (Foundry) — for the default transfer_from path:

With approval in place, sign and broadcast transaction (the {to, value, data} object) from your sender wallet. If transaction.gas is absent, estimate with eth_estimateGas first.

Quote validity

The quote is valid against the block in the response. Encoded calldata includes a deadline, but market state moves every block — re-quote within ~1 block (12s on Ethereum, faster on L2s) before submitting. For execution-critical flows, quote → sign → submit in a single sequence; don't cache quotes for later.

5. Sign and execute with a Fynd client

For the full approve → sign → submit → settle flow, the Fynd clients (@kayibal/fynd-client for TypeScript, fynd-client for Rust) support the hosted API directly — pass your API key and chain to the client builder and the rest is handled.

The typed clients expose camelCase equivalents of the REST fields (amountOut, solveTimeMs, amountOutNetGas, etc.). The REST reference uses snake_case (amount_out, solve_time_ms).

Supported chains

Each chain is served from its own Fynd backend behind the shared gateway. Send the chain name in the URL path (/v1/{chain}/…). With the typed clients, set the chain option (TypeScript) or .with_chain("…") (Rust).

Chain

chain path segment

Chain ID

Native token

Ethereum

ethereum

1

ETH

Base

base

8453

ETH

Arbitrum

arbitrum

42161

ETH

BNB Smart Chain

bsc

56

BNB

Polygon

polygon

137

POL

Unichain

unichain

130

ETH

A request to /v1/{chain}/… for a chain that isn't configured returns 404 with {"error": "unknown_chain", ...}.

Native token swaps

Use the zero address (0x0000000000000000000000000000000000000000) as token_in or token_out to swap the chain's native gas token (ETH on Ethereum/Base/Arbitrum/Unichain, BNB on BSC, POL on Polygon). Native-token token_in skips the approval step — the router wraps native gas for you.

API key limits by tier

Your API key belongs to a plan that sets your rate limit. Limits are enforced per key by a token-bucket limiter at the gateway.

Plan
Requests / second
Burst
How to get

fynd-basic (default)

10

2× (20)

Self-service via @fynd_portal_bot

basic (tycho)

10

2× (20)

scale

25

2× (50)

Burst is the bucket capacity = rps × burst_multiplier. A fynd-basic key can briefly sustain 20 requests in one second before being throttled back to the steady-state 10 rps. All requests count against the bucket/health, /info, and /quote alike. The bucket is per key, shared across all chains.

When you exceed the limit you get 429 Too Many Requests with a Retry-After header (seconds). The hosted API is REST-only today (no WebSocket); for higher throughput, run your own stack (see below) or talk to us about a dedicated instance.

Pricing: The hosted API is free to use during beta — no platform fee on top of Fynd's standard 0.1 bps router fee on executed swaps (see Fynd Fees). Quotes are always free. scale is allocated case-by-case — reach out to discuss volume and needs.

Checking your plan

The gateway returns your plan in the X-User-Plan response header on every authenticated request (use curl -i to see it). If you're unsure which plan your key is on, message @fynd_portal_bot or ask in our Telegram group.

Errors

HTTP status
Meaning
Body format

400

Malformed request body, bad token address, or invalid slippage type

JSON: {"error": "...", "code": "BAD_REQUEST"}

401

Missing or invalid API key, or plan not recognized

Plain text: Unauthorized or Missing authorization token

403

Your plan doesn't allow this service

Plain text: Forbidden

404

Unknown chain path segment

JSON: {"error": "unknown_chain", ...}

429

Rate limit exceeded

Plain text: Too Many Requests, plus Retry-After: <seconds> header

5xx

Backend or gateway failure

varies — check health and retry with backoff

A 200 with orders[0].status: "no_route_found" is not an HTTP error — it means the solver ran but couldn't find a profitable route for the pair at the requested size. Check /v1/{chain}/health (last_update_ms: 0 means the Tycho stream isn't delivering live state yet), try a different token pair or size, or confirm the tokens have Tycho-indexed liquidity on that chain.

Scaling beyond the hosted tiers

The hosted API is a shared, beta-rate-limited service designed for getting started and for moderate-volume integrations. If you need:

  • Higher or unlimited rate limits — run Fynd on your own hardware. The self-host quickstart has you serving in minutes, and there's no rate limiter in front of your own instance.

  • Custom algorithms, custom protocol sets, or RFQ integration — self-host and pass --protocols / your algorithm config. See Server Configuration and Custom Algorithm.

  • A dedicated hosted instance with guaranteed capacity and SLA — reach out to our business team. Message @tanay_j on Telegram, or email us at Propeller Heads.

What the hosted API buys you (vs. self-hosting): no infrastructure to run, no Tycho indexer endpoint to source, no release tracking, and per-chain routing tuned by the Fynd team. Self-hosting gives you ~1,000 RPS on commodity hardware (see Performance) and full control — pick the tradeoff that fits your scale.

FAQ

Is the hosted API the same software as self-hosted Fynd? Yes. Identical binary, same quote API. The hosted gateway adds a /{chain} path segment, API-key auth, and rate limiting — none of which exist in the self-hosted binary. The per-chain request/response bodies are identical.

How do I know which Fynd version is running? The unauthenticated endpoint https://fynd-api.propellerheads.xyz/api-docs/openapi.json exposes the version under info.version. We update the hosted backends shortly after each release. During beta the surface area may change; we post breaking changes in our Telegram group ahead of rollout.

Can I use one key for all chains? Yes. A single API key works against every /v1/{chain}/… path. The rate-limit bucket is shared across chains.

Why did my quote return no_route_found? The solver found no profitable route for the pair at the requested size on that chain. Common causes: thin Tycho-indexed liquidity for the pair, an amount too large or too small, or the chain's backend is still warming up. Check /v1/{chain}/healthlast_update_ms: 0 indicates the Tycho stream isn't delivering live state yet.

Can I bring my own RPC and Tycho endpoint with the hosted API? No — the hosted API uses Propeller Heads' Tycho endpoints. To use your own, self-host.

Next steps

Last updated