> ## 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 /execute

> One-shot quote + submit. Returns a fresh quote and broadcast-ready calldata in a single call.

`POST /execute` is the one-step convenience endpoint. It runs `/quote` and `/submit` server-side and returns both the route plan (so you can display it) and the calldata (so you can broadcast).

Use this when:

* You don't need a separate price preview step (one-click swap, server-side bot).
* You want to avoid the `quoteId` round trip.
* You always submit immediately after quoting.

For UIs that show a quote, let the user think, then submit, prefer the [`/quote` + `/submit`](/api/dex-aggregator/guides/integration-patterns) two-step flow so the user sees the final price before signing.

<Info>
  * **Authentication:** `x-api-key` header required.
  * **`user` is required** here (unlike `/quote`) because the response includes signed-ready calldata.
</Info>

## Request

<Tabs>
  <Tab title="Endpoint">
    ```http theme={null} theme={null}
    POST {API_URL}/execute
    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,
      "user": "0xYourWalletAddress",
      "useNativeIn": false,
      "unwrapNativeOut": true,
      "feeBps": 30
    }
    ```
  </Tab>
</Tabs>

### Body parameters

`/execute` accepts the union of `/quote` and `/submit` parameters.

| Field                 | Type             | Required | Description                                        |
| --------------------- | ---------------- | -------- | -------------------------------------------------- |
| `chainId`             | integer          | yes      | `8453` for Base.                                   |
| `tokenIn`             | address          | yes      | Token to sell. Native sentinel allowed.            |
| `tokenOut`            | address          | yes      | Token to buy. Native sentinel allowed.             |
| `amountIn`            | string           | yes      | Amount in wei as a decimal string.                 |
| `slippageBps`         | integer          | yes      | Slippage tolerance in bps (`0..10000`).            |
| `user`                | address          | yes      | Wallet that will sign the tx.                      |
| `useNativeIn`         | boolean          | no       | Override native-in detection.                      |
| `unwrapNativeOut`     | boolean          | no       | Receive native ETH instead of WETH.                |
| `feeBps`              | integer          | no       | Integrator fee in bps.                             |
| `maxHops`             | integer          | no       | Default `3`.                                       |
| `splitEnabled`        | boolean          | no       | Default `true`.                                    |
| `enforcePoolDisjoint` | boolean          | no       | Default `false`.                                   |
| `allowedDexes`        | array of `DexId` | no       | Restrict routing to specific venues.               |
| `permit`              | object           | no       | EIP-2612 permit payload (same shape as `/submit`). |

See [`POST /quote`](/api/dex-aggregator/endpoints/quote) and [`POST /submit`](/api/dex-aggregator/endpoints/submit) for full descriptions of each field.

## Response

<Tabs>
  <Tab title="200 OK">
    ```json theme={null} theme={null}
    {
      "quoteId": "a1b2c3d4e5f6...",
      "chainId": 8453,
      "to": "0x8Dc736C6BA12e1Df1c73DB6BED8d7573F0aD90B3",
      "data": "0x...",
      "value": "0",
      "expiresAt": 1712180000000,
      "routePlan": {
        "chainId": 8453,
        "tokenIn": "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913",
        "tokenOut": "0x4200000000000000000000000000000000000006",
        "amountIn": "1000000000",
        "expectedAmountOut": "484446072048780734",
        "minAmountOut": "479601611328292926",
        "slippageBps": 100,
        "blockNumber": 44266656,
        "routes": [ /* ... */ ]
      }
    }
    ```
  </Tab>

  <Tab title="400 Bad Request">
    ```json theme={null} theme={null}
    { "error": "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

A union of the `/quote` response (so you can display the price) and `/submit` response (so you can broadcast).

| Field       | Type    | Description                                                                           |
| ----------- | ------- | ------------------------------------------------------------------------------------- |
| `quoteId`   | string  | The freshly issued quote ID. Useful for log correlation.                              |
| `chainId`   | integer | `8453`.                                                                               |
| `to`        | address | Always the `O1Router`.                                                                |
| `data`      | hex     | `swapExactIn(...)` calldata.                                                          |
| `value`     | string  | `msg.value` in wei.                                                                   |
| `expiresAt` | integer | Unix milliseconds at which the cached quote drops.                                    |
| `routePlan` | object  | Full route plan. See [RoutePlan reference](/api/dex-aggregator/reference/route-plan). |

## Examples

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

  const txHash = await walletClient.sendTransaction({
    to: exec.to as `0x${string}`,
    data: exec.data as `0x${string}`,
    value: BigInt(exec.value),
  });
  ```

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

<Tip>
  `/execute` always returns a fresh quote. There's no risk of `404 expired` here because the quote is consumed immediately on the server side.
</Tip>


## OpenAPI

````yaml openapi.yaml POST /execute
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:
  /execute:
    post:
      tags:
        - submit
      summary: One-shot quote + submit
      description: >-
        Equivalent to calling /quote then /submit. The taker address is
        required.
      operationId: postExecute
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ExecuteRequest'
      responses:
        '200':
          description: Quote + transaction payload
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ExecuteResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '429':
          $ref: '#/components/responses/RateLimited'
components:
  schemas:
    ExecuteRequest:
      type: object
      required:
        - chainId
        - tokenIn
        - tokenOut
        - amountIn
        - slippageBps
        - user
      properties:
        chainId:
          type: integer
          minimum: 1
        tokenIn:
          $ref: '#/components/schemas/Address'
        tokenOut:
          $ref: '#/components/schemas/Address'
        amountIn:
          $ref: '#/components/schemas/AmountString'
        slippageBps:
          type: integer
          minimum: 0
          maximum: 10000
        user:
          $ref: '#/components/schemas/Address'
        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
        useNativeIn:
          type: boolean
        unwrapNativeOut:
          type: boolean
        permit:
          $ref: '#/components/schemas/PermitPayload'
      additionalProperties: false
    ExecuteResponse:
      type: object
      required:
        - quoteId
        - chainId
        - to
        - data
        - value
        - routePlan
        - expiresAt
      properties:
        quoteId:
          type: string
        chainId:
          type: integer
        to:
          $ref: '#/components/schemas/Address'
        data:
          $ref: '#/components/schemas/Hex'
        value:
          $ref: '#/components/schemas/AmountString'
        routePlan:
          $ref: '#/components/schemas/RoutePlan'
        expiresAt:
          type: integer
          format: int64
    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
    PermitPayload:
      type: object
      required:
        - value
        - deadline
        - v
        - r
        - s
      properties:
        value:
          $ref: '#/components/schemas/AmountString'
        deadline:
          type: integer
          format: int64
          description: Unix timestamp (seconds) at which the permit expires.
        v:
          type: integer
          minimum: 0
          maximum: 255
        r:
          $ref: '#/components/schemas/Hex'
        s:
          $ref: '#/components/schemas/Hex'
    Hex:
      type: string
      pattern: ^0x[a-fA-F0-9]*$
      description: Hex-encoded bytes.
    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
    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

````