Skip to main content
POST
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.

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 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 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. 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 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.
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.
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

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 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.
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.
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 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 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 never repeat this call on their own. After you create the order, poll GET /limit-order/{id} to follow its status. Change a pending order with PATCH /limit-order/{id}, and cancel it with DELETE /limit-order/{id}. The Place a limit order guide walks through the whole flow.

Authorizations

x-api-key-id
string
header
required

Your API key ID (UUID). See Sign requests.

x-value-info
string
header
required

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.

x-passphrase
string
header
required

Your account passphrase. Treat it like the secret key.

x-signature
string
header
required

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.

Body

application/json

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.

accountTo
string
required

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").

Minimum string length: 1
chainId
integer
required

Chain of both tokens, as an integer such as 137. Use a chain from GET /chains. A string returns 400 VALIDATION_ERROR.

Required range: 0 < x <= 9007199254740991
gasPrice
string
required

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.

Minimum string length: 1
inTokenAddress
string
required

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").

Minimum string length: 1
outTokenAddress
string
required

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").

Minimum string length: 1
slippage
string
required

Maximum slippage at execution, in percent, as a decimal string ("1" is 1%).

Minimum string length: 1
tokenASymbol
string
required

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).

Minimum string length: 1
tokenBSymbol
string
required

Symbol of outTokenAddress, for example USDC.

Minimum string length: 1
amount
required

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.

Minimum string length: 1
priceTrigger
required

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.

Minimum string length: 1
expired
string
required

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
string
required

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.

Minimum string length: 1
price

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.

Response

The order, as stored.

success
enum<boolean>
required
Available options:
true
data
object
required

A limit order. Olympex can add fields; ignore the ones you don't use.

meta
object
required