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

# OpenAPI specification

> Download the Olympex OpenAPI 3.0 document, generate a typed client, add request signing to it, and map the data model.

The Olympex REST API is described by an OpenAPI 3.0.3 document. The parameter, body and response sections of every endpoint page are generated from it, and you can use it to generate a typed client, validate payloads in tests, or browse every schema in one place.

## Download the spec

```text theme={null}
https://docs.olympex.io/api-reference/openapi.json
```

```bash theme={null}
curl -sS -o olympex-openapi.json https://docs.olympex.io/api-reference/openapi.json
```

| Property | Value |
| - | - |
| Format | OpenAPI 3.0.3, JSON |
| Server | `https://api-rest.olympex.io/api/v1` |
| Operations | 21: the 19 endpoints listed in the [overview](/api-reference/overview#endpoints), which use `GET`, `POST`, `PATCH` and `DELETE`, plus the service's public `GET /openapi.json` and `GET /docs` |
| Tags | `Accounts`, `Quotes`, `Swap`, `TxStatus`, `Transactions`, `Chains and tokens`, `Limit orders`, `DCA` and `Docs`. OpenAPI Generator groups the generated methods by tag. |
| Security | Four header schemes, required together on signed endpoints. See [Security schemes](#security-schemes). |
| Document version | `info.version` is `1.0.0`. The API version is `v1`, in the path. |

<Tip>
  Commit the downloaded spec to your repository and regenerate your client on purpose. A spec update then never changes your types without a review.
</Tip>

## Service-hosted spec and Swagger UI

The API also serves its own OpenAPI document and a Swagger UI. Both are public `GET` routes:

```text theme={null}
https://api-rest.olympex.io/api/v1/openapi.json
https://api-rest.olympex.io/api/v1/docs
```

Build against the curated spec at `docs.olympex.io` instead. It includes:

* an absolute server URL, so generators and tools know where to send requests;
* response examples for every endpoint;
* a `discriminator` on `mode` for the single-chain and cross-chain schemas;
* `readOnly` marks on request fields you can't set or change;
* the gateway's own responses (`401`, `403`, `500`, `503`) with the `GatewayError` schema;
* the unit of every amount, fee and gas field;
* an `operationId` on every endpoint, for readable generated method names;
* security scheme descriptions that match the exact signing encodings.

Swagger UI can't compute signatures: every signed request needs a new nonce and a fresh timestamp. To send signed requests from a browser, use the [API console](/api-reference/console), or its [Copy as cURL](/api-reference/console#copy-as-curl) command if your browser blocks the request. If the curated spec and the live API ever disagree, email [partners@olympex.io](mailto:partners@olympex.io) with the `meta.requestId` of the request.

## Generate a client

Olympex doesn't publish an SDK package. Generate a client from the spec in your language, then add signing to it as shown in [Sign requests from a generated client](#sign-requests-from-a-generated-client).

<Tabs>
  <Tab title="TypeScript">
    [openapi-typescript](https://openapi-ts.dev) generates types from the spec, and [openapi-fetch](https://openapi-ts.dev/openapi-fetch/) is a small `fetch` client that uses them. The examples on this page are ES modules that Node.js 22.18 or later runs directly: `npm init -y` writes `"type": "commonjs"`, so set the project's type to `module` first.

    ```bash theme={null}
    npm pkg set type=module
    npm install openapi-fetch
    npm install --save-dev openapi-typescript typescript
    npx openapi-typescript https://docs.olympex.io/api-reference/openapi.json -o ./olympex-api.ts
    ```
  </Tab>

  <Tab title="Other languages">
    [OpenAPI Generator](https://openapi-generator.tech) produces clients for Python, Go, Java, C# and many other languages. The npm wrapper below needs a Java runtime.

    ```bash theme={null}
    npx @openapitools/openapi-generator-cli generate \
      -i https://docs.olympex.io/api-reference/openapi.json \
      -g python \
      -o ./olympex-client
    ```

    Replace `python` with the generator for your language.
  </Tab>
</Tabs>

## Sign requests from a generated client

Generated clients send requests without signatures. They read the four security schemes as static API key values, and a static signature fails: the server rejects a nonce it has seen in the last 5 minutes and a timestamp more than 300 seconds from its clock. Leave those settings empty and sign each request in the client's request hook instead.

The TypeScript example below adds an openapi-fetch middleware that uses `signRequest` from the [reference signer](/authentication/sign-requests) (`sign-request.ts`). It signs every attempt, retries included, and skips the public endpoint, `POST /accounts`. It passes the request's method and full URL to the signer, so the path and the query the client builds are signed too. For `POST` and `PATCH` it replaces the body with the canonical bytes it hashed. `GET` and `DELETE` have no body, so it signs the empty string and sends no body: a `GET` request can't carry one, not even an empty string.

```ts olympex-client.ts theme={null}
import createClient, { type Middleware } from "openapi-fetch";
import type { paths } from "./olympex-api.ts"; // generated by openapi-typescript
import { OLYMPEX_BASE_URL, credentialsFromEnv, signRequest, type Json } from "./sign-request.ts"; // /authentication/sign-requests

const PUBLIC_PATHS = new Set(["/accounts"]);
const credentials = credentialsFromEnv();

const signOlympexRequests: Middleware = {
  async onRequest({ request, schemaPath }) {
    if (PUBLIC_PATHS.has(schemaPath)) return undefined;
    const hasBody = request.method === "POST" || request.method === "PATCH";
    const text = hasBody ? await request.clone().text() : "";
    // Signs the method, the path and canonical query of request.url, and the body (the empty string for GET and DELETE).
    const signed = signRequest(request.method, request.url, text ? (JSON.parse(text) as Json) : undefined, credentials);
    const headers = new Headers(request.headers);
    for (const [name, value] of Object.entries(signed.headers)) headers.set(name, value);
    // Send exactly the canonical bytes that were hashed, and no body at all for GET and DELETE.
    return new Request(request, hasBody ? { body: signed.bodyString, headers } : { headers });
  },
};

export const olympex = createClient<paths>({ baseUrl: OLYMPEX_BASE_URL });
olympex.use(signOlympexRequests);
```

Every call is then typed from the spec, and signed:

```ts theme={null}
import { olympex } from "./olympex-client.ts";

const { data, error, response } = await olympex.POST("/quotes", {
  body: {
    mode: "single-chain",
    params: {
      chainId: 137,
      inTokenAddress: "0xc2132d05d31c914a87c6611c10748aeb04b58e8f", // USDT
      outTokenAddress: "0x3c499c542cef5e3811e1192ce70d8cc03d5c3359", // USDC
      amount: "10",
      slippage: "1",
      gasPrice: "35",
    },
  },
});

if (error) {
  // Olympex errors carry error.code; gateway responses carry only message.
  console.error(response.status, "error" in error ? error.error.code : error.message);
} else if (data.data.mode === "single-chain") {
  console.log(data.data.quote.aggregatorId, data.data.quote.outAmount);
}
```

`GET` and `DELETE` calls pass their parameters through `params`. The middleware signs the empty string as the body, together with the path and the query:

```ts theme={null}
import { olympex } from "./olympex-client.ts";

// Query parameter. The middleware signs it with the path.
const tokens = await olympex.GET("/tokens", { params: { query: { chainId: 137 } } });
console.log(tokens.data?.data.tokens.length);

// Path parameter. An ID that doesn't belong to your API key returns 404 NOT_FOUND.
const order = await olympex.GET("/limit-order/{id}", {
  params: { path: { id: "afc47108-d059-473c-b2e1-5f2ca7951466" } },
});
console.log(order.response.status, order.data?.data.status);
```

In other languages, add the same steps to the generated client's request interceptor:

1. For `POST` and `PATCH`, canonicalize the body. For `GET` and `DELETE`, use the empty string and send no body.
2. Take the method in uppercase, and the path and the [canonical query](/authentication/sign-requests#canonical-query) of the final URL. The path starts with `/api/v1`.
3. Build and sign the message as described in [Sign requests](/authentication/sign-requests#algorithm).
4. Set the four headers, and `Content-Type: application/json`.
5. Send the canonical string as the body of a `POST` or `PATCH`.

If the client can't replace the body, use its models for types and send the request through the reference signer: `olympex_request(method, path, body)` in Python, `olympexRequest(method, path, body)` in TypeScript.

## Single-chain and cross-chain variants

`POST /quotes` and `POST /swap` accept two body shapes, chosen by `mode`. In the spec, `QuoteRequest` and `SwapRequest` are `oneOf` schemas with a `discriminator` on `mode`. In the responses, `data` is a `oneOf` of two variants whose `mode` has a single allowed value, so checking `data.mode` narrows the type in TypeScript and most typed languages.

| | Single-chain | Cross-chain |
| - | - | - |
| `mode` | `"single-chain"` | `"cross-chain"` |
| Request schemas | `SingleChainQuoteRequest`, `SingleChainSwapRequest` | `CrossChainQuoteRequest`, `CrossChainSwapRequest` |
| Chain fields | `chainId` (integer) | `fromChainId`, `toChainId` (integers) |
| Token fields | `inTokenAddress`, `outTokenAddress` | `inTokenAddress`, `outTokenAddress` |
| `gasPrice` | Required | Not part of the schema |
| `dryRun` on `/swap` | Accepted, no effect | Rejected with `400` |
| Response schemas | `SingleChainQuote`, `SingleChainSwap` | `CrossChainQuote`, `CrossChainSwap` |
| Calldata field | `swap.data` | `swap.calldata` |
| Tracking after broadcast | `GET /transactions/{hash}`, or the receipt from your RPC | `GET /transactions/{hash}` for the source transaction, then `POST /tx-status` with `swap.dexHash` |

The cross-chain request schemas also set `additionalProperties: false`, so an unknown top-level key returns `400`.

## Data model

Every schema lives under `components.schemas`.

### Requests

| Schema | What it is |
| - | - |
| `CreateAccountRequest` | Body of `POST /accounts`: `name` and `password`. |
| `QuoteRequest` | Body of `POST /quotes`: `SingleChainQuoteRequest` or `CrossChainQuoteRequest`, chosen by `mode`. |
| `SwapRequest` | Body of `POST /swap`: `SingleChainSwapRequest` or `CrossChainSwapRequest`, chosen by `mode`. |
| `FeeOptions` | The optional `fees` object on quote and swap bodies: `feeBps` and `feeRecipient`. |
| `SupportChainRequest` | Body of `POST /support-chain`: `chainId` as an integer. |
| `TxStatusRequest` | Body of `POST /tx-status`: `hash`, `chainId` as an integer, and `dexHash`. |
| `LimitOrderCreateRequest` | Body of `POST /limit-order`: the maker, the chain, the two tokens and their symbols, `amount`, `priceTrigger`, `expired`, `gasPrice`, `slippage` and the maker's `signature`. |
| `LimitOrderUpdateRequest` | Body of `PATCH /limit-order/{id}`: any of `priceTrigger`, `price`, `amount`, `expired`, `slippage` and `gasPrice`. |
| `DcaStrategyCreateRequest` | Body of `POST /dca-order/strategies`: the maker, the chain, the two tokens, their symbols and `pair`, `totalAmount`, `iterations`, `frequency`, `slippage`, optional price bounds, an optional `status` and the maker's `signature`. |
| `DcaStrategyUpdateRequest` | Body of `PATCH /dca-order/strategies/{id}`: `status` to cancel, or new `minPrice` and `maxPrice`. |

Request schemas also list fields you can't set or change, marked `readOnly`. Don't send them. Fields that Olympex sets as it executes an order, such as a limit order's `status` and `txHash`, aren't part of the request schemas: sending one returns `400 VALIDATION_ERROR`.

### Envelope and errors

| Schema | What it is |
| - | - |
| `Meta` | `requestId`, `version` and, on signed endpoints, `accountType` and `apiKeyId`. |
| `ErrorResponse` | The error envelope: `success: false`, `error` and `meta`. |
| `ErrorBody` | `code`, `message` and `details`. |
| `ErrorDetail` | One entry in `details`: `field` and `message` for validation errors, `message` only otherwise. |
| `GatewayError` | The `message`-only body the API gateway returns when it answers a request itself. |

### Responses

| Schema | What it is |
| - | - |
| `CreateAccountSuccessResponse` | `data.apiKey` (your API key ID), `data.secretKey` and `data.message`. |
| `QuoteSuccessResponse` | `data.mode` and `data.quote`: a `SingleChainQuote` or a `CrossChainQuote`. |
| `SingleChainQuote` | `outAmount`, `aggregatorId`, `aggregatorOrder`, `estimatedGas`, `routes`, `market`, `gasMultiplier`, `integratorFeeBreakdown`, and the optional `dataFeeTransaction`. |
| `CrossChainQuote` | `aggregatorId`, `fromTokenAmount`, `toTokenAmount`, `minimumReceived`, `estimateCostInUSD`, `estimatedGas`, `estimatedTime`, `bridgeInfo`, `middlewareRoute` and `integratorFeeBreakdown`. |
| `QuoteRoute`, `QuoteSubRoute`, `QuoteDex` | The single-chain path as the source reports it, for display only: each route's percentage, its token hops, and the DEXes on each hop. Percentages don't always sum to 100, and address case varies by source. |
| `QuoteMarket` | Another venue's price for the same trade. |
| `DataFeeTransaction` | Gas fee estimate, with the gas price it used in `effectiveGasPrice`. Present when `includeGasInfo` is `true`. |
| `IntegratorFeeBreakdown` | The Olympex protocol fee and your integrator fee, on every quote. `protocolFeeBps` is in basis points (`15` is 0.15%) and can be fractional, and `integratorMarginBps` is `0` when you send no `fees`. |
| `SwapSuccessResponse` | `data.mode` and `data.swap`: a `SingleChainSwap` or a `CrossChainSwap`. |
| `SingleChainSwap` | `to`, `data`, `value`, `contractToApprove`, `outAmount`, `minOutAmount`, `gasLimit` and `estimatedGas`. |
| `CrossChainSwap` | `to`, `calldata`, `value`, `contractToApprove`, `dexHash`, `gasLimit` and `estimatedGas`. |
| `SupportChainSuccessResponse` | `data` is `true` when Olympex supports the chain. |
| `TxStatusSuccessResponse`, `TxStatus` | `status`, `detailStatus`, `fromChainId` and `toChainId` (integers), and the hashes, amounts and addresses the provider reports. |
| `TransactionStatusSuccessResponse`, `TransactionStatus` | `data.hash`, `chainId`, `status` (`pending`, `success`, `reverted` or `not_found`), `blockNumber`, `confirmations` and `gasUsed`. |
| `ChainsSuccessResponse` | `data.chainIds`: the enabled chain IDs, as integers in ascending order. |
| `TokensSuccessResponse`, `Token` | `data.chainId` and `data.tokens`: each token's `address`, `symbol`, `name`, `decimals`, `icon` and, on some entries, `logoURI`. |
| `LimitOrder` | A limit order: its terms, `status`, `txHash`, `reasonFail`, `attemptNumber` and timestamps. |
| `LimitOrderSuccessResponse`, `LimitOrderListSuccessResponse` | `data` is one `LimitOrder`, or an array of them. |
| `DcaStrategy`, `DcaStrategyWithOrders` | A DCA strategy, and the same strategy with its `orders`, as `GET /dca-order/strategies` returns it. |
| `DcaOrder` | One order of a strategy: `amount`, `status`, and once it executes, `amountReceived`, `executionPrice` and `transactionHash`. |
| `DcaStrategySuccessResponse`, `DcaStrategyListSuccessResponse` | `data` is one `DcaStrategy`, or an array of `DcaStrategyWithOrders`. |
| `DcaOrderSuccessResponse`, `DcaOrderListSuccessResponse` | `data` is one `DcaOrder`, or an array of them. |

[Conventions](/api-reference/conventions#amounts) gives the unit of every amount field.

## Security schemes

The spec declares four `apiKey` schemes, one per header. Signed endpoints list all four in a single security requirement, so a request needs every header at once. Public endpoints declare `security: []`.

| Scheme | Header | Value |
| - | - | - |
| `ApiKeyId` | `x-api-key-id` | Your API key ID. |
| `ValueInfo` | `x-value-info` | Standard base64 of `timestamp`, `nonce` and `bodyHash` joined with newlines. |
| `Passphrase` | `x-passphrase` | Your passphrase. |
| `Signature` | `x-signature` | Lowercase hex HMAC-SHA256 of the signed message (`OLPX-HMAC-SHA256-V2`, timestamp, nonce, method, path, canonical query and `bodyHash`), keyed with your secret key string. |

[Sign requests](/authentication/sign-requests) has the full algorithm, two known-answer vectors and reference code in TypeScript, Python and bash.

## What's next

<CardGroup cols={2}>
  <Card title="Sign requests" icon="shield-halved" href="/authentication/sign-requests">
    The signer the middleware above wraps.
  </Card>

  <Card title="Conventions" icon="list-check" href="/api-reference/conventions">
    Units, chain IDs, errors and forward compatibility.
  </Card>

  <Card title="Get a quote" icon="magnifying-glass-dollar" href="/api-reference/quotes/get-quote">
    The first endpoint most integrations call.
  </Card>

  <Card title="API console" icon="terminal" href="/api-reference/console">
    Try any endpoint from your browser.
  </Card>
</CardGroup>


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