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

# FAQ

> Answers to common questions about Olympex API keys, request signing, quotes, swaps, limit orders, DCA, fees and limits.

Short answers to the questions integrators ask most, each with a link to the page that covers the topic in full. If your question isn't here, see [Support](/resources/support).

## Getting started

<AccordionGroup>
  <Accordion title="What does the Olympex API do?">
    The Olympex REST API returns the best route Olympex finds across its liquidity sources for a swap on one chain or a transfer between two chains, builds the unsigned transaction calldata for that route, and reports the status of transactions and cross-chain transfers. It also runs limit orders and DCA strategies, which Olympex executes from the maker's wallet, and lists the enabled chains and the tokens on each one.

    Olympex never holds your keys. For swaps, your wallet signs and broadcasts every transaction. For limit orders and DCA, the maker signs each token pair once and approves the Olympex order contract, and that allowance caps what the orders can spend. See [How Olympex works](/concepts/how-olympex-works).
  </Accordion>

  <Accordion title="How do I get an API key?">
    Create a test API key in one click on [Create a test API key](/get-started/create-an-api-key), or call [`POST /accounts`](/api-reference/accounts/create-account) from [a terminal](/get-started/create-an-api-key#create-a-key-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](/authentication/credentials).
  </Accordion>

  <Accordion title="Is there a sandbox or testnet?">
    No. Every API key, including a test key created from these docs, is a real account on the live API, and quotes use live prices.

    * Quotes, chain checks, and the chain, token, order and strategy reads change nothing.
    * [`POST /swap`](/api-reference/swap/build-swap) returns unsigned calldata and never broadcasts it. That calldata is real mainnet calldata, so sending it from a funded wallet moves funds.
    * [`POST /limit-order`](/api-reference/limit-orders/create-limit-order) and [`POST /dca-order/strategies`](/api-reference/dca/create-dca-strategy) create 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"`.
  </Accordion>

  <Accordion title="Which chains are supported?">
    Call [`GET /chains`](/api-reference/chains/list-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](/concepts/order-authorization#the-order-contract).

    [`GET /tokens`](/api-reference/tokens/list-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](/concepts/supported-chains).
  </Accordion>

  <Accordion title="Which liquidity sources does Olympex compare?">
    For single-chain swaps, Olympex requests quotes from `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](/concepts/aggregation-and-routing).
  </Accordion>

  <Accordion title="Which cross-chain providers does Olympex use?">
    The cross-chain providers are `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](/concepts/cross-chain-mechanics).
  </Accordion>
</AccordionGroup>

## Authentication

<AccordionGroup>
  <Accordion title="How does authentication work?">
    Signed endpoints take four headers built from three credentials. The API key ID identifies your account in `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](/authentication/overview).
  </Accordion>

  <Accordion title="Why does my signature fail?">
    The gateway's `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](/authentication/sign-requests#canonical-query). A signer that signs only the timestamp, the nonce and the body hash, without the `OLPX-HMAC-SHA256-V2` line, 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_NONCE` or `OLYMPEX_TIMESTAMP` left set after testing the known-answer vectors has the same effect: run `unset 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.

    A `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](mailto:partners@olympex.io). Don't retry an envelope `UNAUTHORIZED` or `FORBIDDEN` (`"Invalid body hash"`) unchanged: fix the cause first.

    The [troubleshooting table](/authentication/sign-requests#troubleshooting) 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.
  </Accordion>

  <Accordion title="Why can't I rotate or revoke a key?">
    API accounts have no rotation, revocation, deletion, scope or expiry features, so credentials stay valid until Olympex deactivates the account. To replace credentials, create a new account, move your integration to it, then ask [partners@olympex.io](mailto:partners@olympex.io) to deactivate the old account. Limit orders and DCA strategies belong to the API key that created them, and the new account can't read, change or cancel them. Manage the old account's open orders and strategies with its own credentials, and cancel them or let them finish before you ask to deactivate it.

    If a secret key or a passphrase leaks, email [partners@olympex.io](mailto:partners@olympex.io) right away and ask to deactivate the account. Include the API key ID, never the secret key or the passphrase. If the account has open limit orders or DCA strategies, also set each maker's allowance to the order contract to `0`. See [Credentials](/authentication/credentials).
  </Accordion>

  <Accordion title="Can I call the API from a browser or a mobile app?">
    Call signed endpoints from your server. Signing needs the secret key and the passphrase, and an app that ships them to users' devices publishes them. Browsers also enforce the API's CORS policy, which allows only specific origins. See [Security model](/concepts/security-model).

    The order signature for limit orders and DCA is different: it comes from the maker's wallet, not from your API credentials. Your app can ask the user's wallet for it in the browser and send it to your server, which creates the order. See [Sign a pair](/concepts/order-authorization#sign-a-pair).
  </Accordion>
</AccordionGroup>

## Requests and errors

<AccordionGroup>
  <Accordion title="Why do I get 400 VALIDATION_ERROR?">
    A field or query parameter is missing, has the wrong type or is out of range. `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:

    * `chainId` was sent as a JSON string, such as `"137"`. It is an integer in every request body. See [Chain IDs](/api-reference/conventions#chain-ids).
    * An amount, slippage or gas price was sent as a number in a quote or swap, or `slippage` or `gasPrice` in a limit order. Send them as decimal strings. DCA strategies are the opposite: `totalAmount`, `slippage`, `minPrice` and `maxPrice` must be JSON numbers.
    * A limit order body includes a field Olympex sets (`status`, `txHash`, `executorAddress`, `reasonFail`, `allowance`, `estimateGas` or `effectivePriceGas`), or an `expired` that 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`, `params` and `fees`, such as `dryRun`. Cross-chain bodies reject unknown top-level keys.
    * `GET /tokens` got a query parameter other than `chainId` (`"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](/concepts/limit-orders#reference-price).
    * The request has no `Content-Type: application/json` header, or another type, such as curl's default `application/x-www-form-urlencoded`. The gateway then base64-encodes the body, and the API answers `400` with `"Invalid JSON body"` on `POST /accounts`, or `403` with `"Invalid body hash"` on signed endpoints.

    Fix the fields and send again; an unchanged request fails the same way. See [API conventions](/api-reference/conventions).
  </Accordion>

  <Accordion title="Why do I get 404 Not Found?">
    A `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](/api-reference/overview#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.
  </Accordion>

  <Accordion title="Why did I get 404 for an ID?">
    On an `{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](/api-reference/conventions#not-found).
  </Accordion>

  <Accordion title="How long can a request take?">
    The API gateway stops a request after about 30 seconds and returns `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](/authentication/errors-and-retries).
  </Accordion>
</AccordionGroup>

## Quotes and swaps

<AccordionGroup>
  <Accordion title="What units do amounts use?">
    * `amount` in a request is a decimal string in human-readable units of the input token: `"10"` is 10 USDT.
    * `outAmount`, `toTokenAmount`, `minimumReceived` and `minOutAmount` are integer strings in base units of the output token: `"10034668"` is 10.034668 USDC, which has 6 decimals.
    * `slippage` is a percentage string: `"1"` is 1%.
    * `gasPrice` is 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 [The `gasPrice` hint](/concepts/gas-and-fees#the-gasprice-hint).
    * `value` in a `/swap` response is the native token amount in wei.

    Quote, swap and limit-order amounts, prices and slippage are decimal strings. DCA strategies take `totalAmount`, `slippage`, `minPrice` and `maxPrice` as JSON numbers instead. See [API conventions](/api-reference/conventions#amounts).
  </Accordion>

  <Accordion title="How long does a quote last?">
    A quote isn't reserved. Prices keep moving, so request the swap right after the quote and protect it with `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](/concepts/slippage-and-price-impact).
  </Accordion>

  <Accordion title="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 `/swap` builds 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 `200` from `/swap` doesn't guarantee that the calldata executes: a source can build calldata that reverts. Run `eth_estimateGas` before you send. If it reverts while the allowance and the balance are in order, build the swap again with the next `aggregatorId` in the quote's `aggregatorOrder`, or, for a cross-chain transfer, request a new quote.
    * **Another swap replaced it.** Another Olympex swap from the same `account` can 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 `contractToApprove` before 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`.

    See [Execute a swap](/guides/execute-a-swap).
  </Accordion>

  <Accordion title="Should I use the gas limit that /swap returns?">
    Only as a fallback. `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](/concepts/gas-and-fees).
  </Accordion>

  <Accordion title="How do I track a swap after I broadcast it?">
    For a cross-chain transfer, call [`POST /tx-status`](/api-reference/transactions/get-transaction-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](/resources/support) with the `requestId`.

    For a single-chain swap, poll [`GET /transactions/{hash}`](/api-reference/transactions/get-transaction) 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](/guides/track-a-swap-to-finality).
  </Accordion>
</AccordionGroup>

## Limit orders and DCA

<AccordionGroup>
  <Accordion title="Can I place limit orders and DCA strategies through the API?">
    Yes. Olympex executes both from the maker's wallet, and nothing moves when you create them.

    * **Limit order.** Sells `amount` of `inTokenAddress` for `outTokenAddress`. The order executes when the market price of `inTokenAddress`, in `outTokenAddress`, reaches `priceTrigger` or better. Create one with [`POST /limit-order`](/api-reference/limit-orders/create-limit-order).
    * **DCA strategy.** Spends `totalAmount` of `tokenAddressFrom` in `iterations` equal orders, one every `frequency` seconds, buying `tokenAddressTo` on the same chain. Create one with [`POST /dca-order/strategies`](/api-reference/dca/create-dca-strategy).

    Both need an order signature and an allowance from the maker. See [Limit orders](/concepts/limit-orders), [DCA strategies](/concepts/dca), and the guides [Place a limit order](/guides/create-a-limit-order) and [Run a DCA strategy](/guides/build-a-dca-strategy).
  </Accordion>

  <Accordion title="What is the difference between a DCA strategy and a DCA order?">
    The strategy is the plan you create: the tokens, `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`](/api-reference/dca/list-dca-strategy-orders) lists a strategy's orders, oldest first.

    To stop a strategy, send [`PATCH /dca-order/strategies/{id}`](/api-reference/dca/update-dca-strategy) 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](/concepts/dca#cancel-a-strategy).
  </Accordion>

  <Accordion title="Who is the maker, and which wallets can be one?">
    The maker is the wallet in `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.
  </Accordion>

  <Accordion title="What does the order signature authorize?">
    The maker signs `keccak256(abi.encodePacked(maker, maker, tokenIn, tokenOut))` once per token pair, with EIP-191 `personal_sign` over the 32 raw bytes, not over the hex string. The signature lets the Olympex order contract execute swaps of `tokenIn` for `tokenOut` from the maker's wallet.

    * It doesn't bind an amount, price, expiry, chain or order: Olympex enforces those when it executes.
    * It stays valid after you cancel an order, and the same signature serves limit orders and DCA for that pair.
    * Olympex doesn't check it when you create an order, and a wrong signature makes execution fail later. Recover the signer and compare it with the maker before you send it.

    Your allowance to the order contract is the on-chain limit on what orders can spend. See [Order signatures and allowances](/concepts/order-authorization).
  </Accordion>

  <Accordion title="Which contract do I approve, and for how much?">
    Approve the Olympex order contract for the chain, listed in [The order contract](/concepts/order-authorization#the-order-contract). It isn't the `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-chain `POST /quotes` for 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.

    Never approve an unlimited amount. Cancelling an order doesn't change the allowance. To stop every order that sells a token, set the allowance to `0`. See [How much to approve](/concepts/order-authorization#how-much-to-approve).
  </Accordion>

  <Accordion title="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](/concepts/supported-chains#token-addresses) lists their addresses.
    * **ERC-20 tokens whose `transfer` and `approve` don'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.**

    The create call can accept an order that sells one of these, and that order can't execute, so check the token before you create the order. See [What can't be sold](/concepts/limit-orders#what-cant-be-sold).
  </Accordion>

  <Accordion title="Why does creating a limit order fail with 'Not exist reference price'?">
    Olympex needs a reference price for the pair. It reuses a recent lookup for the same chain and token addresses, or looks up a market for the two symbols, or identifies the tokens by address. When all of these fail, `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`](/api-reference/tokens/list-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](/concepts/limit-orders#reference-price).
  </Accordion>

  <Accordion title="How do I know when an order executes?">
    Poll. The API doesn't push status changes.

    * **Limit order.** [`GET /limit-order/{id}`](/api-reference/limit-orders/get-limit-order) returns its `status`: `pending`, then `executing` or `submitted`, then `completed` with `txHash`. It can also end as `failed`, with `reasonFail[]`, or `cancelled`.
    * **DCA.** [`GET /dca-order/strategies/{id}/orders`](/api-reference/dca/list-dca-strategy-orders) returns each order's `status`. A `successful` order carries `transactionHash`, `amountReceived` and `executionPrice`. The strategy's `status` becomes `finished` when every order has run.

    Treat a status you don't recognize as not final.
  </Accordion>

  <Accordion title="What can I change after I create an order?">
    * **Limit order.** Only while it is `pending`. [`PATCH /limit-order/{id}`](/api-reference/limit-orders/update-limit-order) changes `priceTrigger` and `price`, `amount`, `expired`, `slippage` or `gasPrice`, and [`DELETE /limit-order/{id}`](/api-reference/limit-orders/cancel-limit-order) cancels the order, which stays readable. Once the order isn't `pending`, both return `409 CONFLICT`.
    * **DCA strategy.** With [`PATCH /dca-order/strategies/{id}`](/api-reference/dca/update-dca-strategy): its `minPrice` and `maxPrice`, or its `status` to cancel it.

    To change anything else, such as the tokens, the chain or the maker, cancel and create a new order or strategy. If you change an amount, set the allowance to match.
  </Accordion>

  <Accordion title="Can I retry a create call that timed out?">
    Not blindly. Each successful `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](/authentication/errors-and-retries#requests-that-create-a-resource).
  </Accordion>

  <Accordion title="Can I sign fractional numbers, such as DCA price bounds?">
    Yes. DCA strategies take `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 ±(2<sup>53</sup> − 1). A number formatted differently changes the body hash, and the request fails with `403 FORBIDDEN` `"Invalid body hash"`. See [Portability rules](/authentication/sign-requests#portability-rules).
  </Accordion>
</AccordionGroup>

## Fees

<AccordionGroup>
  <Accordion title="Does Olympex charge a fee?">
    Pricing and commercial terms are agreed with Olympex: contact [partners@olympex.io](mailto:partners@olympex.io). Every quote for an API account carries `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](/concepts/gas-and-fees).
  </Accordion>

  <Accordion title="Can I charge my own fee?">
    Yes, on swaps. Add a top-level `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](/concepts/gas-and-fees).
  </Accordion>
</AccordionGroup>

## Limits and tools

<AccordionGroup>
  <Accordion title="Are there rate limits?">
    Olympex doesn't publish per-key rate limits or quotas, and responses carry no rate-limit headers. That doesn't make capacity unlimited: tell [partners@olympex.io](mailto:partners@olympex.io) your expected volume before you launch, retry `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](/authentication/limits#rate-limits-and-quotas).
  </Accordion>

  <Accordion title="Where is the OpenAPI specification?">
    Download it from `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](/api-reference/openapi-spec).
  </Accordion>

  <Accordion title="Is there an SDK?">
    There is no SDK package. Generate a typed client from the [OpenAPI specification](/api-reference/openapi-spec) and add a signer to it, or use the reference implementations in TypeScript, Python and bash on [Sign requests](/authentication/sign-requests).
  </Accordion>

  <Accordion title="The API console says the browser blocked the response. What now?">
    The browser couldn't read the API's response. Usually the API's CORS policy doesn't allow the origin you're browsing from, or the gateway rejected the request without CORS headers. Click **Copy as cURL** and run the command in a terminal: it sends the same signed request. Add `-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](/get-started/create-an-api-key#create-a-key-from-a-terminal). Use a test API key in the console, never production credentials. See [API console](/api-reference/console).
  </Accordion>

  <Accordion title="What should I include when I contact support?">
    The `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](/resources/support) lists everything that helps.
  </Accordion>
</AccordionGroup>

## Related

<CardGroup cols={2}>
  <Card title="Quickstart" icon="bolt" href="/get-started/quickstart">
    Send your first signed request.
  </Card>

  <Card title="Sign requests" icon="code" href="/authentication/sign-requests">
    The signing algorithm, reference code and troubleshooting.
  </Card>

  <Card title="Glossary" icon="book" href="/resources/glossary">
    Definitions of the terms used across the docs.
  </Card>

  <Card title="Support" icon="life-ring" href="/resources/support">
    How to contact Olympex and what to include.
  </Card>
</CardGroup>


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