Getting started
What does the Olympex API do?
What does the Olympex API do?
How do I get an API key?
How do I get an API key?
POST /accounts from a terminal or your server with a name of at least 6 characters and a password of at least 8. The response contains your API key ID and your secret key, a random string shown once, and the password becomes your passphrase. The account can call every signed endpoint immediately: there is no activation step.Save the secret key as soon as you receive it: Olympex stores only an encrypted copy and can’t show it again. Create your production account from your server, with a passphrase of at least 24 random characters from a password manager, in printable ASCII with no leading or trailing spaces. See Credentials.Is there a sandbox or testnet?
Is there a sandbox or testnet?
- Quotes, chain checks, and the chain, token, order and strategy reads change nothing.
POST /swapreturns unsigned calldata and never broadcasts it. That calldata is real mainnet calldata, so sending it from a funded wallet moves funds.POST /limit-orderandPOST /dca-order/strategiescreate real orders that Olympex executes against the maker’s allowance. Test them with small amounts from a wallet you control. To test the DCA calls without scheduling orders, create the strategy with"status": "cancelled".
Which chains are supported?
Which chains are supported?
GET /chains for the enabled chain IDs instead of hard-coding them. They are Ethereum (1), Optimism (10), BNB Chain (56), Polygon (137), Base (8453), Arbitrum (42161), Avalanche (43114) and Linea (59144). Cross-chain transfers can start on Ethereum, Optimism, BNB Chain, Polygon, Arbitrum and Avalanche. Limit orders and DCA execute only on the chains listed in The order contract.GET /tokens lists the tokens on each chain. Cache the list, and match tokens by address, never by symbol: symbols aren’t unique, and some carry a suffix such as STRK_1. The list doesn’t limit what you can trade: a quote tells you whether any token address has a route. See Supported chains and tokens.Which liquidity sources does Olympex compare?
Which liquidity sources does Olympex compare?
okx, oneInch, openOceanV3, openOceanV4, zeroExV2AllowanceHolder, uniswapV3Hermes and uniswapV4Hermes, and returns the best route: by default the one with the highest output (orderBy: "MAX_OUT_AMOUNT"). The quote names the winner in aggregatorId and lists every source that quoted in aggregatorOrder, best first. To leave sources out, pass their IDs in excludeMetaAggregatorId. See Aggregation and routing.Which cross-chain providers does Olympex use?
Which cross-chain providers does Olympex use?
okx, rango and liFi. Signed requests from API accounts are quoted and built with okx or rango. The quote’s aggregatorId names the provider and bridgeInfo.displayName names the bridge it chose. The dexHash in the cross-chain /swap response identifies the provider when you track the transfer. See Cross-chain mechanics.Authentication
How does authentication work?
How does authentication work?
x-api-key-id, and the passphrase travels in x-passphrase. The secret key never leaves your server: it keys an HMAC-SHA256 over the method, the path, the canonical query, the timestamp, a single-use nonce and the SHA-256 hash of the canonical request body, which is the empty string for a GET or DELETE. The signature goes in x-signature, and x-value-info carries the timestamp, the nonce and the body hash. POST /accounts is public; every other endpoint is signed. See Authentication overview.Why does my signature fail?
Why does my signature fail?
403 {"message": "Forbidden"} doesn’t say which check failed. The most common causes:- The signed method, path or query isn’t the request you sent. Sign the method in uppercase, the full path starting with
/api/v1, and the canonical query. A signer that signs only the timestamp, the nonce and the body hash, without theOLPX-HMAC-SHA256-V2line, is rejected. - The timestamp is in milliseconds, or your clock is more than 300 seconds from server time. Send Unix time in seconds from a synchronized clock.
- The nonce was used before, usually by a retry that resends the same headers. Sign every attempt again with 24 new hexadecimal characters. In a shell,
OLYMPEX_NONCEorOLYMPEX_TIMESTAMPleft set after testing the known-answer vectors has the same effect: rununset OLYMPEX_NONCE OLYMPEX_TIMESTAMP. - The HMAC is keyed with the decoded secret instead of the secret key string, or the signed message ends with a newline.
- The API key ID or the passphrase is wrong, or the account is inactive.
403 whose envelope carries FORBIDDEN and "Invalid body hash" means the body doesn’t match the signed bodyHash. Hash the canonical JSON (keys sorted at every level, no whitespace) as unpadded base64url, send exactly those bytes, and set Content-Type: application/json. For a GET or DELETE, sign the empty string and send no body. A 401 {"message": "Unauthorized"} means a signing header is missing.On a gateway 401 or 403, sign the request again once with a new nonce. If it fails again, stop and check your credentials and your clock, and if correctly signed requests keep failing, contact partners@olympex.io. Don’t retry an envelope UNAUTHORIZED or FORBIDDEN ("Invalid body hash") unchanged: fix the cause first.The troubleshooting table maps every symptom to its fix, and the known-answer vectors on the same page let you test your implementation offline, with and without a body.Why can't I rotate or revoke a key?
Why can't I rotate or revoke a key?
0. See Credentials.Can I call the API from a browser or a mobile app?
Can I call the API from a browser or a mobile app?
Requests and errors
Why do I get 400 VALIDATION_ERROR?
Why do I get 400 VALIDATION_ERROR?
error.details lists each field at fault with a message, for example {"field": "params.chainId", "message": "Invalid input: expected number, received string"}. The usual causes:chainIdwas sent as a JSON string, such as"137". It is an integer in every request body. See Chain IDs.- An amount, slippage or gas price was sent as a number in a quote or swap, or
slippageorgasPricein a limit order. Send them as decimal strings. DCA strategies are the opposite:totalAmount,slippage,minPriceandmaxPricemust be JSON numbers. - A limit order body includes a field Olympex sets (
status,txHash,executorAddress,reasonFail,allowance,estimateGasoreffectivePriceGas), or anexpiredthat isn’t a Unix timestamp in milliseconds (13 digits), in the future and at most 365 days ahead. - A cross-chain body has a top-level key other than
mode,paramsandfees, such asdryRun. Cross-chain bodies reject unknown top-level keys. GET /tokensgot a query parameter other thanchainId("Invalid query parameters"), or a chain that isn’t enabled ("Chain N is not enabled").- Olympex has no reference price for a limit order’s pair (
"Not exist reference price for this pair A/B"). See Reference price. - The request has no
Content-Type: application/jsonheader, or another type, such as curl’s defaultapplication/x-www-form-urlencoded. The gateway then base64-encodes the body, and the API answers400with"Invalid JSON body"onPOST /accounts, or403with"Invalid body hash"on signed endpoints.
Why do I get 404 Not Found?
Why do I get 404 Not Found?
404 with the code NOT_FOUND and a message that names the method and the path, such as "No route for GET /api/v1/quote", means that no endpoint matches them. Paths start at the base URL, which ends in /api/v1, and they are lowercase and case-sensitive: /support-chain works, /Support-Chain returns 404. Each endpoint accepts only the method its page shows, so a GET /quotes also returns 404.On an {id} path, a 404 whose message names the resource concerns an order or strategy ID. See the next question.Why did I get 404 for an ID?
Why did I get 404 for an ID?
{id} path, a 404 with the code NOT_FOUND means that no limit order, DCA strategy or DCA order with that ID belongs to the API key you signed with. Either the ID doesn’t exist, or another API key created it: Olympex answers the same way in both cases. The message names the resource: "Limit order not found", "DCA strategy not found" or "DCA order not found". A DCA order belongs to the API key that created its strategy.Don’t retry the request unchanged. Check the ID, and sign with the API key that created the order or strategy. The list endpoints return only the orders and strategies of the API key you sign with, so an ID you take from them resolves with that key. See Not found.How long can a request take?
How long can a request take?
500 or 503 with a {"message": …} body instead of the envelope. The first request after a quiet period can also get a gateway 500 {"message": "Internal Server Error"}. Set your client timeout a little above 30 seconds. Retry those responses with backoff, signing each attempt again, except POST /accounts, POST /limit-order and POST /dca-order/strategies: they create a new resource on every success, so check what exists before you send them again. See Errors and retries.Quotes and swaps
What units do amounts use?
What units do amounts use?
amountin a request is a decimal string in human-readable units of the input token:"10"is 10 USDT.outAmount,toTokenAmount,minimumReceivedandminOutAmountare integer strings in base units of the output token:"10034668"is 10.034668 USDC, which has 6 decimals.slippageis a percentage string:"1"is 1%.gasPriceis a gas price hint in whole gwei, rounded up, because some sources reject fractional gwei. On a chain whose gas price is below 1 gwei, that gives"1". See ThegasPricehint.valuein a/swapresponse is the native token amount in wei.
totalAmount, slippage, minPrice and maxPrice as JSON numbers instead. See API conventions.How long does a quote last?
How long does a quote last?
slippage. The calldata from POST /swap carries its own on-chain expiry, 5 minutes on most routes, and is bound to the account it was built for, so broadcast it right after you receive it. Some routes include a market maker’s firm quote that expires within seconds of the build. If you miss the window, request a new quote and a new swap. See Slippage and price impact.Why did my swap transaction revert?
Why did my swap transaction revert?
- The price moved past your slippage. A single-chain swap reverts when it would deliver less than
minOutAmount. Request a new quote and swap. - The calldata expired. On most routes, calldata expires 5 minutes after
/swapbuilds it, and a market maker’s firm quote inside some routes expires within seconds. Broadcast right after you receive it, and build the swap again if it reverts as expired. - The route can’t execute. A
200from/swapdoesn’t guarantee that the calldata executes: a source can build calldata that reverts. Runeth_estimateGasbefore you send. If it reverts while the allowance and the balance are in order, build the swap again with the nextaggregatorIdin the quote’saggregatorOrder, or, for a cross-chain transfer, request a new quote. - Another swap replaced it. Another Olympex swap from the same
accountcan invalidate earlier calldata. Build and send one swap at a time per account. - The allowance is too low. For ERC-20 input, approve the exact amount for
contractToApprovebefore you send. For tokens such as USDT that require it, set the allowance to 0 first. - The gas limit is too low. Estimate gas yourself instead of relying on
gasLimit.
Should I use the gas limit that /swap returns?
Should I use the gas limit that /swap returns?
gasLimit is estimatedGas multiplied by 2, and estimatedGas can be a placeholder of "1500000", "0", or a wei amount on cross-chain routes. Estimate gas with eth_estimateGas and add a buffer, for example 20%. See Gas and fees.How do I track a swap after I broadcast it?
How do I track a swap after I broadcast it?
POST /tx-status with the source-chain transaction hash, the source chainId as an integer, and the dexHash from the cross-chain /swap response in lowercase. Poll with backoff, for example every 15 to 30 seconds. A 500 TX_STATUS_ERROR means the status is unknown, not that the transfer failed: Olympex returns it right after broadcast and also for some transfers the provider marks failed. Keep polling up to a cap you choose, then check the source transaction on a block explorer or contact Support with the requestId.For a single-chain swap, poll GET /transactions/{hash} with the chainId, which returns pending, success, reverted or not_found, or read the transaction receipt from your RPC. See Track a swap to finality.Limit orders and DCA
Can I place limit orders and DCA strategies through the API?
Can I place limit orders and DCA strategies through the API?
- Limit order. Sells
amountofinTokenAddressforoutTokenAddress. The order executes when the market price ofinTokenAddress, inoutTokenAddress, reachespriceTriggeror better. Create one withPOST /limit-order. - DCA strategy. Spends
totalAmountoftokenAddressFrominiterationsequal orders, one everyfrequencyseconds, buyingtokenAddressToon the same chain. Create one withPOST /dca-order/strategies.
What is the difference between a DCA strategy and a DCA order?
What is the difference between a DCA strategy and a DCA order?
totalAmount, iterations, frequency and optional price bounds. DCA orders are its executions. Olympex creates them as the strategy runs, each spending totalAmount / iterations, and there is no endpoint to create one. GET /dca-order/strategies/{id}/orders lists a strategy’s orders, oldest first.To stop a strategy, send PATCH /dca-order/strategies/{id} with {"status":"cancelled"}, which can’t be undone, and lower the maker’s allowance to the order contract. DCA orders are read-only: no endpoint changes or cancels one. See Cancel a strategy.Who is the maker, and which wallets can be one?
Who is the maker, and which wallets can be one?
accountTo. It sells the token, receives the output, signs the token pair and approves the order contract. 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.Send accountTo in EIP-55 checksummed form everywhere. Olympex stores it as you sent it, and the ?accountTo= filter on the list endpoints matches case-sensitively.Which contract do I approve, and for how much?
Which contract do I approve, and for how much?
contractToApprove that POST /swap returns, which is for swaps.- Limit order:
amount, plus the execution gas cost in the token sold, plus a buffer. Estimate the gas cost with a single-chainPOST /quotesfor the same pair and amount with"includeGasInfo": true:dataFeeTransaction.transactionFeeInToken. - DCA strategy:
totalAmount. Its execution gas comes out of the token bought. - Several orders: orders that sell the same token on the same chain share one allowance, so approve the sum.
0. See How much to approve.Which tokens can't be sold in limit orders or DCA?
Which tokens can't be sold in limit orders or DCA?
- Native tokens. The token sold must be an ERC-20: wrap first, and sell WETH, WBNB or WPOL. Token addresses lists their addresses.
- ERC-20 tokens whose
transferandapprovedon’t return a boolean. USDT on Ethereum isn’t supported as the token you sell in limit orders or DCA on Ethereum. - Fee-on-transfer tokens.
Why does creating a limit order fail with 'Not exist reference price'?
Why does creating a limit order fail with 'Not exist reference price'?
POST /limit-order returns 400 VALIDATION_ERROR with "Not exist reference price for this pair A/B", where A/B are the symbols you sent, and no order is created.Send each token’s real symbol in tokenASymbol (the token you sell) and tokenBSymbol (the token you buy). Read symbol() from the token contract, or take the symbol from GET /tokens by address, trimmed and without a trailing _<number> (STRK for STRK_1). Check that the addresses are token contracts on that chain. The error can also be temporary, so retry later with backoff before you rule the pair out.Olympex doesn’t check the symbols against the token contracts, so check the ones the response returns. Responses can return normalized symbols, such as ETH for WETH. Cancel an order whose symbols match neither your tokens nor their normalized forms. See Reference price.How do I know when an order executes?
How do I know when an order executes?
- Limit order.
GET /limit-order/{id}returns itsstatus:pending, thenexecutingorsubmitted, thencompletedwithtxHash. It can also end asfailed, withreasonFail[], orcancelled. - DCA.
GET /dca-order/strategies/{id}/ordersreturns each order’sstatus. Asuccessfulorder carriestransactionHash,amountReceivedandexecutionPrice. The strategy’sstatusbecomesfinishedwhen every order has run.
What can I change after I create an order?
What can I change after I create an order?
- Limit order. Only while it is
pending.PATCH /limit-order/{id}changespriceTriggerandprice,amount,expired,slippageorgasPrice, andDELETE /limit-order/{id}cancels the order, which stays readable. Once the order isn’tpending, both return409 CONFLICT. - DCA strategy. With
PATCH /dca-order/strategies/{id}: itsminPriceandmaxPrice, or itsstatusto cancel it.
Can I retry a create call that timed out?
Can I retry a create call that timed out?
POST /limit-order or POST /dca-order/strategies creates a new order or strategy, and Olympex ignores any id you send. After a timeout, list your orders with GET /limit-order?accountTo=<maker>, or your strategies with GET /dca-order/strategies?accountTo=<maker>, and look for a match on your own fields before you send the call again.GET, PATCH and DELETE requests are safe to repeat. A repeated DELETE /limit-order/{id} returns 409 CONFLICT once the first call has cancelled the order. See Requests that create a resource.Can I sign fractional numbers, such as DCA price bounds?
Can I sign fractional numbers, such as DCA price bounds?
totalAmount, slippage, minPrice and maxPrice as JSON numbers, and bounds such as a minPrice of 0.00025 are fractional. The reference signers in TypeScript and Python, and the API console, canonicalize numbers the way JavaScript does, so these values sign correctly.If you write your own signer in another language, format numbers exactly as JavaScript’s JSON.stringify does: 1.0 becomes 1, 1e21 becomes 1e+21, and 0.0000001 becomes 1e-7. Keep integers within ±(253 − 1). A number formatted differently changes the body hash, and the request fails with 403 FORBIDDEN "Invalid body hash". See Portability rules.Fees
Does Olympex charge a fee?
Does Olympex charge a fee?
integratorFeeBreakdown, which reports the Olympex protocol fee next to yours. The protocol fee applies even when you send no fees, and integratorMarginBps is then 0. protocolFeeBps is the rate in basis points and can be fractional (the examples show 15, which is 0.15%), and protocolFeeAmount is the amount in base units. Read the rate from each response instead of hard-coding it.For swaps, gas is paid by the sending wallet in the chain’s native token, and none of it goes to Olympex. For limit orders and DCA, Olympex pays the execution gas and is reimbursed from the maker: in the token sold, on top of amount, for a limit order, and out of the token bought for each DCA order. See Gas and fees.Can I charge my own fee?
Can I charge my own fee?
fees object to POST /quotes and POST /swap. feeBps is an integer from 0 to 100 basis points, where 100 is 1%. feeRecipient is the EVM address that receives your fee: it is required when feeBps is greater than 0, and the zero address is rejected. Fees apply only to signed requests from API accounts. Send the same fees object on the quote and the swap, so the quote you show matches the calldata you send. Limit orders and DCA strategies don’t take a fees object. See Gas and fees.Limits and tools
Are there rate limits?
Are there rate limits?
500 and 503 responses with exponential backoff and jitter, signing each attempt again, and cap how many requests you send in parallel. The API gateway can answer 429 {"message": "Too Many Requests"} when it receives too many requests in a short time: wait, back off and send fewer requests in parallel. See Limits.Where is the OpenAPI specification?
Where is the OpenAPI specification?
https://docs.olympex.io/api-reference/openapi.json. It is curated from the live service and includes the gateway’s own error responses. Most response examples, including every /quotes and /swap example, are captured from the live API; the /tx-status success example is illustrative. Every endpoint page in the API reference is generated from it. The service also serves its own spec at GET /openapi.json and Swagger UI at GET /docs; build against the curated spec instead. See OpenAPI specification.Is there an SDK?
Is there an SDK?
The API console says the browser blocked the response. What now?
The API console says the browser blocked the response. What now?
-i to the command (or -D -) to see the HTTP status and the response headers, including apigw-requestid. To create a key, follow Create a key from a terminal. Use a test API key in the console, never production credentials. See API console.What should I include when I contact support?
What should I include when I contact support?
meta.requestId of the failing response (for a gateway response, its apigw-requestid header), the endpoint, the time of the request in UTC, and the request body without credentials. For a limit order or a DCA strategy, add its id, the chain ID and the maker address. Never send the secret key or the passphrase. Support lists everything that helps.