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

# API console

> Sign and send requests to every signed Olympex endpoint from your browser, inspect every signing value, and create a test API key.

The API console signs each request in your browser with the Web Crypto API and sends it straight to the Olympex API, with no docs proxy in between. Use it to explore the endpoints, reproduce an error and get its `requestId`, or check your own signer against headers you know are correct.

If your browser blocks the request, use [Copy as cURL](#copy-as-curl) to send the same signed request from a terminal. `PATCH` and `DELETE` requests may need it. To create a key without the browser, see [Create a test API key](/get-started/create-an-api-key#create-a-key-from-a-terminal).

This page hosts an interactive console for people using a browser. To call the API from code, sign each request as described in [Sign requests](/authentication/sign-requests). The [API reference overview](/api-reference/overview) lists every endpoint.

<Info>
  You need an API key ID, a secret key and a passphrase. No key yet? [Create a test API key](#create-a-test-api-key) on this page.
</Info>

## Explore safely

The console runs on a page hosted by Mintlify that loads analytics. Treat anything you type here as visible to the page.

<Warning>
  Use a test API key made for exploring, never production credentials. There is no way to rotate or revoke a key: if a key leaks, email [partners@olympex.io](mailto:partners@olympex.io) to deactivate the account, then create a new one.
</Warning>

A test key calls the same production API as any other key. Quotes use live prices, `POST /swap` returns real mainnet calldata, and the limit orders and DCA strategies you create are real orders.

<Warning>
  The console never broadcasts a transaction, but what it returns and creates is real. Swap calldata moves funds if you sign and send it from a funded wallet. Olympex executes the limit orders and DCA strategies you create here from the maker wallet, up to the allowance that wallet granted to the Olympex order contract.
</Warning>

Creating a limit order or a DCA strategy needs the maker wallet's signature for the token pair. The create examples start with a placeholder `signature`, and **Send request** and **Copy as cURL** stay disabled until `signature` is a 65-byte hex signature (`0x` and 130 hexadecimal characters). Click **Sign with wallet**: your browser wallet signs the pair, and the console fills in `accountTo` with the wallet's address and `signature` with its signature. Signing doesn't grant an allowance or move funds. Without a browser wallet, sign the pair with your own tooling, as shown in [Order signatures and allowances](/concepts/order-authorization), and paste the signature. Olympex doesn't check the signature when you create an order: a wrong signature is accepted, and the order fails at execution. To try `POST /dca-order/strategies` without scheduling orders, add `"status": "cancelled"` to the body: the strategy is created stopped. Cancel what you don't need: a limit order with `DELETE /limit-order/{id}`, a DCA strategy with `PATCH /dca-order/strategies/{id}` and `{"status":"cancelled"}`.

The console keeps the secret key and the passphrase in this tab's memory only, and masks them on screen until you choose to show them, for example with **Reveal** on a key you just created.

| Value | Where it lives | Cleared when |
| - | - | - |
| API key ID | This tab's memory, and the browser's session storage so it survives a reload | You click **Clear** or close the tab |
| Secret key | This tab's memory only | You reload the page or click **Clear** |
| Passphrase | This tab's memory only | You reload the page or click **Clear** |

* Enter your credentials once: every console on this site uses them, including the **Try it** panel on each signed endpoint page, until you reload.
* The response panel hides credential values, such as `passphrase`, `password` and `secretKey` fields.
* **Copy as cURL** never includes your passphrase. The copied command reads it from `$OLYMPEX_PASSPHRASE`, and stops with a message before it sends anything if the variable isn't set.

## Send a request

<Steps>
  <Step title="Add your credentials">
    Enter your API key ID, secret key and passphrase, or open **No key yet? Create a test API key** to create one without leaving the console.
  </Step>

  <Step title="Choose an endpoint and an example">
    Pick an endpoint, then an example. Fill in the path and query parameters, such as an order ID or `chainId`. For `POST` and `PATCH`, edit the JSON body as you like: the console sends it as canonical JSON (keys sorted, no whitespace), which is exactly what `bodyHash` covers. The signature also covers the method, the path and the query. For `POST /limit-order` and `POST /dca-order/strategies`, click **Sign with wallet** before you send.
  </Step>

  <Step title="Send the request">
    Click **Send request**. The console signs the method, the path, the query and the body, or the empty string for `GET` and `DELETE`, with a new timestamp and nonce, calls the API, and shows the response.
  </Step>

  <Step title="Reuse it outside the browser">
    Click **Copy as cURL** to run the same signed request from a terminal. See [Copy as cURL](#copy-as-curl).
  </Step>
</Steps>

The console covers every signed endpoint, grouped into swaps, chains and tokens, limit orders and DCA. `POST /accounts` is available through [Create a test API key](#create-a-test-api-key).

| Group | Endpoints | Examples |
| - | - | - |
| Swaps | [`POST /quotes`](/api-reference/quotes/get-quote), [`POST /swap`](/api-reference/swap/build-swap), [`POST /tx-status`](/api-reference/transactions/get-transaction-status), [`GET /transactions/{hash}`](/api-reference/transactions/get-transaction) | 10 USDT to USDC on Polygon, with and without `includeGasInfo`, and 10 USDT on Polygon to USDT on Ethereum. For `/swap`, set `aggregatorId` to the value your quote returned: the presets use `oneInch` and `rango`. For `/tx-status`, replace `hash` with the source-chain transaction you broadcast and `dexHash` with the value from your cross-chain `/swap` response. For `/transactions/{hash}`, replace `hash` with a transaction you broadcast. |
| Chains and tokens | [`GET /chains`](/api-reference/chains/list-chains), [`GET /tokens`](/api-reference/tokens/list-tokens), [`POST /support-chain`](/api-reference/chains/check-chain-support) | The tokens on Polygon, Ethereum and BNB Chain. Chain support for Polygon (`137`), which returns `true`, and zkSync Era (`324`), which returns `false`. |
| Limit orders | [`GET /limit-order`](/api-reference/limit-orders/list-limit-orders), [`POST /limit-order`](/api-reference/limit-orders/create-limit-order), [`GET`](/api-reference/limit-orders/get-limit-order), [`PATCH`](/api-reference/limit-orders/update-limit-order) and [`DELETE /limit-order/{id}`](/api-reference/limit-orders/cancel-limit-order) | Every order for your API key, or the pending ones on Polygon. An order that sells WETH for USDC on Polygon. A new trigger price. |
| DCA | [`GET`](/api-reference/dca/list-dca-strategies) and [`POST /dca-order/strategies`](/api-reference/dca/create-dca-strategy), [`GET`](/api-reference/dca/get-dca-strategy) and [`PATCH /dca-order/strategies/{id}`](/api-reference/dca/update-dca-strategy), [`GET /dca-order/strategies/{id}/orders`](/api-reference/dca/list-dca-strategy-orders), [`GET /dca-order/orders/{id}`](/api-reference/dca/get-dca-order) | Every strategy for your API key, or the active ones. A strategy that buys WETH with 100 USDC in 10 orders on Polygon. Cancelling a strategy. |

### IDs fill in for you

Endpoints with `{id}` in the path have an ID field. You don't have to copy IDs by hand: when a create or list response returns a limit order, a DCA strategy or a DCA order, the console fills its ID into the ID field of every console for that resource, until you reload.

| Response | Fills in |
| - | - |
| `POST /limit-order`, `GET /limit-order` | The limit order ID |
| `POST /dca-order/strategies`, `GET /dca-order/strategies` | The DCA strategy ID |
| `GET /dca-order/strategies/{id}/orders` | The DCA order ID |

A list fills in the ID of its first item. Check the ID before you send a `PATCH` or `DELETE`.

### Read the response

* **Status line.** The HTTP status, the round-trip time, and `meta.requestId` when Olympex answered. **Gateway response** marks a `message`-only body from the API gateway. [Conventions](/api-reference/conventions#gateway-responses) explains each one.
* **Filled-in ID.** When the response filled in an ID for other consoles, a line under the status names it.
* **Hint.** For an error, a one-line explanation of the likely cause and the fix.
* **Body.** The full response, with credential fields hidden.

Keep the `requestId` of any response you want to ask about: support needs it to find your request. A **Gateway response** has no `requestId`, and the browser can't read the `apigw-requestid` header that identifies it. Click **Copy as cURL**, add `-i` right after `curl` so that curl prints the response headers, and run the command in a terminal. Send support the `apigw-requestid` value from that response, with the time of the request in UTC.

## Create a test API key

This creates a real API account with `POST /accounts`. It suggests a name (`docs-test-` and eight random hexadecimal characters) that you can change, and generates a 32-character random passphrase in your browser.

When the account is created, the console shows the API key ID, the secret key, the passphrase and the request's `requestId`, and loads them into every console on this site until you reload. **Copy as .env** and **Download .env** give you the three `OLYMPEX_*` variables that the [reference signers](/authentication/sign-requests) read.

<Warning>
  Save the secret key and the passphrase before you leave or reload the page. Olympex stores only a hash of the passphrase and an encrypted copy of the secret key, so it can't show either one again.
</Warning>

If the browser blocks the call, the console shows a terminal command that creates the same account, with the name exactly as you entered it. The command prompts for the passphrase without echoing it: copy the generated passphrase with its own button and paste it at the prompt, so it stays out of the command and your shell history. The response, secret key included, prints in your terminal: store the credentials right away, then clear the terminal. [Create a test API key](/get-started/create-an-api-key#create-a-key-from-a-terminal) covers creating credentials from a terminal and storing them.

## Copy as cURL

**Copy as cURL** signs the current request and copies a `curl` command for bash or zsh, with the method, the path and query string, and the body for `POST` and `PATCH`. `PATCH` and `DELETE` requests may need it: if your browser blocks the request, run the copied command from a terminal.

The command carries the signed headers as literals and reads your passphrase from the environment, so set `OLYMPEX_PASSPHRASE` first. If it isn't set, the command stops with `set OLYMPEX_PASSPHRASE first` before it sends anything. Setting it this way keeps the passphrase off the screen and out of your shell history:

```bash theme={null}
# Prompts without echoing, then exports the passphrase for the copied command.
read -rs OLYMPEX_PASSPHRASE && export OLYMPEX_PASSPHRASE
```

Each copied command works once. The server accepts its timestamp for 300 seconds and rejects its nonce once it has been used, so copy again for every run. The comment at the top of the command shows, in UTC, when it was signed and when it stops working.

The command prints the response body only. To also see the status line and the response headers, such as `apigw-requestid`, add `-i` right after `curl` (`curl -i -sS …`), or `-D -` in the same place.

<Tip>
  Copy as cURL is the quickest way to rule out the browser. If the command succeeds in a terminal but **Send request** fails, the problem is on the browser side, such as CORS.
</Tip>

## Signing details

After you send or copy a request, **Signing details** lists every value the console computed, so you can compare them with your own signer:

| Value | What it is |
| - | - |
| Method and path | The method and the URL path that were signed, for example `GET /api/v1/tokens`. |
| Canonical query | The query as signed: sorted by key, then by value, and percent-encoded per RFC 3986. Empty when there is no query. |
| Canonical body | The exact string that was hashed and sent. Empty for `GET` and `DELETE`. |
| `bodyHash` | Unpadded base64url SHA-256 of the canonical body. |
| `timestamp` | Unix time in seconds. |
| `nonce` | 24 random hexadecimal characters. |
| `x-value-info` | Standard base64 of `timestamp`, `nonce` and `bodyHash` joined with newlines. |
| `x-signature` | Lowercase hex HMAC-SHA256 of the signed message (`OLPX-HMAC-SHA256-V2`, `timestamp`, `nonce`, the method, the path, the canonical query and `bodyHash`), keyed with your secret key. |

The passphrase is sent as `x-passphrase` and is not shown. To compare, sign the same method, URL and body with the same credentials, timestamp and nonce in your code:

<CodeGroup>
  ```ts TypeScript theme={null}
  import { OLYMPEX_BASE_URL, credentialsFromEnv, signRequest } from "./sign-request.ts"; // /authentication/sign-requests

  // Paste the method and URL you sent, and the canonical body, timestamp and nonce from the Signing details panel.
  const body = JSON.parse('{"chainId":137}'); // the canonical body; undefined for GET and DELETE
  const signed = signRequest("POST", `${OLYMPEX_BASE_URL}/support-chain`, body, credentialsFromEnv(), {
    timestamp: "1758700000",
    nonce: "0123456789abcdef01234567",
  });
  console.log(signed.path, signed.query, signed.bodyString, signed.bodyHash, signed.headers["x-value-info"], signed.headers["x-signature"]);
  ```

  ```python Python theme={null}
  import json

  from sign_request import OLYMPEX_BASE_URL, credentials_from_env, sign_request  # /authentication/sign-requests

  # Paste the method and URL you sent, and the canonical body, timestamp and nonce from the Signing details panel.
  body = json.loads('{"chainId":137}')  # the canonical body; None for GET and DELETE
  signed = sign_request(
      "POST", OLYMPEX_BASE_URL + "/support-chain", body, credentials_from_env(), timestamp="1758700000", nonce="0123456789abcdef01234567"
  )
  print(signed["path"], signed["query"], signed["body_string"], signed["body_hash"], signed["headers"]["x-value-info"], signed["headers"]["x-signature"])
  ```
</CodeGroup>

<Note>
  Use a fixed timestamp and nonce only to compare values. Don't send a request signed this way: the server rejects a nonce it has already seen and a timestamp older than 300 seconds.
</Note>

The first value that differs points to the bug:

| First difference | Likely cause |
| - | - |
| Method and path, or canonical query | The method isn't uppercase, the path doesn't start with `/api/v1`, or the query isn't sorted and percent-encoded per RFC 3986. |
| Canonical body or `bodyHash` | Keys not sorted at every level, whitespace in the body, or the hash encoded as padded base64 or hex instead of unpadded base64url. |
| `x-value-info` | A trailing newline after `bodyHash`, base64 wrapped across lines (use `openssl base64 -A`), or the seven-line signed message encoded instead of only `timestamp`, `nonce` and `bodyHash`. |
| `x-signature` only | The method, path or query you signed differ from the console's: sign the method in uppercase, the path with `/api/v1` and the canonical query. Otherwise the HMAC key is wrong: use the secret key string as UTF-8, not its base64url-decoded bytes. |

To test a signer without any credentials, use the known-answer vectors in [Sign requests](/authentication/sign-requests).

## Troubleshooting

| What you see | Cause | What to do |
| - | - | - |
| "The browser blocked the response" | The browser didn't allow the request, for example because of the API's CORS policy for this site or for the method, 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` right after `curl` to see the real status and headers. |
| `401` with **Gateway response** | A signing header is missing or empty. | Fill in all three credentials and send again. |
| `set OLYMPEX_PASSPHRASE first` in the terminal | You ran a copied command in a shell where `OLYMPEX_PASSPHRASE` isn't set. The command stopped before it sent anything. | Run `read -rs OLYMPEX_PASSPHRASE && export OLYMPEX_PASSPHRASE`, then copy the command again and run it. |
| `403` with **Gateway response** | Unknown API key ID, wrong passphrase or secret key, a copied command whose method, URL or query was edited, a clock more than 300 seconds off, a reused nonce, an inactive account, or signature verification temporarily unavailable. | Send again once: the console signs every attempt with a new nonce. If it fails again, stop and check each credential and your computer's clock. If correctly signed requests keep failing, contact [partners@olympex.io](mailto:partners@olympex.io) with the `apigw-requestid` header of a copied command run with `-i`. |
| `403` `FORBIDDEN` `Invalid body hash` | The body that arrived doesn't match the signed hash, for example because a copied command's body was edited. | Don't resend it unchanged. Copy the command again after you edit the body, or send from the console, which hashes the exact body it sends. |
| `400` `VALIDATION_ERROR` | A field or query parameter is missing or has the wrong type. | Fix each field listed in `error.details`. [Conventions](/api-reference/conventions#chain-ids) covers chain IDs. |
| `400` `VALIDATION_ERROR` `Chain <chainId> is not enabled` | `GET /tokens` or `GET /transactions/{hash}` was called for a chain that isn't enabled. | Pick a chain from `GET /chains`. |
| `400` `VALIDATION_ERROR` `Not exist reference price for this pair …` | Olympex has no reference price for the limit order's pair. | Send the tokens' real symbols in `tokenASymbol` and `tokenBSymbol`, retry later with backoff, or choose another pair. |
| "signature must be the maker's 65-byte signature over the token pair" | The create body still has the placeholder, or `signature` isn't `0x` and 130 hexadecimal characters. | Click **Sign with wallet**, or paste the maker's signature for the pair. |
| "accountTo must be the maker wallet address" | `accountTo` isn't `0x` and 40 hexadecimal characters. | Click **Sign with wallet**, which fills it in, or enter the maker's address. |
| "No browser wallet found" | The page found no browser wallet. | Sign the pair with your own tooling and paste the signature. |
| "You rejected the signature request" | You declined the request in your wallet. | Click **Sign with wallet** again and approve the request. |
| `404` `NOT_FOUND` | No limit order, DCA strategy or DCA order with this ID belongs to your API key, or the message is `No route for …`: the method and path don't exist. | Check the ID, and that you signed with the API key that created the resource, or check the method and path. |
| `409` `CONFLICT` | The limit order is no longer `pending`: Olympex is executing it, or it is completed, failed or cancelled. | Read it with `GET /limit-order/{id}`. |
| `422` `NO_ROUTE` | No liquidity source has a route for this pair and amount right now. | Retry later, or change the amount or pair. For `/swap`, which can also fail with `500 SWAP_ERROR`, build again with the next `aggregatorId` in the quote's `aggregatorOrder`. |
| `429` with **Gateway response** | Too many requests in a short time. | Wait, then retry with exponential backoff and jitter, and send fewer requests in parallel. See [Limits](/authentication/limits#rate-limits-and-quotas). |
| `500` `TX_STATUS_ERROR` | From `/tx-status`: the provider has no status for the transfer yet, or reported a failure. From `/transactions/{hash}`: the request to the chain's RPC failed. | Right after broadcast this is expected from `/tx-status`. Retry with backoff, for example every 15 to 30 seconds. If it persists, check a block explorer or contact support with the `requestId`. |
| `500` with **Gateway response** | The gateway got no response from Olympex, for example on the first request after a quiet period, and occasionally in the middle of a session. | Send again: the console signs every attempt. If it keeps failing, retry with backoff. Check your orders before you send a create again. |
| "No response within 35 seconds" | The API or the network didn't answer in time. | Retry with backoff. Before you send a create again, list your orders or strategies: the first request may have created one. |
| "Use printable ASCII characters with no leading or trailing spaces" | The passphrase breaks the passphrase rules. Browsers can send only ISO-8859-1 header values, and the API trims the header. | Enter the passphrase exactly as you created it. If it can't meet the rules, create a new account with a compliant passphrase. |

## What's next

<CardGroup cols={2}>
  <Card title="Sign requests" icon="shield-halved" href="/authentication/sign-requests">
    Move from the console to signed requests in your own code.
  </Card>

  <Card title="Create a test API key" icon="key" href="/get-started/create-an-api-key">
    Create credentials from a terminal and store them safely.
  </Card>

  <Card title="Errors and retries" icon="circle-exclamation" href="/authentication/errors-and-retries">
    What each error means and when to retry.
  </Card>

  <Card title="Conventions" icon="list-check" href="/api-reference/conventions">
    Units, chain IDs, the envelope and request IDs.
  </Card>
</CardGroup>


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