> For the complete documentation index, see [llms.txt](https://flowrouter.gitbook.io/flowrouter-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://flowrouter.gitbook.io/flowrouter-docs/build-with-flowrouter/swap-api.md).

# Swap API v1

Get prices and ready-to-send swap transactions from your server with the FlowRouter Swap API v1.

The Swap API v1 is the FlowRouter interface for wallets, aggregators, and backends. Your server sends a `GET` request. The API returns a price, or a firm quote with a simulated transaction for the user's wallet.

| Item                                    | Value                                                                                |
| --------------------------------------- | ------------------------------------------------------------------------------------ |
| Base URL                                | `https://api.flowrouter.xyz`                                                         |
| Chain                                   | Robinhood Chain, chain ID `4663`                                                     |
| Transaction target and approval spender | FlowRouter `0x8Ad60fAE44DD6aaFD8A98B7f25EaD026013efdF2`                              |
| Native ETH                              | `0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE`. The API also accepts the zero address. |
| Methods                                 | `GET` only. Do not send a request body.                                              |
| Amounts                                 | Base-10 integer strings in the token's smallest unit.                                |
| Order type                              | Exact input. The taker sells a fixed amount and receives the output.                 |
| Quote lifetime                          | 30 seconds or less. See `expiresAt`.                                                 |

## Access

You do not need an API key for any endpoint. Send requests from your server. The API does not support browser calls: a request with an `Origin` header gets `403 FORBIDDEN`, and there is no CORS.

Requests are rate limited. Without a key, the limits apply to your client IP address. See [Limits](/flowrouter-docs/build-with-flowrouter/swap-api-reference.md#limits).

### API keys

Get a key yourself on the [API keys page](https://flowrouter.xyz/developers/api-keys/). You do not need an email address or a password.

1. Connect your wallet. The wallet owns its keys.
2. Sign the sign-in message. The message is for `flowrouter.xyz`. It does not send a transaction and it costs no gas. Smart-contract wallets are not supported yet.
3. Select **Create key**. Copy the key at once: the page shows it one time only. FlowRouter stores only a hash of the key.

A wallet can have 3 active keys. A key is valid for 365 days. To replace a key, create a new key, move your server to it, and then revoke the old key. A revoked key stops at once. See [Limits](/flowrouter-docs/build-with-flowrouter/swap-api-reference.md#limits) for the limits of each key.

Self-serve keys are for attribution only. Your wallet gets one FlowRouter referral code, and your swaps carry it. These keys have no integrator fee and no surplus share. [Contact us](/flowrouter-docs/reference/official-links.md) for higher limits or for a fee or surplus agreement. FlowRouter registers those codes on chain.

Send the key in the `X-API-Key` header of every request. Send the header one time only. Do not put the key in the URL, and keep it on your server.

If you send a key, it must be valid. A wrong, expired, or revoked key gets `401 UNAUTHORIZED`. The API does not fall back to access without a key.

A key is bound to one FlowRouter referral code on chain. The code sets the fee or surplus share of your swaps. You do not send the code in requests.

## Endpoints

| Endpoint              | Purpose                                                                     |
| --------------------- | --------------------------------------------------------------------------- |
| `GET /v1/4663/price`  | Indicative price. No transaction. Use it before the user connects a wallet. |
| `GET /v1/4663/quote`  | Firm quote for one taker, with a simulated transaction.                     |
| `GET /v1/4663/tokens` | Tokens that FlowRouter routes now.                                          |
| `GET /v1/health`      | Service readiness.                                                          |

Another path gets `404 NOT_FOUND`.

## Request parameters

`/price` and `/quote` use these query parameters:

| Parameter     | Required                    | Rules                                                                                                    |
| ------------- | --------------------------- | -------------------------------------------------------------------------------------------------------- |
| `sellToken`   | Yes                         | Token address in any letter case, or the native ETH address.                                             |
| `buyToken`    | Yes                         | Token address, or the native ETH address. It must differ from `sellToken`.                               |
| `sellAmount`  | Yes                         | Integer string, 1 to 78 digits, no leading zero. Smallest unit of `sellToken`.                           |
| `slippageBps` | No                          | Integer from `1` to `1000`, no leading zero. Default `50` (0.5%).                                        |
| `taker`       | `/quote`: yes. `/price`: no | The address that sends the transaction and receives the output. `/price` accepts it but does not use it. |
| `recipient`   | No, `/quote` only           | Must equal `taker`. A different recipient is not supported in v1.                                        |

The API refuses these requests with `400 INVALID_REQUEST`:

* An unknown parameter.
* A parameter that is empty or that occurs more than one time.
* A query string longer than 1,024 bytes.
* A `taker` that is the zero address or the native ETH address.

A token that is not in the current token list gets `400 TOKEN_NOT_SUPPORTED`. `/tokens` and `/health` take no parameters.

## Price and quote responses

`/price` and `/quote` both return these fields:

| Field                                      | Meaning                                                                                                                       |
| ------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------- |
| `chainId`                                  | Always `4663`.                                                                                                                |
| `blockNumber`                              | The block whose state priced the route.                                                                                       |
| `sellToken`, `buyToken`                    | Your tokens, in the spelling that you sent.                                                                                   |
| `sellAmount`                               | Your `sellAmount`. In `/quote`, it is also the exact input amount in the calldata.                                            |
| `buyAmount`                                | The most that the taker receives. Surplus above this amount does not go to the taker. Net of any fee.                         |
| `minBuyAmount`                             | The on-chain minimum. The transaction reverts if the taker would receive less. It follows from `slippageBps`. Net of any fee. |
| `allowanceTarget`                          | The address to approve for `sellToken`: the FlowRouter address. `null` when you sell native ETH.                              |
| `fees.integratorFee`, `fees.flowRouterFee` | Fee parts. Both are `null` when your code has no fee.                                                                         |
| `route.fills`                              | The route steps. See below.                                                                                                   |
| `gas`                                      | The expected gas use of the swap.                                                                                             |
| `gasPrice`                                 | The gas price used for this quote, in wei per gas. It is an estimate.                                                         |
| `totalNetworkFee`                          | `gas × gasPrice`, in wei. The expected network cost.                                                                          |
| `liquidityAvailable`                       | Always `true` in a `200` response. Without a route, you get an error.                                                         |
| `requestId`                                | The ID of this request. It is also in the `X-Request-Id` header. Include it when you report a problem.                        |

Each entry of `route.fills` has:

| Field           | Meaning                                                                                                                        |
| --------------- | ------------------------------------------------------------------------------------------------------------------------------ |
| `source`        | The venue ID, for example `uniswap-v4` or `wrapped-native`.                                                                    |
| `from`, `to`    | The step's input and output token, in lowercase. `native` means ETH.                                                           |
| `proportionBps` | The part of all `from` tokens on the route that this step takes, in basis points. Steps from the same token add up to `10000`. |

Venue IDs are display data. Do not use them to build a transaction.

### Price only

`/price` also returns `indicative: true`. A price is not firm. It does not ask market makers for firm quotes, so a later `/quote` can differ. Equal price requests (same tokens, amount, and slippage) can get the same price for a short time.

A price or quote never fills only part of `sellAmount`. If the route cannot take the full amount, you get `422 INSUFFICIENT_LIQUIDITY`.

### Quote only

| Field                         | Meaning                                                                                                                                      |
| ----------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| `quoteId`                     | The ID of this quote.                                                                                                                        |
| `transaction.to`              | The FlowRouter address. Check this value.                                                                                                    |
| `transaction.data`            | Calldata for FlowRouter `swap((address,uint256,address,uint256,uint256,address),bytes,address,uint32)`, selector `0xd46cadbc`.               |
| `transaction.value`           | Wei to send. It equals `sellAmount` when you sell native ETH; otherwise `"0"`.                                                               |
| `transaction.gas`             | The gas limit. Send it unchanged. See [Gas](#gas).                                                                                           |
| `transaction.gasPrice`        | The fee cap: `2 × base fee + priority fee` at the simulated block. Use it as `maxFeePerGas`.                                                 |
| `expiresAt`                   | Epoch milliseconds. Send the transaction before this time.                                                                                   |
| `quoteValidUntil`             | The same value as `expiresAt`.                                                                                                               |
| `issues.allowance`            | `null`, or `{ "actual", "spender" }` when the taker's FlowRouter allowance is less than `sellAmount`.                                        |
| `issues.balance`              | `null`, or `{ "token", "actual", "expected" }` when the taker holds less than `sellAmount`. For native ETH, this check does not include gas. |
| `issues.simulationIncomplete` | Always `false` in v1.                                                                                                                        |
| `issues.invalidSourcesPassed` | Always `[]` in v1.                                                                                                                           |
| `simulation.status`           | Always `"success"`. A failed simulation gives an error, not a quote.                                                                         |
| `simulation.blockNumber`      | The block of the simulation.                                                                                                                 |
| `simulation.funding`          | Always `"canonical_overrides"`.                                                                                                              |

The simulation gives the taker the sell amount and the allowance as simulated state. Thus you get a quote even when the taker has no funds or approval yet. Read `issues` to find what the taker lacks.

The calldata's `tokenInfo` tuple is `(inputToken, inputAmount, outputToken, outputQuote, outputMin, outputReceiver)`:

| Calldata field                 | API field                                                                                                     |
| ------------------------------ | ------------------------------------------------------------------------------------------------------------- |
| `inputToken`                   | `sellToken`; the zero address for native ETH.                                                                 |
| `inputAmount`                  | `sellAmount`, exactly.                                                                                        |
| `outputToken`                  | `buyToken`; the zero address for native ETH.                                                                  |
| `outputQuote`                  | `buyAmount`.                                                                                                  |
| `outputMin`                    | `minBuyAmount`.                                                                                               |
| `outputReceiver`               | `taker`.                                                                                                      |
| `referralCode` (last argument) | Without a key, FlowRouter's default code `4663`, which has no fee. With an API key, your key's referral code. |

On FlowRouter, `outputReceiver` set to the zero address does not mean "the sender". The API never builds such a transaction. If you decode calldata, treat a zero receiver as invalid.

## Expiry

`expiresAt` is the earliest of these times:

* 30 seconds after the route was priced.
* 30 seconds after the simulation.
* The earliest deadline of a market maker on the route.

Do not send the transaction after `expiresAt`. Get a new quote. A slow signing flow, for example a hardware wallet or a multisig, needs a new quote when the old one expires.

## Gas

| Field                  | Meaning                         | Use                                                    |
| ---------------------- | ------------------------------- | ------------------------------------------------------ |
| `gas`                  | Expected gas use.               | Compare quotes: output minus `gas × your gas price`.   |
| `gasPrice`             | The quote's gas price estimate. | Compare quotes when you have no gas price of your own. |
| `totalNetworkFee`      | `gas × gasPrice`.               | Expected network cost. The receipt can differ.         |
| `transaction.gas`      | Gas limit.                      | Send it unchanged.                                     |
| `transaction.gasPrice` | Fee cap.                        | `maxFeePerGas` of an EIP-1559 transaction.             |

`transaction.gas` follows these rules:

* For most routes, it is `eth_estimateGas` of the taker's exact transaction × 1.3, plus 50,000.
* Some pools give a different result when less gas is available. For a route through such a pool, `transaction.gas` is the chain's maximum transaction gas, currently `32000000`. Do not lower it, and do not replace it with your own estimate.

The chain charges only the gas that the transaction uses. But the wallet must hold `transaction.gas × transaction.gasPrice + transaction.value` in ETH before it can send the transaction. The API simulates the transaction at the gas limit that it returns.

## Tokens

`GET /v1/4663/tokens` returns:

```json
{
  "chainId": 4663,
  "nativeToken": "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",
  "tokens": [
    {
      "address": "0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168",
      "symbol": "USDG",
      "name": "Global Dollar",
      "decimals": 6,
      "logoURI": null,
      "provenance": "curated"
    }
  ]
}
```

The example shows one entry. The name is illustrative.

* `tokens` contains ERC-20 tokens, sorted by address. Native ETH is not in the list; it is `nativeToken`.
* `address` is in EIP-55 checksum form. `logoURI` is currently always `null`.
* `provenance` is `curated` or `automatic-admission`. Automatic admission is not an endorsement.
* The list changes over time. Read it again from time to time, for example every 10 minutes.

## Health

`GET /v1/health` returns HTTP `200` with:

```json
{ "chainId": 4663, "ready": true, "router": "0x8Ad60fAE44DD6aaFD8A98B7f25EaD026013efdF2" }
```

`ready: false` means that prices and quotes are not available now.

## Send the swap

1. Get a quote with `taker` set to the user's address.
2. Check that `transaction.to` is the FlowRouter address.
3. If `sellToken` is an ERC-20 token and `issues.allowance` is not `null`, approve `allowanceTarget` for at least `sellAmount`. If the quote expires while the approval confirms, get a new quote.
4. If `issues.balance` is not `null`, stop. The taker does not hold the sell amount.
5. Send `to`, `data`, `value`, and `gas` from the `taker` address before `expiresAt`. Use `transaction.gasPrice` as `maxFeePerGas`.
6. Do not change `data` or `value`. Do not lower `gas`.
7. Read the receipt. FlowRouter's `Swap` event shows the real output. See [Network and contracts](/flowrouter-docs/reference/networks-and-contracts.md#swap-interface).

## Example

Request a firm quote from your server:

```sh
curl -sS "https://api.flowrouter.xyz/v1/4663/quote?sellToken=0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE&buyToken=0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168&sellAmount=1000000000000000&slippageBps=50&taker=<USER_ADDRESS>"
```

This example sells 0.001 ETH for USDG. Replace `<USER_ADDRESS>` with the taker's address. A route at that amount is not guaranteed. If you have an API key, add `-H "X-API-Key: $FLOWROUTER_API_KEY"` and keep the key in an environment variable.

See [Swap API errors and limits](/flowrouter-docs/build-with-flowrouter/swap-api-reference.md) for error codes and rate limits.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://flowrouter.gitbook.io/flowrouter-docs/build-with-flowrouter/swap-api.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
