> ## Documentation Index
> Fetch the complete documentation index at: https://docs.o1.exchange/llms.txt
> Use this file to discover all available pages before exploring further.

# POST /quote

> Price a swap and receive a routePlan you can hand back to /submit. Read-only, no user address required.

Use `POST /quote` to fetch a price. The response includes a stable `quoteId` you echo on `/submit` when the user is ready to swap.

<Info>
  * **Authentication:** `x-api-key` header required.
  * **Rate limit:** 120 req/min per key (default). See [Rate limits](/api/dex-aggregator/reference/rate-limits).
</Info>

## Request

<Tabs>
  <Tab title="Endpoint">
    ```http theme={null} theme={null}
    POST {API_URL}/quote
    Content-Type: application/json
    x-api-key: <YOUR_API_KEY>
    ```
  </Tab>

  <Tab title="Body">
    ```json theme={null} theme={null}
    {
      "chainId": 8453,
      "tokenIn": "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913",
      "tokenOut": "0x4200000000000000000000000000000000000006",
      "amountIn": "1000000000",
      "slippageBps": 100,
      "feeBps": 30,
      "maxHops": 3,
      "splitEnabled": true
    }
    ```
  </Tab>
</Tabs>

### Body parameters

| Field                 | Type             | Required | Description                                                                                                   |
| --------------------- | ---------------- | -------- | ------------------------------------------------------------------------------------------------------------- |
| `chainId`             | integer          | yes      | EVM chain ID. Currently only `8453` (Base) is supported.                                                      |
| `tokenIn`             | address          | yes      | Token to sell. Use `0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE` or the zero address for native ETH.           |
| `tokenOut`            | address          | yes      | Token to buy. Same native sentinel rules apply.                                                               |
| `amountIn`            | string           | yes      | Amount in base units (wei) as a decimal string. Must be `> 0`.                                                |
| `slippageBps`         | integer          | yes      | Slippage tolerance in basis points (`100` = 1%). Range `0..10000`.                                            |
| `feeBps`              | integer          | no       | Integrator fee in basis points, taken out of `expectedAmountOut`. Range `0..10000`.                           |
| `maxHops`             | integer          | no       | Maximum hops per route. Default `3`.                                                                          |
| `splitEnabled`        | boolean          | no       | Allow the optimizer to split the trade across multiple routes when it improves output. Default `true`.        |
| `enforcePoolDisjoint` | boolean          | no       | When splitting, require routes to use disjoint pool sets. Off by default.                                     |
| `allowedDexes`        | array of `DexId` | no       | Restrict routing to a subset of venues. See [Supported DEXes](/api/dex-aggregator/reference/supported-dexes). |
| `taker`               | address          | no       | Optional taker hint. Doesn't affect pricing for most callers.                                                 |
| `timeBudgetMs`        | integer          | no       | Per-request override of the optimizer wall-clock budget. Range `50..10000`.                                   |

## Response

<Tabs>
  <Tab title="200 OK">
    ```json theme={null} theme={null}
    {
      "quoteId": "a1b2c3d4e5f6...",
      "expiresAt": 1712180000000,
      "routePlan": {
        "chainId": 8453,
        "tokenIn": "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913",
        "tokenOut": "0x4200000000000000000000000000000000000006",
        "amountIn": "1000000000",
        "expectedAmountOut": "484446072048780734",
        "minAmountOut": "479601611328292926",
        "slippageBps": 100,
        "feeBps": 30,
        "blockNumber": 44266656,
        "gasEstimate": { "gasUnits": 300000 },
        "feeBreakdown": {
          "protocolFeeAmount": "1457804507741243911",
          "integratorFeeAmount": "0"
        },
        "routes": [
          {
            "amountIn": "1000000000",
            "legs": [
              {
                "dex": "UNIV3",
                "tokenIn": "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913",
                "tokenOut": "0x4200000000000000000000000000000000000006",
                "amountIn": "1000000000",
                "minOut": "0",
                "poolId": "0xd0b5...f224",
                "data": { "kind": "v3_direct", "pool": "0xd0b5...f224" }
              }
            ]
          }
        ],
        "metadata": {
          "candidatePaths": 16,
          "selectedPaths": 1,
          "connectorsConsidered": [
            "0xcbb7c0000ab88b473b1f5afd9ef808440eed33bf",
            "0x9401e5e6564db35c0f86573a9828df69fc778631"
          ]
        }
      }
    }
    ```
  </Tab>

  <Tab title="400 Bad Request">
    ```json theme={null} theme={null}
    { "error": "amountIn must be > 0" }
    ```

    Other common 400 messages: `chainId required`, `slippageBps out of range`, `no routes for pair`.
  </Tab>

  <Tab title="401 Unauthorized">
    ```json theme={null} theme={null}
    { "error": "unauthorized" }
    ```
  </Tab>

  <Tab title="429 Rate Limited">
    ```json theme={null} theme={null}
    {
      "error": "rate limit exceeded",
      "limit": 120,
      "windowSec": 60
    }
    ```
  </Tab>
</Tabs>

### Response fields

| Field       | Type    | Description                                                                                                                                             |
| ----------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `quoteId`   | string  | Stable identifier for this quote. Hand to `/submit`.                                                                                                    |
| `expiresAt` | integer | Unix milliseconds at which the cached quote drops.                                                                                                      |
| `routePlan` | object  | Full plan including pricing, gas estimate, and per-leg detail. See the [RoutePlan reference](/api/dex-aggregator/reference/route-plan) for every field. |

The fields you'll most commonly surface to users:

* `routePlan.expectedAmountOut` — the price you display
* `routePlan.minAmountOut` — the worst case after slippage
* `routePlan.routes[].legs[].dex` — list of venues used (e.g. `UNIV3 → AERODROME_CL`)
* `routePlan.feeBps` — protocol + integrator fee in bps
* `routePlan.gasEstimate.gasUnits` — estimated gas for the swap

## Caching and freshness

Quotes are cached server-side under their `quoteId` for roughly 10 seconds. After `expiresAt`, calling `/submit` returns `404 quote not found or expired`.

For UIs that show a live price, the recommended pattern is to re-fetch the quote every 5 to 8 seconds while the swap modal is open. See [Quote freshness](/api/dex-aggregator/guides/quote-freshness).

## Examples

<CodeGroup>
  ```ts TypeScript theme={null} theme={null}
  const quote = await fetch(`${API_URL}/quote`, {
    method: "POST",
    headers: {
      "x-api-key": process.env.O1_API_KEY!,
      "content-type": "application/json",
    },
    body: JSON.stringify({
      chainId: 8453,
      tokenIn: "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913",
      tokenOut: "0x4200000000000000000000000000000000000006",
      amountIn: "1000000000",
      slippageBps: 100,
    }),
  }).then((r) => r.json());
  ```

  ```bash cURL theme={null} theme={null}
  curl -X POST https://quiet-bloodhound-531.convex.site/quote \
    -H "x-api-key: $O1_API_KEY" \
    -H "content-type: application/json" \
    -d '{
      "chainId": 8453,
      "tokenIn": "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913",
      "tokenOut": "0x4200000000000000000000000000000000000006",
      "amountIn": "1000000000",
      "slippageBps": 100
    }'
  ```
</CodeGroup>

<Tip>
  Pair this with [`POST /submit`](/api/dex-aggregator/endpoints/submit) for the standard two-step flow, or use [`POST /execute`](/api/dex-aggregator/endpoints/execute) when you don't need a price preview step.
</Tip>


## OpenAPI

````yaml openapi.yaml POST /quote
openapi: 3.1.0
info:
  title: o1 DEX Aggregator API
  version: 0.1.0
  description: |
    Quote + execution API for the o1 DEX aggregator on Base.

    Flow:
      1. POST /quote   → returns quoteId + routePlan
      2. POST /submit  → returns the calldata payload to broadcast
      3. Caller signs and broadcasts O1Router.swapExactIn().

    /execute is a one-shot convenience that combines /quote and /submit.

    All non-`/health` endpoints require the `x-api-key` header. Rate limit
    defaults to 120 requests per minute per client IP.
servers:
  - url: https://quiet-bloodhound-531.convex.site
    description: Production
security:
  - ApiKeyAuth: []
tags:
  - name: meta
    description: Liveness and version probes.
  - name: quote
    description: Pricing endpoints that produce a routePlan.
  - name: submit
    description: Calldata builders that turn a quote into a broadcast-ready transaction.
  - name: aggregator-comparison
    description: >-
      Optional endpoints that fan out to upstream aggregators (0x / 1inch /
      KyberSwap / Relay / Odos / CoW). Mounted only when at least one upstream
      adapter is configured server-side.
paths:
  /quote:
    post:
      tags:
        - quote
      summary: Price a swap and return a routePlan
      operationId: postQuote
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/QuoteRequest'
      responses:
        '200':
          description: Quote produced
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/QuoteResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '429':
          $ref: '#/components/responses/RateLimited'
components:
  schemas:
    QuoteRequest:
      type: object
      required:
        - chainId
        - tokenIn
        - tokenOut
        - amountIn
        - slippageBps
      properties:
        chainId:
          type: integer
          minimum: 1
          description: EVM chain id. 8453 for Base (current Phase-1 target).
        tokenIn:
          $ref: '#/components/schemas/Address'
        tokenOut:
          $ref: '#/components/schemas/Address'
        amountIn:
          $ref: '#/components/schemas/AmountString'
        slippageBps:
          type: integer
          minimum: 0
          maximum: 10000
        maxHops:
          type: integer
          minimum: 1
        splitEnabled:
          type: boolean
        enforcePoolDisjoint:
          type: boolean
        allowedDexes:
          type: array
          minItems: 1
          items:
            $ref: '#/components/schemas/DexId'
        feeBps:
          type: integer
          minimum: 0
          maximum: 10000
          description: Integrator fee in bps, charged out of the output amount.
        taker:
          $ref: '#/components/schemas/Address'
        timeBudgetMs:
          type: integer
          minimum: 50
          maximum: 10000
          description: |
            Per-request override of the optimizer's wall-clock budget.
            Omit to inherit the engine default.
      additionalProperties: false
    QuoteResponse:
      type: object
      required:
        - quoteId
        - routePlan
        - expiresAt
      properties:
        quoteId:
          type: string
          description: |
            SHA-256 (or HMAC-SHA256 if the server has `O1_QUOTE_SIGNING_KEY`
            set) of the quote payload. Echo this on /submit.
        routePlan:
          $ref: '#/components/schemas/RoutePlan'
        expiresAt:
          type: integer
          format: int64
          description: Unix epoch milliseconds at which the cached quote drops.
    Address:
      type: string
      pattern: ^0x[a-fA-F0-9]{40}$
      description: |
        20-byte hex address. The sentinel
        `0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE` (or the zero
        address) signals the chain's native asset (ETH on Base) and is
        recognized in `tokenIn`/`tokenOut`.
    AmountString:
      type: string
      pattern: ^[0-9]+$
      description: Non-negative integer encoded as a decimal string (wei).
    DexId:
      type: string
      enum:
        - UNIV2
        - UNIV3
        - UNIV4
        - AERODROME_V2LIKE
        - AERODROME_CL
        - PANCAKE_V2
        - PANCAKE_V3
        - PANCAKE_INFINITY_CL
        - HYDREX
        - QUICKSWAP_V4
        - ALIEN_BASE_V3
        - CURVE
        - PROPSWAP
        - TESSERA
        - ELFOMOFI
        - LUNARBASE
        - FELTIR
        - DODO_V2
        - WOOFI
        - GYROSCOPE_ECLP
        - MAVERICK_V2
    RoutePlan:
      type: object
      required:
        - chainId
        - tokenIn
        - tokenOut
        - amountIn
        - expectedAmountOut
        - minAmountOut
        - slippageBps
        - routes
        - blockNumber
      properties:
        chainId:
          type: integer
        tokenIn:
          $ref: '#/components/schemas/Address'
        tokenOut:
          $ref: '#/components/schemas/Address'
        amountIn:
          $ref: '#/components/schemas/AmountString'
        expectedAmountOut:
          $ref: '#/components/schemas/AmountString'
        minAmountOut:
          $ref: '#/components/schemas/AmountString'
        feeBps:
          type: integer
          minimum: 0
          maximum: 10000
        slippageBps:
          type: integer
          minimum: 0
          maximum: 10000
        routes:
          type: array
          items:
            $ref: '#/components/schemas/SplitRoute'
        blockNumber:
          type: integer
          minimum: 0
        gasEstimate:
          $ref: '#/components/schemas/GasEstimate'
        feeBreakdown:
          $ref: '#/components/schemas/FeeBreakdown'
        metadata:
          $ref: '#/components/schemas/RouteMetadata'
        nativeIn:
          type: boolean
          description: |
            Set when the original request used the ETH sentinel for tokenIn.
            The submit handler must send `msg.value = amountIn` and set
            `useNativeIn: true` so the router wraps to WETH before
            dispatching legs.
        nativeOut:
          type: boolean
          description: Mirror of nativeIn for tokenOut = ETH (unwrap WETH).
    Error:
      type: object
      required:
        - error
      properties:
        error:
          type: string
    SplitRoute:
      type: object
      required:
        - amountIn
        - legs
      properties:
        amountIn:
          $ref: '#/components/schemas/AmountString'
        legs:
          type: array
          minItems: 1
          items:
            $ref: '#/components/schemas/RouteLeg'
    GasEstimate:
      type: object
      required:
        - gasUnits
      properties:
        gasUnits:
          type: integer
          minimum: 0
        gasCostWei:
          $ref: '#/components/schemas/AmountString'
    FeeBreakdown:
      type: object
      required:
        - protocolFeeAmount
        - integratorFeeAmount
      properties:
        protocolFeeAmount:
          $ref: '#/components/schemas/AmountString'
        integratorFeeAmount:
          $ref: '#/components/schemas/AmountString'
    RouteMetadata:
      type: object
      required:
        - connectorsConsidered
        - candidatePaths
        - selectedPaths
        - candidates
      properties:
        connectorsConsidered:
          type: array
          items:
            $ref: '#/components/schemas/Address'
        candidatePaths:
          type: integer
          minimum: 0
        selectedPaths:
          type: integer
          minimum: 0
        candidates:
          type: array
          items:
            $ref: '#/components/schemas/RouteCandidateMetadata'
      additionalProperties: true
    RouteLeg:
      type: object
      required:
        - dex
        - tokenIn
        - tokenOut
        - amountIn
        - minOut
        - data
      properties:
        dex:
          $ref: '#/components/schemas/DexId'
        tokenIn:
          $ref: '#/components/schemas/Address'
        tokenOut:
          $ref: '#/components/schemas/Address'
        amountIn:
          $ref: '#/components/schemas/AmountString'
        minOut:
          $ref: '#/components/schemas/AmountString'
        poolId:
          type: string
        data:
          $ref: '#/components/schemas/LegData'
    RouteCandidateMetadata:
      type: object
      required:
        - path
        - dexes
        - projectedOut
        - allocatedIn
        - score
      properties:
        path:
          type: array
          items:
            $ref: '#/components/schemas/Address'
        dexes:
          type: array
          items:
            $ref: '#/components/schemas/DexId'
        projectedOut:
          $ref: '#/components/schemas/AmountString'
        allocatedIn:
          $ref: '#/components/schemas/AmountString'
        score:
          type: number
    LegData:
      description: |
        Tagged union discriminated by `kind`. Direct-pool legs (`v2_direct`,
        `v3_direct`, `pancake_v3_direct`, `algebra_direct`) carry a single
        pool address and are dispatched by the corresponding O1Router
        adapter. Multi-hop venue legs (`univ4`, `aerodrome_v2`, `curve`,
        `dodo_v2`, `woofi`, `prop_amm`) carry venue-specific routing data.
        Legacy `univ2` / `univ3` shapes are still emitted for older quotes
        in transit.
      oneOf:
        - $ref: '#/components/schemas/V2DirectLegData'
        - $ref: '#/components/schemas/V3DirectLegData'
        - $ref: '#/components/schemas/PancakeV3DirectLegData'
        - $ref: '#/components/schemas/AlgebraDirectLegData'
        - $ref: '#/components/schemas/HydrexLegData'
        - $ref: '#/components/schemas/UniV4LegData'
        - $ref: '#/components/schemas/CurveLegData'
        - $ref: '#/components/schemas/PropAmmLegData'
        - $ref: '#/components/schemas/DodoV2LegData'
        - $ref: '#/components/schemas/WooFiLegData'
        - $ref: '#/components/schemas/UniV2LegData'
        - $ref: '#/components/schemas/UniV3LegData'
        - $ref: '#/components/schemas/AerodromeLegData'
      discriminator:
        propertyName: kind
        mapping:
          v2_direct:
            $ref: '#/components/schemas/V2DirectLegData'
          v3_direct:
            $ref: '#/components/schemas/V3DirectLegData'
          pancake_v3_direct:
            $ref: '#/components/schemas/PancakeV3DirectLegData'
          algebra_direct:
            $ref: '#/components/schemas/AlgebraDirectLegData'
          hydrex:
            $ref: '#/components/schemas/HydrexLegData'
          univ4:
            $ref: '#/components/schemas/UniV4LegData'
          curve:
            $ref: '#/components/schemas/CurveLegData'
          prop_amm:
            $ref: '#/components/schemas/PropAmmLegData'
          dodo_v2:
            $ref: '#/components/schemas/DodoV2LegData'
          woofi:
            $ref: '#/components/schemas/WooFiLegData'
          univ2:
            $ref: '#/components/schemas/UniV2LegData'
          univ3:
            $ref: '#/components/schemas/UniV3LegData'
          aerodrome_v2:
            $ref: '#/components/schemas/AerodromeLegData'
    V2DirectLegData:
      type: object
      required:
        - kind
        - pool
        - feeBps
      properties:
        kind:
          type: string
          const: v2_direct
        pool:
          $ref: '#/components/schemas/Address'
        feeBps:
          type: integer
          minimum: 0
          maximum: 10000
    V3DirectLegData:
      type: object
      required:
        - kind
        - pool
      properties:
        kind:
          type: string
          const: v3_direct
        pool:
          $ref: '#/components/schemas/Address'
    PancakeV3DirectLegData:
      type: object
      required:
        - kind
        - pool
      properties:
        kind:
          type: string
          const: pancake_v3_direct
        pool:
          $ref: '#/components/schemas/Address'
    AlgebraDirectLegData:
      type: object
      required:
        - kind
        - pool
      properties:
        kind:
          type: string
          const: algebra_direct
        pool:
          $ref: '#/components/schemas/Address'
    HydrexLegData:
      type: object
      required:
        - kind
      properties:
        kind:
          type: string
          const: hydrex
        deadline:
          type: integer
          format: int64
    UniV4LegData:
      type: object
      required:
        - kind
        - commands
        - inputs
      properties:
        kind:
          type: string
          const: univ4
        commands:
          $ref: '#/components/schemas/Hex'
        inputs:
          type: array
          items:
            $ref: '#/components/schemas/Hex'
        deadline:
          type: integer
          format: int64
    CurveLegData:
      type: object
      required:
        - kind
        - pool
        - i
        - j
      properties:
        kind:
          type: string
          const: curve
        pool:
          $ref: '#/components/schemas/Address'
        i:
          type: integer
          minimum: 0
        j:
          type: integer
          minimum: 0
    PropAmmLegData:
      type: object
      required:
        - kind
        - router
        - protocol
      properties:
        kind:
          type: string
          const: prop_amm
        router:
          $ref: '#/components/schemas/Address'
        protocol:
          type: string
          enum:
            - propswap
            - tessera
            - elfomofi
            - lunarbase
            - feltir
    DodoV2LegData:
      type: object
      required:
        - kind
        - pool
        - baseToken
      properties:
        kind:
          type: string
          const: dodo_v2
        pool:
          $ref: '#/components/schemas/Address'
        baseToken:
          $ref: '#/components/schemas/Address'
    WooFiLegData:
      type: object
      required:
        - kind
        - router
      properties:
        kind:
          type: string
          const: woofi
        router:
          $ref: '#/components/schemas/Address'
    UniV2LegData:
      type: object
      required:
        - kind
        - path
      properties:
        kind:
          type: string
          const: univ2
        path:
          type: array
          minItems: 2
          items:
            $ref: '#/components/schemas/Address'
        deadline:
          type: integer
          format: int64
    UniV3LegData:
      type: object
      required:
        - kind
        - path
      properties:
        kind:
          type: string
          const: univ3
        path:
          $ref: '#/components/schemas/Hex'
        deadline:
          type: integer
          format: int64
    AerodromeLegData:
      type: object
      required:
        - kind
        - routes
      properties:
        kind:
          type: string
          const: aerodrome_v2
        routes:
          type: array
          minItems: 1
          items:
            $ref: '#/components/schemas/AerodromeRoute'
        deadline:
          type: integer
          format: int64
    Hex:
      type: string
      pattern: ^0x[a-fA-F0-9]*$
      description: Hex-encoded bytes.
    AerodromeRoute:
      type: object
      required:
        - from
        - to
        - stable
        - factory
      properties:
        from:
          $ref: '#/components/schemas/Address'
        to:
          $ref: '#/components/schemas/Address'
        stable:
          type: boolean
        factory:
          $ref: '#/components/schemas/Address'
  responses:
    BadRequest:
      description: Validation error
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    Unauthorized:
      description: Missing or incorrect x-api-key
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    RateLimited:
      description: Sliding-window rate limit exceeded (default 120/min/IP)
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: x-api-key

````