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

# Create a limit order

> Create an order that sells a token from the maker's wallet when the market reaches your price.

`POST /limit-order` creates an order to sell `amount` of `inTokenAddress` for `outTokenAddress`. The order executes when the market price of `inTokenAddress`, in `outTokenAddress`, reaches `priceTrigger` or better. Olympex stores the order as `pending` and returns it with its `id`. Nothing moves on-chain until Olympex executes the order from the maker's wallet, which is why the maker signs the token pair and approves the Olympex order contract before you call this endpoint.

Signed endpoint. Send `Content-Type: application/json`, the canonical JSON body, and the four headers `x-api-key-id`, `x-value-info`, `x-passphrase` and `x-signature` described in [Sign requests](/authentication/sign-requests). Required fields: `accountTo`, `chainId`, `inTokenAddress`, `outTokenAddress`, `tokenASymbol`, `tokenBSymbol`, `amount`, `priceTrigger`, `expired`, `gasPrice`, `slippage` and `signature`. `chainId` is an integer. `expired` is a Unix timestamp in milliseconds, as a 13-digit string, in the future and at most 365 days ahead. Fields Olympex sets, such as `status`, `txHash` and `reasonFail`, return `400 VALIDATION_ERROR`. `price` is optional; send the same value as `priceTrigger`. `tokenASymbol` and `tokenBSymbol` are the real symbols of the two tokens: Olympex can use them to find the reference price and doesn't check them, so check the symbols the response returns. Addresses are `0x` and 40 hex digits, lowercase or EIP-55 checksummed. `amount` and `priceTrigger` are human-readable decimal strings, not base units; `priceTrigger` is units of `outTokenAddress` per 1 `inTokenAddress`. `signature` is the maker's `personal_sign` over the 32 bytes of `keccak256(abi.encodePacked(accountTo, accountTo, inTokenAddress, outTokenAddress))`, and Olympex doesn't check it at creation. The maker must also approve the Olympex order contract for `amount` plus the execution gas cost, both in `inTokenAddress`. Success is HTTP `200` with the new order. Every success creates a new order: after a timeout, list orders with `GET /limit-order` before you retry.

## Before you call it

`accountTo` is the maker: it sells `inTokenAddress`, receives all the output and signs `signature`. It must be an externally owned account (EOA). Smart-contract wallets, such as Safe or ERC-4337 accounts, can't sign orders, because only 65-byte ECDSA signatures are accepted. Olympex stores `accountTo` exactly as you send it, and the `accountTo` filter of [`GET /limit-order`](/api-reference/limit-orders/list-limit-orders) matches case-sensitively, so always send the EIP-55 checksummed form, which `getAddress()` returns in ethers and viem.

The maker wallet does two things before you call this endpoint. Neither one calls Olympex.

1. **Sign the token pair.** The maker signs `keccak256(abi.encodePacked(accountTo, accountTo, inTokenAddress, outTokenAddress))` with `personal_sign`, over the 32 raw bytes, not the hex string. One signature serves every limit order and DCA strategy for that maker and pair. Olympex doesn't check the signature when you create the order, and a wrong one makes execution fail later, so verify it yourself before you send it, as the signing helpers in the examples do. [Order signatures and allowances](/concepts/order-authorization) explains what the signature authorizes and how to produce it.
2. **Approve the Olympex order contract** for `amount` plus the execution gas cost, both in `inTokenAddress`. The spender is the order contract for `chainId`, listed in [The order contract](/concepts/order-authorization#the-order-contract). It isn't the `contractToApprove` that `POST /swap` returns, which is for swaps.

**How funds move.** Creating the order moves nothing. At execution, Olympex pulls `amount` of `inTokenAddress` from `accountTo` through the order contract, swaps it and sends all the output to `accountTo`. Olympex pays the execution gas and takes it back from `accountTo` in `inTokenAddress`, as a second transfer, which is why the allowance covers the gas cost too. Estimate that cost with a single-chain [`POST /quotes`](/api-reference/quotes/get-quote) for the same pair and amount, with `params.includeGasInfo` set to `true`: `dataFeeTransaction.transactionFeeInToken` is the fee, and `valueToApprove` is `amount` plus the fee, both human-readable. Add a buffer: gas prices move, and the estimate leaves out the gas the Olympex contracts use. Keep the balance and the allowance in place while the order is open: Olympex can't execute the order without them.

<Warning>
  Approve only what your open orders need, never an unlimited amount. The pair signature doesn't limit the amount, so the allowance is the on-chain limit. The allowance is shared: approve the **sum** for every open limit order and active DCA strategy that sells the same token on the same chain.
</Warning>

In a dApp, the user's wallet signs the pair and sends the approval in the browser, and your server calls this endpoint. Your API credentials never reach the browser.

## Units and formats

| Field | Format |
| - | - |
| `amount` | Amount of `inTokenAddress` to sell, as a human-readable decimal string. `"0.5"` is 0.5 WETH, not 0.5 base units. |
| `priceTrigger` | Units of `outTokenAddress` per 1 `inTokenAddress`, as a human-readable decimal string. `"4200"` on a WETH to USDC order is 4,200 USDC per WETH. |
| `price` | Optional. A copy of the limit price that Olympex stores as sent and never syncs with `priceTrigger`. Send the same value as `priceTrigger`, and send both whenever you change one. Responses return `0` when you omit it. |
| `expired` | A Unix timestamp in milliseconds, as a 13-digit string, in the future and at most 365 days ahead: `String(Date.now() + 7 * 24 * 60 * 60 * 1000)` is one week from now. A time in seconds, an ISO 8601 date or a past time returns `400 VALIDATION_ERROR`. Don't rely on it to stop the order: when you no longer want the order, cancel it and lower the allowance. |
| `gasPrice` | The chain's current gas price in gwei, as a decimal string. `"35"` is 35 gwei. Olympex stores it with the order. It isn't a cap: neither the API nor the order contract enforces it, and the gas cost the maker reimburses is the execution transaction's gas used times its actual gas price, converted to `inTokenAddress`. Size the allowance from the fee estimate plus a buffer, not from `gasPrice`. |
| `slippage` | Maximum slippage at execution, in percent, as a string. `"1"` is 1%. |
| `chainId` | An integer, such as `137`. A string returns `400 VALIDATION_ERROR`. Responses return an integer. Limit orders execute only on the chains listed in [The order contract](/concepts/order-authorization#the-order-contract). |

Responses return `amount`, `price` and `priceTrigger` as JSON numbers. Olympex stores them as double-precision numbers, so send at most 15 significant digits: `"0.123456789123456789"` comes back as `0.12345678912345678`. Fields that Olympex sets as it executes the order, such as `status`, `txHash` and `reasonFail`, aren't accepted: sending one returns `400 VALIDATION_ERROR`.

## The token pair

**Reference price.** Olympex picks the market that prices the order when you create it. It reuses a recent lookup for the same `chainId`, `inTokenAddress` and `outTokenAddress`, written exactly the same way, and then ignores the symbols you send. Otherwise it looks for a market for `tokenASymbol` and `tokenBSymbol`, and if it finds none, it identifies the two tokens by address. Olympex doesn't check the symbols against the token contracts. Set `tokenASymbol` to the real symbol of the token you sell and `tokenBSymbol` to the real symbol of the token you buy, for example `WETH` and `USDC`. Read them with `symbol()` from the token contracts, or take them from [`GET /tokens`](/api-reference/tokens/list-tokens) by address, trimmed and without a trailing `_<number>` (send `ICE` for `ICE_3`). When Olympex finds no price source for the pair, the call returns `400 VALIDATION_ERROR` with the message `"Not exist reference price for this pair A/B"`, where `A/B` are the symbols you sent, and no order is created. The error can be temporary, so retry later with backoff before you rule the pair out.

**Normalized symbols.** Responses can return normalized symbols: `WETH` comes back as `ETH`, `WBNB` as `BNB` and `WPOL` as `POL`. Identify orders by token address, never by symbol.

<Warning>
  Check `tokenASymbol` and `tokenBSymbol` in the response. A real but wrong symbol, such as `WBTC` on a WETH order, is accepted, and Olympex then watches that token's market. If a returned symbol is neither your token's symbol nor its normalized form (`WETH` as `ETH`, `WBNB` as `BNB`, `WPOL` as `POL`), cancel the order.
</Warning>

**Tokens you can't sell.** Olympex can't execute an order that sells:

* A native token. `inTokenAddress` must be an ERC-20: wrap the native token first and sell WETH, WBNB or WPOL. [List tokens](/api-reference/tokens/list-tokens#match-tokens-by-address) gives their addresses on Ethereum, BNB Chain and Polygon.
* An ERC-20 whose `transfer` and `approve` don't return a boolean. USDT is the notable one: it isn't supported as the token you sell in limit orders or DCA on Ethereum.
* A fee-on-transfer token.

## Don't retry a create blindly

Every successful call creates a new order, and Olympex ignores any `id` you send. If the call times out, or returns a `5xx` or no response at all, the order may exist anyway. Before you send it again, list the maker's orders with [`GET /limit-order`](/api-reference/limit-orders/list-limit-orders#find-an-order-after-a-create-call-timed-out) and match on the fields you sent. A duplicate is a second order that Olympex can execute against the same allowance. The retry wrappers in [Handle errors and retries](/guides/handle-errors-and-retries) never repeat this call on their own.

After you create the order, poll [`GET /limit-order/{id}`](/api-reference/limit-orders/get-limit-order) to follow its `status`. Change a `pending` order with [`PATCH /limit-order/{id}`](/api-reference/limit-orders/update-limit-order), and cancel it with [`DELETE /limit-order/{id}`](/api-reference/limit-orders/cancel-limit-order). The [Place a limit order](/guides/create-a-limit-order) guide walks through the whole flow.

<RequestExample>
  ```bash cURL theme={null}
  # Create a limit order on Polygon: sell 0.5 WETH for USDC at 4200 USDC per WETH or better.
  # Needs openssl, curl, python3 and OLYMPEX_API_KEY_ID, OLYMPEX_SECRET_KEY, OLYMPEX_PASSPHRASE, plus the maker's key in
  # WALLET_PRIVATE_KEY and sign_order_pair.py from /concepts/order-authorization in this folder, with eth-account
  # installed in an active virtual environment.
  SIGNED="$(python3 -c 'import os, sign_order_pair as s; r = s.sign_order_pair(os.environ["WALLET_PRIVATE_KEY"], "0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619", "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359"); print(r["accountTo"], r["signature"])')"
  MAKER="${SIGNED% *}"      # the maker's EIP-55 address
  SIGNATURE="${SIGNED#* }"  # the maker's signature for the WETH to USDC pair
  EXPIRED="$(( ($(date +%s) + 7 * 86400) * 1000 ))" # 7 days from now, as a Unix timestamp in milliseconds
  METHOD=POST
  ENDPOINT=/limit-order
  QUERY=''
  BODY="$(printf '{"accountTo":"%s","amount":"0.5","chainId":137,"expired":"%s","gasPrice":"35","inTokenAddress":"0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619","outTokenAddress":"0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359","price":"4200","priceTrigger":"4200","signature":"%s","slippage":"1","tokenASymbol":"WETH","tokenBSymbol":"USDC"}' "$MAKER" "$EXPIRED" "$SIGNATURE")"
  TS="${OLYMPEX_TIMESTAMP:-$(date +%s)}"
  NONCE="${OLYMPEX_NONCE:-$(openssl rand -hex 12)}"
  BODY_HASH="$(printf '%s' "$BODY" | openssl dgst -sha256 -binary | openssl base64 -A | tr '+/' '-_' | tr -d '=')"
  VALUE_INFO="$(printf '%s\n%s\n%s' "$TS" "$NONCE" "$BODY_HASH")"
  MESSAGE="$(printf 'OLPX-HMAC-SHA256-V2\n%s\n%s\n%s\n%s\n%s\n%s' "$TS" "$NONCE" "$METHOD" "/api/v1$ENDPOINT" "$QUERY" "$BODY_HASH")"
  curl -sS -X "$METHOD" "https://api-rest.olympex.io/api/v1$ENDPOINT${QUERY:+?$QUERY}" \
    -H "content-type: application/json" \
    -H "x-api-key-id: $OLYMPEX_API_KEY_ID" \
    -H "x-value-info: $(printf '%s' "$VALUE_INFO" | openssl base64 -A)" \
    -H "x-passphrase: $OLYMPEX_PASSPHRASE" \
    -H "x-signature: $(printf '%s' "$MESSAGE" | openssl dgst -sha256 -hmac "$OLYMPEX_SECRET_KEY" -binary | od -An -v -tx1 | tr -d ' \n')" \
    --data-raw "$BODY"
  ```

  ```ts TypeScript theme={null}
  // npm install ethers. Reads the maker's WALLET_PRIVATE_KEY from the environment.
  import { Wallet } from "ethers";
  import { olympexRequest } from "./sign-request.ts"; // /authentication/sign-requests
  import { signOrderPair } from "./sign-order-pair.ts"; // /concepts/order-authorization

  const WETH = "0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619"; // Polygon
  const USDC = "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359"; // Polygon

  // An EOA that holds the WETH and has approved the Olympex order contract.
  // In a dApp, pass the user's wallet signer instead.
  const wallet = new Wallet(process.env.WALLET_PRIVATE_KEY!);
  const { accountTo, signature } = await signOrderPair(wallet, WETH, USDC); // checks the signature before it returns

  type LimitOrder = { id: string; status: string; tokenASymbol: string; tokenBSymbol: string };

  // Every success creates a new order: after a timeout, list the orders before you retry.
  const order = await olympexRequest<LimitOrder>("POST", "/limit-order", {
    accountTo, // EIP-55 checksummed
    chainId: 137,
    inTokenAddress: WETH,
    outTokenAddress: USDC,
    tokenASymbol: "WETH", // real symbols: Olympex finds the reference price with them
    tokenBSymbol: "USDC",
    amount: "0.5", // human-readable WETH, not base units
    priceTrigger: "4200", // USDC per 1 WETH
    price: "4200", // the same value as priceTrigger
    expired: String(Date.now() + 7 * 24 * 60 * 60 * 1000), // Unix timestamp in milliseconds, as a string
    gasPrice: "35", // gwei
    slippage: "1", // percent
    signature,
  });
  console.log(order.id, order.status); // save the ID

  // Olympex prices the order from the market of the symbols it returns, and WETH can come back as ETH.
  // Cancel an order priced from another token's market.
  if (!["WETH", "ETH"].includes(order.tokenASymbol) || order.tokenBSymbol !== "USDC") {
    await olympexRequest("DELETE", `/limit-order/${order.id}`);
    throw new Error(`Priced as ${order.tokenASymbol}/${order.tokenBSymbol}, not WETH/USDC: order cancelled`);
  }
  ```

  ```python Python theme={null}
  # In a virtual environment: python3 -m venv .venv && . .venv/bin/activate && python3 -m pip install eth-account requests
  import os
  import time

  from sign_order_pair import sign_order_pair  # /concepts/order-authorization
  from sign_request import olympex_request  # /authentication/sign-requests

  WETH = "0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619"  # Polygon
  USDC = "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359"  # Polygon

  # An EOA that holds the WETH and has approved the Olympex order contract.
  pair = sign_order_pair(os.environ["WALLET_PRIVATE_KEY"], WETH, USDC)  # checks the signature before it returns

  # Every success creates a new order: after a timeout, list the orders before you retry.
  order = olympex_request("POST", "/limit-order", {
      "accountTo": pair["accountTo"],  # EIP-55 checksummed
      "chainId": 137,
      "inTokenAddress": WETH,
      "outTokenAddress": USDC,
      "tokenASymbol": "WETH",  # real symbols: Olympex finds the reference price with them
      "tokenBSymbol": "USDC",
      "amount": "0.5",  # human-readable WETH, not base units
      "priceTrigger": "4200",  # USDC per 1 WETH
      "price": "4200",  # the same value as priceTrigger
      "expired": str(int(time.time() * 1000) + 7 * 24 * 60 * 60 * 1000),  # Unix timestamp in milliseconds, as a string
      "gasPrice": "35",  # gwei
      "slippage": "1",  # percent
      "signature": pair["signature"],
  })
  print(order["id"], order["status"])  # save the ID

  # Olympex prices the order from the market of the symbols it returns, and WETH can come back as ETH.
  # Cancel an order priced from another token's market.
  if order["tokenASymbol"] not in ("WETH", "ETH") or order["tokenBSymbol"] != "USDC":
      olympex_request("DELETE", f'/limit-order/{order["id"]}')
      raise RuntimeError(f'Priced as {order["tokenASymbol"]}/{order["tokenBSymbol"]}, not WETH/USDC: order cancelled')
  ```
</RequestExample>

<ResponseExample>
  ```json 200 theme={null}
  {
    "success": true,
    "data": {
      "id": "afc47108-d059-473c-b2e1-5f2ca7951466",
      "accountTo": "0x1E67cb01969D79B2B895179e4A07D24a839dBb52",
      "chainId": 137,
      "gasPrice": "35",
      "inTokenAddress": "0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619",
      "outTokenAddress": "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359",
      "slippage": "1",
      "tokenASymbol": "ETH",
      "tokenBSymbol": "USDC",
      "amount": 0.5,
      "price": 4200,
      "priceTrigger": 4200,
      "expired": "1791302400000",
      "txHash": "",
      "status": "pending",
      "reasonFail": [],
      "attemptNumber": 0,
      "allowance": "",
      "estimateGas": "",
      "effectivePriceGas": "",
      "createdAt": "2026-09-29T16:01:22.237Z",
      "updatedAt": "2026-09-29T16:01:22.237Z",
      "deletedAt": ""
    },
    "meta": {
      "requestId": "EeAQVh4coAMEJSw=",
      "version": "v1",
      "accountType": "integrator",
      "apiKeyId": "00000000-0000-4000-8000-000000000000"
    }
  }
  ```

  ```json 400 chainId as a string theme={null}
  {
    "success": false,
    "error": {
      "code": "VALIDATION_ERROR",
      "message": "Invalid request body",
      "details": [
        {
          "field": "chainId",
          "message": "Invalid input: expected number, received string"
        }
      ]
    },
    "meta": {
      "requestId": "E7eiXi2AIAMEZXA=",
      "version": "v1",
      "accountType": "integrator",
      "apiKeyId": "00000000-0000-4000-8000-000000000000"
    }
  }
  ```

  ```json 400 Expiry in seconds theme={null}
  {
    "success": false,
    "error": {
      "code": "VALIDATION_ERROR",
      "message": "Invalid request body",
      "details": [
        {
          "field": "expired",
          "message": "expired must be a Unix timestamp in milliseconds (13 digits), e.g. String(Date.now() + 86_400_000)"
        }
      ]
    },
    "meta": {
      "requestId": "E7eiLgFUoAMEZcQ=",
      "version": "v1",
      "accountType": "integrator",
      "apiKeyId": "00000000-0000-4000-8000-000000000000"
    }
  }
  ```

  ```json 400 No reference price theme={null}
  {
    "success": false,
    "error": {
      "code": "VALIDATION_ERROR",
      "message": "Not exist reference price for this pair FOOZZ/BARZZ",
      "details": [
        {
          "message": "Not exist pair for create limit order, you must be select a new pair (Not possible create limit order, you must be select a new pair | > Error => Could not recover data of contract)"
        }
      ]
    },
    "meta": {
      "requestId": "EdkfSjF0IAMEPEg=",
      "version": "v1",
      "accountType": "integrator",
      "apiKeyId": "00000000-0000-4000-8000-000000000000"
    }
  }
  ```

  ```json 403 Gateway theme={null}
  {
    "message": "Forbidden"
  }
  ```
</ResponseExample>


## OpenAPI

````yaml api-reference/openapi.json POST /limit-order
openapi: 3.0.3
info:
  title: Olympex REST API
  version: 1.0.0
  description: >-
    Aggregated swap quotes and transactions, limit orders and DCA strategies on
    EVM chains, plus the chain and token catalog. Every response uses the same
    envelope, except the API gateway's own responses (`{"message": …}`): `401`
    or `403` when the signed headers are missing or rejected, `429` when it
    throttles requests, and `500` or `503` when it can't get a response from
    Olympex in time. Chain IDs are integers on every endpoint. Signed endpoints
    require four signed headers; see [Sign
    requests](https://docs.olympex.io/authentication/sign-requests).
  termsOfService: https://docs.olympex.io/legal/terms
  contact:
    name: Olympex partnerships
    email: partners@olympex.io
    url: https://docs.olympex.io
servers:
  - url: https://api-rest.olympex.io/api/v1
    description: Olympex REST API v1
security: []
tags:
  - name: Accounts
    description: Create API credentials.
  - name: Quotes
    description: Aggregated single-chain and cross-chain quotes.
  - name: Swap
    description: Unsigned transaction calldata for a quoted route.
  - name: TxStatus
    description: Track a cross-chain transfer after you broadcast it.
  - name: Transactions
    description: On-chain status of a transaction you broadcast.
  - name: Chains and tokens
    description: Enabled chains and the tokens listed on each.
  - name: Limit orders
    description: Orders that Olympex executes when the market reaches your price.
  - name: DCA
    description: Strategies that buy a token in equal orders over time.
  - name: Docs
    description: Machine-readable API description.
paths:
  /limit-order:
    post:
      tags:
        - Limit orders
      summary: Create a limit order
      description: >-
        Creates an order to sell `amount` of `inTokenAddress` for
        `outTokenAddress` when the market reaches `priceTrigger` or better.
        Olympex checks that it has a reference price for the pair, then stores
        the order as `pending`. Nothing moves on-chain now: at execution,
        Olympex pulls the tokens from `accountTo` under the allowance
        `accountTo` granted to the Olympex order contract, and takes the gas
        cost in `inTokenAddress`. Each call creates a new order, so don't retry
        a call that timed out: list your orders first.
      operationId: createLimitOrder
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/LimitOrderCreateRequest'
      responses:
        '200':
          description: The order, as stored.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/LimitOrderSuccessResponse'
              example:
                success: true
                data:
                  id: afc47108-d059-473c-b2e1-5f2ca7951466
                  accountTo: '0x1E67cb01969D79B2B895179e4A07D24a839dBb52'
                  chainId: 137
                  gasPrice: '35'
                  inTokenAddress: '0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619'
                  outTokenAddress: '0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359'
                  slippage: '1'
                  tokenASymbol: ETH
                  tokenBSymbol: USDC
                  amount: 0.5
                  price: 4200
                  priceTrigger: 4200
                  expired: '1791302400000'
                  txHash: ''
                  status: pending
                  reasonFail: []
                  attemptNumber: 0
                  allowance: ''
                  estimateGas: ''
                  effectivePriceGas: ''
                  createdAt: '2026-09-29T16:01:22.237Z'
                  updatedAt: '2026-09-29T16:01:22.237Z'
                  deletedAt: ''
                meta:
                  requestId: EeAQVh4coAMEJSw=
                  version: v1
                  accountType: integrator
                  apiKeyId: 00000000-0000-4000-8000-000000000000
        '400':
          description: >-
            The body failed validation (`error.details` lists each field), for
            example a missing field, a `chainId` that isn't an integer, an
            `expired` that isn't a 13-digit millisecond timestamp within the
            next 365 days, or a field Olympex sets, such as `status`. Also
            returned when Olympex has no reference price for the pair.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                stringChainId:
                  summary: chainId sent as a string
                  value:
                    success: false
                    error:
                      code: VALIDATION_ERROR
                      message: Invalid request body
                      details:
                        - field: chainId
                          message: 'Invalid input: expected number, received string'
                    meta:
                      requestId: E7eiXi2AIAMEZXA=
                      version: v1
                      accountType: integrator
                      apiKeyId: 00000000-0000-4000-8000-000000000000
                expired:
                  summary: expired in seconds
                  value:
                    success: false
                    error:
                      code: VALIDATION_ERROR
                      message: Invalid request body
                      details:
                        - field: expired
                          message: >-
                            expired must be a Unix timestamp in milliseconds (13
                            digits), e.g. String(Date.now() + 86_400_000)
                    meta:
                      requestId: E7eiLgFUoAMEZcQ=
                      version: v1
                      accountType: integrator
                      apiKeyId: 00000000-0000-4000-8000-000000000000
                engineField:
                  summary: Field that Olympex sets
                  value:
                    success: false
                    error:
                      code: VALIDATION_ERROR
                      message: Invalid request body
                      details:
                        - field: ''
                          message: 'Unrecognized key: "status"'
                    meta:
                      requestId: E7eh2j9DoAMEPYg=
                      version: v1
                      accountType: integrator
                      apiKeyId: 00000000-0000-4000-8000-000000000000
                pair:
                  summary: No reference price for the pair
                  value:
                    success: false
                    error:
                      code: VALIDATION_ERROR
                      message: Not exist reference price for this pair FOOZZ/BARZZ
                      details:
                        - message: >-
                            Not exist pair for create limit order, you must be
                            select a new pair (Not possible create limit order,
                            you must be select a new pair | > Error => Could not
                            recover data of contract)
                    meta:
                      requestId: EdkfSjF0IAMEPEg=
                      version: v1
                      accountType: integrator
                      apiKeyId: 00000000-0000-4000-8000-000000000000
        '401':
          description: >-
            A signing header is missing. The gateway answers with
            `{"message":"Unauthorized"}` before your request reaches Olympex;
            the handler answers with the `UNAUTHORIZED` envelope when the
            authorizer context is missing.
          content:
            application/json:
              schema:
                oneOf:
                  - $ref: '#/components/schemas/GatewayError'
                  - $ref: '#/components/schemas/ErrorResponse'
              example:
                message: Unauthorized
        '403':
          description: >-
            Authentication failed: unknown key, wrong passphrase, invalid
            signature, timestamp outside the ±300 s window, reused nonce, or
            inactive account (gateway `{"message":"Forbidden"}`). The handler
            answers with the `FORBIDDEN` envelope when the body does not match
            the signed `bodyHash`.
          content:
            application/json:
              schema:
                oneOf:
                  - $ref: '#/components/schemas/GatewayError'
                  - $ref: '#/components/schemas/ErrorResponse'
              examples:
                gateway:
                  summary: Signature rejected by the gateway
                  value:
                    message: Forbidden
                bodyHash:
                  summary: Body does not match the signed hash
                  value:
                    success: false
                    error:
                      code: FORBIDDEN
                      message: Invalid body hash
                      details: []
                    meta:
                      requestId: ENXGDhsXIAMEMEw=
                      version: v1
                      accountType: integrator
                      apiKeyId: 00000000-0000-4000-8000-000000000000
        '404':
          description: >-
            Unknown path or wrong method (`NOT_FOUND`). `error.message` names
            the method and path.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                success: false
                error:
                  code: NOT_FOUND
                  message: No route for GET /api/v1/quote
                  details: []
                meta:
                  requestId: E7edogG4IAMEPYA=
                  version: v1
        '500':
          description: >-
            Olympex could not complete the request (`INTERNAL_ERROR`), or the
            gateway could not get a response (`{"message":"Internal Server
            Error"}`), which also happens on the first request after a quiet
            period. Retry with backoff.
          content:
            application/json:
              schema:
                oneOf:
                  - $ref: '#/components/schemas/ErrorResponse'
                  - $ref: '#/components/schemas/GatewayError'
              example:
                success: false
                error:
                  code: INTERNAL_ERROR
                  message: Unexpected internal error
                  details: []
                meta:
                  requestId: EdlnHjzkIAMEVUA=
                  version: v1
                  accountType: integrator
                  apiKeyId: 00000000-0000-4000-8000-000000000000
        '503':
          description: >-
            The gateway could not get a response in time (the integration
            timeout is about 30 seconds) or the service is briefly unavailable.
            Returned by the gateway. Retry with backoff.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GatewayError'
              example:
                message: Service Unavailable
      security:
        - ApiKeyId: []
          ValueInfo: []
          Passphrase: []
          Signature: []
components:
  schemas:
    LimitOrderCreateRequest:
      type: object
      properties:
        id:
          type: string
          format: uuid
          pattern: >-
            ^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$
          readOnly: true
          description: 'Ignored: Olympex assigns every order a new ID. Don''t send it.'
        accountTo:
          type: string
          minLength: 1
          description: >-
            The maker: the wallet that sells `inTokenAddress`, receives
            `outTokenAddress` and signs `signature`. It must be an externally
            owned account (EOA); smart-contract wallets can't sign orders.
            Stored exactly as sent. Send the EIP-55 checksummed form, and use
            the same form in list filters, which match case-sensitively. Must be
            a valid EVM address: `0x` and 40 hexadecimal digits, in lowercase or
            EIP-55 checksummed form. A mixed-case address with a wrong checksum
            returns `400 VALIDATION_ERROR` ("Must be a valid EVM address").
        chainId:
          type: integer
          minimum: 0
          exclusiveMinimum: true
          maximum: 9007199254740991
          description: >-
            Chain of both tokens, as an integer such as `137`. Use a chain from
            `GET /chains`. A string returns `400 VALIDATION_ERROR`.
        gasPrice:
          type: string
          minLength: 1
          description: >-
            Gas price for the execution, in gwei, as a decimal string. Olympex
            stores it with the order, but execution uses the chain's gas price
            at that moment, so it isn't a cap: the maker reimburses the
            execution's actual gas cost.
        inTokenAddress:
          type: string
          minLength: 1
          description: >-
            ERC-20 token to sell. Native tokens can't be sold: use the wrapped
            token (WETH, WBNB, WPOL). Must be a valid EVM address: `0x` and 40
            hexadecimal digits, in lowercase or EIP-55 checksummed form. A
            mixed-case address with a wrong checksum returns `400
            VALIDATION_ERROR` ("Must be a valid EVM address").
        outTokenAddress:
          type: string
          minLength: 1
          description: >-
            Token to buy. Must be a valid EVM address: `0x` and 40 hexadecimal
            digits, in lowercase or EIP-55 checksummed form. A mixed-case
            address with a wrong checksum returns `400 VALIDATION_ERROR` ("Must
            be a valid EVM address").
        slippage:
          type: string
          minLength: 1
          description: >-
            Maximum slippage at execution, in percent, as a decimal string
            (`"1"` is 1%).
        tokenASymbol:
          type: string
          minLength: 1
          description: >-
            Symbol of `inTokenAddress`, for example `WETH`, as the token
            contract's `symbol()` returns it (token lists can add suffixes such
            as `_1`). Olympex can use it to find the pair's reference price and
            doesn't check it against the token contract, so send the real symbol
            and check the symbols the response returns. Responses can return a
            normalized symbol (`WETH` becomes `ETH`).
        tokenBSymbol:
          type: string
          minLength: 1
          description: Symbol of `outTokenAddress`, for example `USDC`.
        amount:
          anyOf:
            - type: string
              minLength: 1
            - type: number
          description: >-
            Amount of `inTokenAddress` to sell, human-readable (`"0.5"` is 0.5
            WETH), not in base units. Send a decimal string. Responses return it
            as a number.
        price:
          anyOf:
            - type: string
            - type: number
          description: >-
            Optional copy of the limit price. Send the same value as
            `priceTrigger`. It's stored as sent and never synced with
            `priceTrigger`. Responses return `0` when you omit it.
        priceTrigger:
          anyOf:
            - type: string
              minLength: 1
            - type: number
          description: >-
            Limit price: units of `outTokenAddress` per 1 `inTokenAddress`,
            human-readable. The order executes when the market reaches this
            price or better. Send a decimal string. Responses return it as a
            number.
        expired:
          type: string
          description: >-
            When the order expires: a Unix timestamp in milliseconds, as a
            13-digit string, in the future and at most 365 days ahead. Compute
            it when you send the request, for example `String(Date.now() + 7 *
            86400000)`. A time in seconds, an ISO 8601 date or a past time
            returns `400 VALIDATION_ERROR`.
        signature:
          type: string
          minLength: 1
          description: >-
            The maker's signature authorizing Olympex to execute orders for this
            token pair: `personal_sign` over
            `keccak256(abi.encodePacked(accountTo, accountTo, inTokenAddress,
            outTokenAddress))`, 65 bytes as 0x-prefixed hex. Olympex doesn't
            check it when you create the order; a wrong signature makes
            execution fail later. See [Order signatures and
            allowances](/concepts/order-authorization).
        pair:
          type: string
          readOnly: true
          description: Set by Olympex from the reference-price lookup. Don't send it.
        provider:
          type: string
          readOnly: true
          description: Set by Olympex from the reference-price lookup. Don't send it.
      required:
        - accountTo
        - chainId
        - gasPrice
        - inTokenAddress
        - outTokenAddress
        - slippage
        - tokenASymbol
        - tokenBSymbol
        - amount
        - priceTrigger
        - expired
        - signature
      additionalProperties: false
      description: >-
        Creates an order that Olympex executes when the market reaches
        `priceTrigger`. New orders always start `pending`. Fields marked
        read-only are accepted by the API but reserved for Olympex. A field the
        schema doesn't list, including the ones Olympex sets during execution
        (`status`, `txHash`, `executorAddress`, `reasonFail`, `allowance`,
        `estimateGas`, `effectivePriceGas`), returns `400 VALIDATION_ERROR`.
      example:
        accountTo: '0x1E67cb01969D79B2B895179e4A07D24a839dBb52'
        amount: '0.5'
        chainId: 137
        expired: '1814400000000'
        gasPrice: '35'
        inTokenAddress: '0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619'
        outTokenAddress: '0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359'
        price: '4200'
        priceTrigger: '4200'
        signature: 0x<65-byte signature from accountTo>
        slippage: '1'
        tokenASymbol: WETH
        tokenBSymbol: USDC
    LimitOrderSuccessResponse:
      type: object
      required:
        - success
        - data
        - meta
      properties:
        success:
          type: boolean
          enum:
            - true
        data:
          $ref: '#/components/schemas/LimitOrder'
        meta:
          $ref: '#/components/schemas/Meta'
    ErrorResponse:
      type: object
      required:
        - success
        - error
        - meta
      properties:
        success:
          type: boolean
          enum:
            - false
        error:
          $ref: '#/components/schemas/ErrorBody'
        meta:
          $ref: '#/components/schemas/Meta'
    GatewayError:
      type: object
      required:
        - message
      description: >-
        Returned by the API gateway itself: `401` or `403` when the signed
        headers are missing or rejected, `429` when it throttles requests, and
        `500` or `503` when it can't get a response from Olympex in time. It has
        no `success`, `error` or `meta`.
      properties:
        message:
          type: string
          example: Forbidden
    LimitOrder:
      type: object
      description: A limit order. Olympex can add fields; ignore the ones you don't use.
      required:
        - id
        - accountTo
        - chainId
        - inTokenAddress
        - outTokenAddress
        - tokenASymbol
        - tokenBSymbol
        - amount
        - price
        - priceTrigger
        - expired
        - slippage
        - gasPrice
        - status
        - txHash
        - reasonFail
        - attemptNumber
        - createdAt
        - updatedAt
        - deletedAt
      properties:
        id:
          type: string
          format: uuid
          description: Order ID.
        accountTo:
          type: string
          description: Maker wallet, as sent when the order was created.
        chainId:
          type: integer
          description: Chain ID.
        inTokenAddress:
          type: string
          description: Token sold, as sent.
        outTokenAddress:
          type: string
          description: Token bought, as sent.
        tokenASymbol:
          type: string
          description: >-
            Symbol of the token sold, possibly normalized (`WETH` becomes
            `ETH`).
        tokenBSymbol:
          type: string
          description: Symbol of the token bought, possibly normalized.
        amount:
          type: number
          description: Amount of the token sold, human-readable.
        price:
          type: number
          description: Copy of the limit price. `0` when it wasn't sent.
        priceTrigger:
          type: number
          description: 'Limit price: units of the token bought per 1 token sold.'
        expired:
          type: string
          description: 'Expiry as sent: a Unix timestamp in milliseconds.'
        slippage:
          type: string
          description: Maximum slippage, in percent.
        gasPrice:
          type: string
          description: >-
            Gas price, in gwei, as sent. Olympex stores it with the order, but
            execution uses the chain's gas price at that moment, so it isn't a
            cap.
        status:
          type: string
          enum:
            - pending
            - executing
            - submitted
            - completed
            - cancelled
            - failed
          description: >-
            `pending`: waiting for the price. `executing` and `submitted`:
            Olympex is executing it. `completed`: executed, see `txHash`.
            `cancelled`: cancelled. `failed`: execution failed, see
            `reasonFail`. Treat any other value as not final.
        txHash:
          type: string
          description: >-
            Execution transaction hash on `chainId`. Empty until the order
            executes.
        reasonFail:
          type: array
          items:
            type: string
          description: Why execution failed, when it did. Empty otherwise.
        attemptNumber:
          type: integer
          description: How many times Olympex has tried to execute the order.
        allowance:
          type: string
          description: >-
            Informational, reserved for Olympex: you can't set it. Usually an
            empty string.
        estimateGas:
          type: string
          description: >-
            Informational, reserved for Olympex: you can't set it. Usually an
            empty string.
        effectivePriceGas:
          type: string
          description: >-
            Informational, reserved for Olympex: you can't set it. Usually an
            empty string.
        createdAt:
          type: string
          format: date-time
          description: When the order was created (ISO 8601, UTC).
        updatedAt:
          type: string
          format: date-time
          description: When the order last changed (ISO 8601, UTC).
        deletedAt:
          type: string
          description: >-
            When the order was cancelled with `DELETE` (ISO 8601, UTC). An empty
            string until then.
    Meta:
      type: object
      required:
        - requestId
        - version
      properties:
        requestId:
          type: string
          description: Unique ID for this request. Include it when you contact support.
        version:
          type: string
          default: v1
          description: API version that served the request.
        accountType:
          type: string
          description: >-
            Account type resolved by the signature check, for example
            `integrator`. Present when the request was authenticated; absent on
            the `404` for an unknown path or method.
        apiKeyId:
          type: string
          format: uuid
          description: >-
            The API key ID that signed the request. Present when the request was
            authenticated; absent on the `404` for an unknown path or method.
    ErrorBody:
      type: object
      required:
        - code
        - message
        - details
      properties:
        code:
          type: string
          description: >-
            Machine-readable error code. `VALIDATION_ERROR` (400),
            `UNAUTHORIZED` (401), `FORBIDDEN` (403), `NOT_FOUND` (404, also for
            an unknown path or method), `CONFLICT` (409), `NO_ROUTE` (422), and
            for 500: `QUOTE_ERROR`, `CROSS_CHAIN_QUOTE_ERROR`, `SWAP_ERROR`,
            `CROSS_CHAIN_SWAP_ERROR`, `SUPPORT_CHAIN_ERROR`,
            `ENABLED_CHAINS_ERROR`, `TOKEN_LIST_ERROR`, `TX_STATUS_ERROR`,
            `INTERNAL_ERROR`. Olympex can add codes: handle an unknown code by
            its HTTP status.
        message:
          type: string
          description: Human-readable summary. Don't parse it.
        details:
          type: array
          items:
            $ref: '#/components/schemas/ErrorDetail'
    ErrorDetail:
      type: object
      additionalProperties: true
      description: >-
        Validation errors carry `field` and `message`; other errors carry
        `message` only.
      properties:
        field:
          type: string
          description: >-
            Dot path of the invalid field, for example `params.chainId`. Empty
            for the top level.
        message:
          type: string
  securitySchemes:
    ApiKeyId:
      type: apiKey
      in: header
      name: x-api-key-id
      description: >-
        Your API key ID (UUID). See [Sign
        requests](https://docs.olympex.io/authentication/sign-requests).
    ValueInfo:
      type: apiKey
      in: header
      name: x-value-info
      description: >-
        Base64 of `timestamp + "\n" + nonce + "\n" + bodyHash`, where
        `timestamp` is Unix seconds, `nonce` is 24 new hexadecimal characters
        and `bodyHash` is the unpadded base64url SHA-256 of the canonical body.
    Passphrase:
      type: apiKey
      in: header
      name: x-passphrase
      description: Your account passphrase. Treat it like the secret key.
    Signature:
      type: apiKey
      in: header
      name: x-signature
      description: >-
        Lowercase hex HMAC-SHA256 (signature v2), keyed with your secret key
        string (UTF-8, not decoded), of seven lines joined with `\n`, with no
        trailing newline: `OLPX-HMAC-SHA256-V2`, `timestamp`, `nonce`, the
        uppercase method, `path`, `canonicalQuery` and `bodyHash`. `path` is the
        request path including `/api/v1`, without the query string, for example
        `/api/v1/limit-order/<id>`. `canonicalQuery` is the query parameters
        decoded (`+` is a space), sorted by key and then by value, re-encoded
        per RFC 3986 and joined with `&`, or the empty string when there is no
        query. Headers signed for one request are rejected on any other. See
        [Sign requests](https://docs.olympex.io/authentication/sign-requests).

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.