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

# Create a DCA strategy

> Spend a fixed budget in equal orders at a fixed interval to buy a token on one chain.

`POST /dca-order/strategies` creates a DCA strategy: Olympex spends `totalAmount` of `tokenAddressFrom` in `iterations` equal orders, one every `frequency` seconds, to buy `tokenAddressTo` for the maker wallet `accountTo`. The strategy starts `active` immediately, unless you send `"status": "cancelled"` to create a stopped one for testing. Nothing moves when you create it: each order pulls its amount from `accountTo` through the Olympex order contract when it executes. [DCA](/concepts/dca) explains how strategies and their orders work.

Signed endpoint. Send `Content-Type: application/json`, the canonical JSON body, and the four headers `x-api-key-id`, `x-value-info`, `x-passphrase` and `x-signature` described in [Sign requests](/authentication/sign-requests). Numeric fields are JSON numbers, not strings: `chainIdFrom`, `chainIdTo`, `totalAmount` (human-readable units of `tokenAddressFrom`), `frequency` (seconds), `iterations`, `slippage` (percent) and the optional `minPrice` and `maxPrice`. `chainIdFrom` must equal `chainIdTo`. `pair` is `"<tokenSymbolFrom>/<tokenSymbolTo>"`. `status` is optional: omit it for an `active` strategy, or send `"cancelled"` to create a stopped one for testing. The create call checks types, required fields and that addresses are valid EVM addresses (`0x` and 40 hex digits, lowercase or EIP-55 checksummed), not the other rules or the signature. `signature` is the maker's EIP-191 `personal_sign` over the 32 bytes of `keccak256(abi.encodePacked(accountTo, accountTo, tokenAddressFrom, tokenAddressTo))`. Orders execute only if `accountTo` has approved the Olympex order contract for `totalAmount` of `tokenAddressFrom`. Returns `200` with the new strategy. Each successful call creates a new strategy, so after a timeout, list strategies before you send the request again.

## Units

| Field | Meaning and unit |
| - | - |
| `totalAmount` | Total budget in human-readable units of `tokenAddressFrom`, not base units. `100` is 100 USDC. |
| `iterations` | Number of orders. Each order spends `totalAmount / iterations`: 100 USDC over 10 iterations is 10 USDC per order. |
| `frequency` | Seconds between orders. `86400` is daily. |
| `slippage` | Maximum slippage per order, in percent. `1` is 1%. Always send it: a strategy created without it shows `0`. |
| `minPrice`, `maxPrice` | Optional price bounds, in units of `tokenAddressTo` per 1 `tokenAddressFrom`. Olympex executes an order only while the price is within the bounds you set. |
| `chainIdFrom`, `chainIdTo` | Chain IDs. They must be equal: DCA runs on one chain. |
| `pair` | `"<tokenSymbolFrom>/<tokenSymbolTo>"`, for example `"USDC/WETH"`. It isn't returned in responses. |

Every numeric field is a **JSON number**, unlike the decimal strings that quotes and limit orders use. A string such as `"totalAmount": "100"` returns `400 VALIDATION_ERROR`. The reference signers format numbers the way JavaScript does, so fractional values sign correctly in TypeScript, Python and the API console. See [Portability rules](/authentication/sign-requests#portability-rules).

## Sign the pair and approve the amount

Orders execute only when the maker wallet `accountTo` has done two things. [Order signatures and allowances](/concepts/order-authorization) covers both, with the Olympex order contract address on each chain.

1. **Signed the token pair.** `signature` is the maker's `personal_sign` over the 32 bytes of `keccak256(abi.encodePacked(accountTo, accountTo, tokenAddressFrom, tokenAddressTo))`. Sign the bytes, not their hex string. Olympex doesn't check the signature when you create the strategy, and a wrong one makes execution fail later, so verify it before you send it. A limit order for the same pair uses the same signature.
2. **Approved `totalAmount`.** The maker approves the Olympex order contract, not the `contractToApprove` that `POST /swap` returns, to spend `totalAmount` of `tokenAddressFrom`. Execution gas is reimbursed out of the token bought, so the allowance needs nothing on top for fees. The allowance is shared: if other active strategies or open limit orders sell the same token on the same chain, approve the sum.

<Warning>
  This endpoint creates a live strategy, including when you send it from the console on this page. The pair signature doesn't bind an amount, a price or an expiry, and it stays valid after you cancel. The on-chain limit is the maker's allowance to the order contract: approve only what open orders need, never an unlimited amount, and set it to `0` to stop everything for a token.
</Warning>

## Tokens, chain and maker

* **One chain.** `chainIdFrom` and `chainIdTo` must be the same chain, and DCA executes only on chains with an Olympex order contract.
* **Tokens you can sell.** `tokenAddressFrom` must be an ERC-20 token. Native tokens can't be sold: wrap them first (WETH, WBNB, WPOL, listed in [List tokens](/api-reference/tokens/list-tokens#match-tokens-by-address)). Fee-on-transfer tokens aren't supported, and USDT isn't supported as the token you sell in limit orders or DCA on Ethereum.
* **The maker.** `accountTo` sells `tokenAddressFrom`, receives `tokenAddressTo` and signs `signature`. It must be an externally owned account (EOA): smart-contract wallets such as Safe or ERC-4337 accounts can't sign orders, because only 65-byte ECDSA signatures are accepted. Olympex stores the address as you send it and list filters match it case-sensitively, so send the EIP-55 checksummed form.
* **Symbols.** Send the tokens' real symbols in `tokenSymbolFrom`, `tokenSymbolTo` and `pair`. Read them with `symbol()` from the token contracts, or take them from [`GET /tokens`](/api-reference/tokens/list-tokens) by address, trimmed and without a trailing `_<number>`.
* **Test without scheduling orders.** Omit `status` and the strategy starts `active`. Send `"status": "cancelled"` to create a stopped strategy, for example to test your integration without moving funds. `pending` and `finished` are reserved for Olympex.
* **What the create call checks.** Olympex checks the types, the required fields and that each address is a valid EVM address. It doesn't check the other rules in this section or the pair signature: a strategy that breaks one is created, and its orders can't execute. Check them before you send the request.
* Other fields in the schema are set by Olympex; don't send them.

## Each call creates a strategy

Every successful call creates a new strategy with a new ID, and Olympex ignores any `id` you send. If a request times out or the connection drops, you don't know whether the strategy exists. Before you send it again, [list the maker's active strategies](/api-reference/dca/list-dca-strategies) and look for one with the same tokens, `totalAmount`, `iterations` and `frequency`. The retry wrappers in [Handle errors and retries](/guides/handle-errors-and-retries) never retry this endpoint automatically.

Store `data.id` from the response. Olympex places the orders one `frequency` apart: follow them with [`GET /dca-order/strategies/{id}/orders`](/api-reference/dca/list-dca-strategy-orders), and stop the strategy with [`PATCH /dca-order/strategies/{id}`](/api-reference/dca/update-dca-strategy).

<RequestExample>
  ```bash cURL theme={null}
  # Buy WETH with 100 USDC on Polygon: 10 orders of 10 USDC, one every 86400 seconds (daily).
  # Needs openssl, curl, python3 and OLYMPEX_API_KEY_ID, OLYMPEX_SECRET_KEY, OLYMPEX_PASSPHRASE, plus the maker's key in
  # WALLET_PRIVATE_KEY and sign_order_pair.py from /concepts/order-authorization in this folder, with eth-account
  # installed in an active virtual environment.
  SIGNED="$(python3 -c 'import os, sign_order_pair as s; r = s.sign_order_pair(os.environ["WALLET_PRIVATE_KEY"], "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359", "0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619"); print(r["accountTo"], r["signature"])')"
  MAKER="${SIGNED% *}"      # the maker's EIP-55 address
  SIGNATURE="${SIGNED#* }"  # the maker's signature for the USDC to WETH pair
  METHOD=POST
  ENDPOINT=/dca-order/strategies
  QUERY=''
  BODY="$(printf '{"accountTo":"%s","chainIdFrom":137,"chainIdTo":137,"frequency":86400,"iterations":10,"pair":"USDC/WETH","signature":"%s","slippage":1,"tokenAddressFrom":"0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359","tokenAddressTo":"0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619","tokenSymbolFrom":"USDC","tokenSymbolTo":"WETH","totalAmount":100}' "$MAKER" "$SIGNATURE")"
  TS="${OLYMPEX_TIMESTAMP:-$(date +%s)}"
  NONCE="${OLYMPEX_NONCE:-$(openssl rand -hex 12)}"
  BODY_HASH="$(printf '%s' "$BODY" | openssl dgst -sha256 -binary | openssl base64 -A | tr '+/' '-_' | tr -d '=')"
  VALUE_INFO="$(printf '%s\n%s\n%s' "$TS" "$NONCE" "$BODY_HASH")"
  MESSAGE="$(printf 'OLPX-HMAC-SHA256-V2\n%s\n%s\n%s\n%s\n%s\n%s' "$TS" "$NONCE" "$METHOD" "/api/v1$ENDPOINT" "$QUERY" "$BODY_HASH")"
  curl -sS -X "$METHOD" "https://api-rest.olympex.io/api/v1$ENDPOINT${QUERY:+?$QUERY}" \
    -H "content-type: application/json" \
    -H "x-api-key-id: $OLYMPEX_API_KEY_ID" \
    -H "x-value-info: $(printf '%s' "$VALUE_INFO" | openssl base64 -A)" \
    -H "x-passphrase: $OLYMPEX_PASSPHRASE" \
    -H "x-signature: $(printf '%s' "$MESSAGE" | openssl dgst -sha256 -hmac "$OLYMPEX_SECRET_KEY" -binary | od -An -v -tx1 | tr -d ' \n')" \
    --data-raw "$BODY"
  ```

  ```ts TypeScript theme={null}
  // npm install ethers. Reads the maker's WALLET_PRIVATE_KEY from the environment.
  import { Wallet } from "ethers";
  import { olympexRequest } from "./sign-request.ts"; // /authentication/sign-requests
  import { signOrderPair } from "./sign-order-pair.ts"; // /concepts/order-authorization

  const USDC = "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359"; // Polygon
  const WETH = "0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619"; // Polygon

  // An EOA that holds the USDC and has approved the Olympex order contract for totalAmount.
  // In a dApp, pass the user's wallet signer instead.
  const wallet = new Wallet(process.env.WALLET_PRIVATE_KEY!);
  const { accountTo, signature } = await signOrderPair(wallet, USDC, WETH); // checks the signature before it returns

  // Every success creates a new strategy: after a timeout, list the strategies before you retry.
  const strategy = await olympexRequest<{ id: string; status: string }>("POST", "/dca-order/strategies", {
    accountTo, // EIP-55 checksummed
    chainIdFrom: 137,
    chainIdTo: 137, // same chain only
    tokenAddressFrom: USDC,
    tokenAddressTo: WETH,
    tokenSymbolFrom: "USDC",
    tokenSymbolTo: "WETH",
    pair: "USDC/WETH",
    totalAmount: 100, // JSON number, human-readable: 100 USDC in total
    iterations: 10, // 10 orders of 10 USDC
    frequency: 86400, // seconds between orders
    slippage: 1, // percent
    signature,
  });
  console.log(strategy.id, strategy.status); // save the ID: "active" from the start
  ```

  ```python Python theme={null}
  # In a virtual environment: python3 -m venv .venv && . .venv/bin/activate && python3 -m pip install eth-account requests
  import os

  from sign_order_pair import sign_order_pair  # /concepts/order-authorization
  from sign_request import olympex_request  # /authentication/sign-requests

  USDC = "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359"  # Polygon
  WETH = "0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619"  # Polygon

  # An EOA that holds the USDC and has approved the Olympex order contract for totalAmount.
  pair = sign_order_pair(os.environ["WALLET_PRIVATE_KEY"], USDC, WETH)  # checks the signature before it returns

  # Every success creates a new strategy: after a timeout, list the strategies before you retry.
  strategy = olympex_request("POST", "/dca-order/strategies", {
      "accountTo": pair["accountTo"],  # EIP-55 checksummed
      "chainIdFrom": 137,
      "chainIdTo": 137,  # same chain only
      "tokenAddressFrom": USDC,
      "tokenAddressTo": WETH,
      "tokenSymbolFrom": "USDC",
      "tokenSymbolTo": "WETH",
      "pair": "USDC/WETH",
      "totalAmount": 100,  # JSON number, human-readable: 100 USDC in total
      "iterations": 10,  # 10 orders of 10 USDC
      "frequency": 86400,  # seconds between orders
      "slippage": 1,  # percent
      "signature": pair["signature"],
  })
  print(strategy["id"], strategy["status"])  # save the ID: "active" from the start
  ```
</RequestExample>

<ResponseExample>
  ```json 200 theme={null}
  {
    "success": true,
    "data": {
      "id": "320263ca-2f38-4349-b641-a23aed2ff847",
      "accountTo": "0x1E67cb01969D79B2B895179e4A07D24a839dBb52",
      "chainIdFrom": 137,
      "chainIdTo": 137,
      "tokenAddressFrom": "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359",
      "tokenAddressTo": "0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619",
      "tokenSymbolFrom": "USDC",
      "tokenSymbolTo": "WETH",
      "totalAmount": 100,
      "frequency": 86400,
      "iterations": 10,
      "slippage": 1,
      "status": "active",
      "createdAt": "2026-09-29T13:48:57.833Z",
      "updatedAt": "2026-09-29T13:48:57.833Z"
    },
    "meta": {
      "requestId": "Eds3EgIrIAMEPJA=",
      "version": "v1",
      "accountType": "integrator",
      "apiKeyId": "00000000-0000-4000-8000-000000000000"
    }
  }
  ```

  ```json 400 theme={null}
  {
    "success": false,
    "error": {
      "code": "VALIDATION_ERROR",
      "message": "Invalid request body",
      "details": [
        {
          "field": "accountTo",
          "message": "Invalid input: expected string, received undefined"
        },
        {
          "field": "chainIdFrom",
          "message": "Invalid input: expected number, received undefined"
        },
        {
          "field": "chainIdTo",
          "message": "Invalid input: expected number, received undefined"
        }
      ]
    },
    "meta": {
      "requestId": "Edje9jY4oAMEVNA=",
      "version": "v1",
      "accountType": "integrator",
      "apiKeyId": "00000000-0000-4000-8000-000000000000"
    }
  }
  ```

  ```json 403 Gateway theme={null}
  {
    "message": "Forbidden"
  }
  ```
</ResponseExample>


## OpenAPI

````yaml api-reference/openapi.json POST /dca-order/strategies
openapi: 3.0.3
info:
  title: Olympex REST API
  version: 1.0.0
  description: >-
    Aggregated swap quotes and transactions, limit orders and DCA strategies on
    EVM chains, plus the chain and token catalog. Every response uses the same
    envelope, except the API gateway's own responses (`{"message": …}`): `401`
    or `403` when the signed headers are missing or rejected, `429` when it
    throttles requests, and `500` or `503` when it can't get a response from
    Olympex in time. Chain IDs are integers on every endpoint. Signed endpoints
    require four signed headers; see [Sign
    requests](https://docs.olympex.io/authentication/sign-requests).
  termsOfService: https://docs.olympex.io/legal/terms
  contact:
    name: Olympex partnerships
    email: partners@olympex.io
    url: https://docs.olympex.io
servers:
  - url: https://api-rest.olympex.io/api/v1
    description: Olympex REST API v1
security: []
tags:
  - name: Accounts
    description: Create API credentials.
  - name: Quotes
    description: Aggregated single-chain and cross-chain quotes.
  - name: Swap
    description: Unsigned transaction calldata for a quoted route.
  - name: TxStatus
    description: Track a cross-chain transfer after you broadcast it.
  - name: Transactions
    description: On-chain status of a transaction you broadcast.
  - name: Chains and tokens
    description: Enabled chains and the tokens listed on each.
  - name: Limit orders
    description: Orders that Olympex executes when the market reaches your price.
  - name: DCA
    description: Strategies that buy a token in equal orders over time.
  - name: Docs
    description: Machine-readable API description.
paths:
  /dca-order/strategies:
    post:
      tags:
        - DCA
      summary: Create a DCA strategy
      description: >-
        Creates a strategy that spends `totalAmount` of `tokenAddressFrom` in
        `iterations` equal orders, one every `frequency` seconds, buying
        `tokenAddressTo`. The strategy starts as `active`. Nothing moves
        on-chain now: each order pulls its amount from `accountTo` under the
        allowance `accountTo` granted to the Olympex order contract. Each call
        creates a new strategy, so don't retry a call that timed out: list your
        strategies first.
      operationId: createDcaStrategy
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/DcaStrategyCreateRequest'
      responses:
        '200':
          description: The strategy, as stored.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DcaStrategySuccessResponse'
              example:
                success: true
                data:
                  id: 320263ca-2f38-4349-b641-a23aed2ff847
                  accountTo: '0x1E67cb01969D79B2B895179e4A07D24a839dBb52'
                  chainIdFrom: 137
                  chainIdTo: 137
                  tokenAddressFrom: '0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359'
                  tokenAddressTo: '0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619'
                  tokenSymbolFrom: USDC
                  tokenSymbolTo: WETH
                  totalAmount: 100
                  frequency: 86400
                  iterations: 10
                  slippage: 1
                  status: active
                  createdAt: '2026-09-29T13:48:57.833Z'
                  updatedAt: '2026-09-29T13:48:57.833Z'
                meta:
                  requestId: Eds3EgIrIAMEPJA=
                  version: v1
                  accountType: integrator
                  apiKeyId: 00000000-0000-4000-8000-000000000000
        '400':
          description: The body failed validation. `error.details` lists each field.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                success: false
                error:
                  code: VALIDATION_ERROR
                  message: Invalid request body
                  details:
                    - field: accountTo
                      message: 'Invalid input: expected string, received undefined'
                    - field: chainIdFrom
                      message: 'Invalid input: expected number, received undefined'
                    - field: chainIdTo
                      message: 'Invalid input: expected number, received undefined'
                meta:
                  requestId: Edje9jY4oAMEVNA=
                  version: v1
                  accountType: integrator
                  apiKeyId: 00000000-0000-4000-8000-000000000000
        '401':
          description: >-
            A signing header is missing. The gateway answers with
            `{"message":"Unauthorized"}` before your request reaches Olympex;
            the handler answers with the `UNAUTHORIZED` envelope when the
            authorizer context is missing.
          content:
            application/json:
              schema:
                oneOf:
                  - $ref: '#/components/schemas/GatewayError'
                  - $ref: '#/components/schemas/ErrorResponse'
              example:
                message: Unauthorized
        '403':
          description: >-
            Authentication failed: unknown key, wrong passphrase, invalid
            signature, timestamp outside the ±300 s window, reused nonce, or
            inactive account (gateway `{"message":"Forbidden"}`). The handler
            answers with the `FORBIDDEN` envelope when the body does not match
            the signed `bodyHash`.
          content:
            application/json:
              schema:
                oneOf:
                  - $ref: '#/components/schemas/GatewayError'
                  - $ref: '#/components/schemas/ErrorResponse'
              examples:
                gateway:
                  summary: Signature rejected by the gateway
                  value:
                    message: Forbidden
                bodyHash:
                  summary: Body does not match the signed hash
                  value:
                    success: false
                    error:
                      code: FORBIDDEN
                      message: Invalid body hash
                      details: []
                    meta:
                      requestId: ENXGDhsXIAMEMEw=
                      version: v1
                      accountType: integrator
                      apiKeyId: 00000000-0000-4000-8000-000000000000
        '404':
          description: >-
            Unknown path or wrong method (`NOT_FOUND`). `error.message` names
            the method and path.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                success: false
                error:
                  code: NOT_FOUND
                  message: No route for GET /api/v1/quote
                  details: []
                meta:
                  requestId: E7edogG4IAMEPYA=
                  version: v1
        '500':
          description: >-
            Olympex could not complete the request (`INTERNAL_ERROR`), or the
            gateway could not get a response (`{"message":"Internal Server
            Error"}`), which also happens on the first request after a quiet
            period. Retry with backoff.
          content:
            application/json:
              schema:
                oneOf:
                  - $ref: '#/components/schemas/ErrorResponse'
                  - $ref: '#/components/schemas/GatewayError'
              example:
                success: false
                error:
                  code: INTERNAL_ERROR
                  message: Unexpected internal error
                  details: []
                meta:
                  requestId: EdkffjY7oAMEZMA=
                  version: v1
                  accountType: integrator
                  apiKeyId: 00000000-0000-4000-8000-000000000000
        '503':
          description: >-
            The gateway could not get a response in time (the integration
            timeout is about 30 seconds) or the service is briefly unavailable.
            Returned by the gateway. Retry with backoff.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GatewayError'
              example:
                message: Service Unavailable
      security:
        - ApiKeyId: []
          ValueInfo: []
          Passphrase: []
          Signature: []
components:
  schemas:
    DcaStrategyCreateRequest:
      type: object
      properties:
        id:
          type: string
          format: uuid
          pattern: >-
            ^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$
          readOnly: true
          description: 'Ignored: Olympex assigns every strategy a new ID. Don''t send it.'
        accountTo:
          type: string
          minLength: 1
          description: >-
            The maker: the wallet that sells `tokenAddressFrom`, receives
            `tokenAddressTo` and signs `signature`. It must be an externally
            owned account (EOA). Stored exactly as sent. Send the EIP-55
            checksummed form, and use the same form in list filters, which match
            case-sensitively. Must be a valid EVM address: `0x` and 40
            hexadecimal digits, in lowercase or EIP-55 checksummed form. A
            mixed-case address with a wrong checksum returns `400
            VALIDATION_ERROR` ("Must be a valid EVM address").
        chainIdFrom:
          type: integer
          minimum: 0
          exclusiveMinimum: true
          maximum: 9007199254740991
          description: >-
            Chain of `tokenAddressFrom`, as a number. Use a chain from `GET
            /chains`.
        chainIdTo:
          type: integer
          minimum: 0
          exclusiveMinimum: true
          maximum: 9007199254740991
          description: >-
            Chain of `tokenAddressTo`. Must equal `chainIdFrom`: DCA runs on one
            chain.
        tokenAddressFrom:
          type: string
          minLength: 1
          description: >-
            ERC-20 token to sell in every order. Native tokens can't be sold:
            use the wrapped token (WETH, WBNB, WPOL). Must be a valid EVM
            address: `0x` and 40 hexadecimal digits, in lowercase or EIP-55
            checksummed form. A mixed-case address with a wrong checksum returns
            `400 VALIDATION_ERROR` ("Must be a valid EVM address").
        tokenAddressTo:
          type: string
          minLength: 1
          description: >-
            Token to buy. Must be a valid EVM address: `0x` and 40 hexadecimal
            digits, in lowercase or EIP-55 checksummed form. A mixed-case
            address with a wrong checksum returns `400 VALIDATION_ERROR` ("Must
            be a valid EVM address").
        tokenSymbolFrom:
          type: string
          minLength: 1
          description: Symbol of `tokenAddressFrom`, for example `USDC`.
        tokenSymbolTo:
          type: string
          minLength: 1
          description: Symbol of `tokenAddressTo`, for example `WETH`.
        pair:
          type: string
          minLength: 1
          description: >-
            The pair as `<tokenSymbolFrom>/<tokenSymbolTo>`, for example
            `USDC/WETH`. Not returned in responses.
        totalAmount:
          type: number
          minimum: 0
          exclusiveMinimum: true
          description: >-
            Total amount of `tokenAddressFrom` to spend across all orders,
            human-readable (`100` is 100 USDC), as a JSON number. Each order
            spends `totalAmount / iterations`.
        frequency:
          type: integer
          minimum: 0
          exclusiveMinimum: true
          maximum: 9007199254740991
          description: Seconds between orders, for example `86400` for daily.
        iterations:
          type: integer
          minimum: 0
          exclusiveMinimum: true
          maximum: 9007199254740991
          description: Number of orders.
        slippage:
          type: number
          minimum: 0
          exclusiveMinimum: true
          description: >-
            Maximum slippage per order, in percent, as a JSON number (`1` is
            1%). Always send it: responses show `0` when it's missing.
        minPrice:
          type: number
          description: >-
            Optional lower price bound, in units of `tokenAddressTo` per 1
            `tokenAddressFrom`. Orders run only while the price is within the
            bounds you set.
        maxPrice:
          type: number
          description: >-
            Optional upper price bound, in units of `tokenAddressTo` per 1
            `tokenAddressFrom`.
        status:
          type: string
          enum:
            - pending
            - active
            - cancelled
            - finished
          description: >-
            Optional. Omit it and the strategy starts `active`. Send `cancelled`
            to create a stopped strategy, for example to test your integration
            without scheduling orders. `pending` and `finished` are reserved for
            Olympex.
        signature:
          type: string
          minLength: 1
          description: >-
            The maker's signature authorizing Olympex to execute orders for this
            token pair: `personal_sign` over
            `keccak256(abi.encodePacked(accountTo, accountTo, tokenAddressFrom,
            tokenAddressTo))`, 65 bytes as 0x-prefixed hex. It's the same
            signature a limit order for the same pair uses. See [Order
            signatures and allowances](/concepts/order-authorization).
      required:
        - accountTo
        - chainIdFrom
        - chainIdTo
        - tokenAddressFrom
        - tokenAddressTo
        - tokenSymbolFrom
        - tokenSymbolTo
        - pair
        - totalAmount
        - frequency
        - iterations
        - signature
      additionalProperties: false
      description: >-
        Creates a strategy that buys `tokenAddressTo` with `tokenAddressFrom` in
        `iterations` equal orders, one every `frequency` seconds. Fields marked
        read-only are accepted by the API but reserved for Olympex.
      example:
        accountTo: '0x1E67cb01969D79B2B895179e4A07D24a839dBb52'
        chainIdFrom: 137
        chainIdTo: 137
        frequency: 86400
        iterations: 10
        pair: USDC/WETH
        signature: 0x<65-byte signature from accountTo>
        slippage: 1
        tokenAddressFrom: '0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359'
        tokenAddressTo: '0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619'
        tokenSymbolFrom: USDC
        tokenSymbolTo: WETH
        totalAmount: 100
    DcaStrategySuccessResponse:
      type: object
      required:
        - success
        - data
        - meta
      properties:
        success:
          type: boolean
          enum:
            - true
        data:
          $ref: '#/components/schemas/DcaStrategy'
        meta:
          $ref: '#/components/schemas/Meta'
    ErrorResponse:
      type: object
      required:
        - success
        - error
        - meta
      properties:
        success:
          type: boolean
          enum:
            - false
        error:
          $ref: '#/components/schemas/ErrorBody'
        meta:
          $ref: '#/components/schemas/Meta'
    GatewayError:
      type: object
      required:
        - message
      description: >-
        Returned by the API gateway itself: `401` or `403` when the signed
        headers are missing or rejected, `429` when it throttles requests, and
        `500` or `503` when it can't get a response from Olympex in time. It has
        no `success`, `error` or `meta`.
      properties:
        message:
          type: string
          example: Forbidden
    DcaStrategy:
      type: object
      description: A DCA strategy. Olympex can add fields; ignore the ones you don't use.
      required:
        - id
        - accountTo
        - chainIdFrom
        - chainIdTo
        - tokenAddressFrom
        - tokenAddressTo
        - tokenSymbolFrom
        - tokenSymbolTo
        - totalAmount
        - frequency
        - iterations
        - slippage
        - status
        - createdAt
        - updatedAt
      properties:
        id:
          type: string
          format: uuid
          description: Strategy ID.
        accountTo:
          type: string
          description: Maker wallet, as sent.
        chainIdFrom:
          type: integer
          description: Chain ID.
        chainIdTo:
          type: integer
          description: Chain ID. Equal to `chainIdFrom`.
        tokenAddressFrom:
          type: string
          description: Token sold, as sent.
        tokenAddressTo:
          type: string
          description: Token bought, as sent.
        tokenSymbolFrom:
          type: string
          description: Symbol of the token sold.
        tokenSymbolTo:
          type: string
          description: Symbol of the token bought.
        totalAmount:
          type: number
          description: Total amount of the token sold across all orders, human-readable.
        frequency:
          type: integer
          description: Seconds between orders.
        iterations:
          type: integer
          description: Number of orders.
        slippage:
          type: number
          description: Maximum slippage per order, in percent. `0` when it wasn't sent.
        minPrice:
          type: number
          description: Lower price bound. Absent when not set.
        maxPrice:
          type: number
          description: Upper price bound. Absent when not set.
        status:
          type: string
          enum:
            - pending
            - active
            - cancelled
            - finished
          description: >-
            `active`: running. `cancelled`: stopped by you. `finished`: every
            order ran. `pending` is reserved. Treat any other value as not
            final.
        createdAt:
          type: string
          format: date-time
          description: When the strategy was created (ISO 8601, UTC).
        updatedAt:
          type: string
          format: date-time
          description: When the strategy last changed (ISO 8601, UTC).
        deletedAt:
          type: string
          format: date-time
          description: Absent unless the strategy was deleted by Olympex.
    Meta:
      type: object
      required:
        - requestId
        - version
      properties:
        requestId:
          type: string
          description: Unique ID for this request. Include it when you contact support.
        version:
          type: string
          default: v1
          description: API version that served the request.
        accountType:
          type: string
          description: >-
            Account type resolved by the signature check, for example
            `integrator`. Present when the request was authenticated; absent on
            the `404` for an unknown path or method.
        apiKeyId:
          type: string
          format: uuid
          description: >-
            The API key ID that signed the request. Present when the request was
            authenticated; absent on the `404` for an unknown path or method.
    ErrorBody:
      type: object
      required:
        - code
        - message
        - details
      properties:
        code:
          type: string
          description: >-
            Machine-readable error code. `VALIDATION_ERROR` (400),
            `UNAUTHORIZED` (401), `FORBIDDEN` (403), `NOT_FOUND` (404, also for
            an unknown path or method), `CONFLICT` (409), `NO_ROUTE` (422), and
            for 500: `QUOTE_ERROR`, `CROSS_CHAIN_QUOTE_ERROR`, `SWAP_ERROR`,
            `CROSS_CHAIN_SWAP_ERROR`, `SUPPORT_CHAIN_ERROR`,
            `ENABLED_CHAINS_ERROR`, `TOKEN_LIST_ERROR`, `TX_STATUS_ERROR`,
            `INTERNAL_ERROR`. Olympex can add codes: handle an unknown code by
            its HTTP status.
        message:
          type: string
          description: Human-readable summary. Don't parse it.
        details:
          type: array
          items:
            $ref: '#/components/schemas/ErrorDetail'
    ErrorDetail:
      type: object
      additionalProperties: true
      description: >-
        Validation errors carry `field` and `message`; other errors carry
        `message` only.
      properties:
        field:
          type: string
          description: >-
            Dot path of the invalid field, for example `params.chainId`. Empty
            for the top level.
        message:
          type: string
  securitySchemes:
    ApiKeyId:
      type: apiKey
      in: header
      name: x-api-key-id
      description: >-
        Your API key ID (UUID). See [Sign
        requests](https://docs.olympex.io/authentication/sign-requests).
    ValueInfo:
      type: apiKey
      in: header
      name: x-value-info
      description: >-
        Base64 of `timestamp + "\n" + nonce + "\n" + bodyHash`, where
        `timestamp` is Unix seconds, `nonce` is 24 new hexadecimal characters
        and `bodyHash` is the unpadded base64url SHA-256 of the canonical body.
    Passphrase:
      type: apiKey
      in: header
      name: x-passphrase
      description: Your account passphrase. Treat it like the secret key.
    Signature:
      type: apiKey
      in: header
      name: x-signature
      description: >-
        Lowercase hex HMAC-SHA256 (signature v2), keyed with your secret key
        string (UTF-8, not decoded), of seven lines joined with `\n`, with no
        trailing newline: `OLPX-HMAC-SHA256-V2`, `timestamp`, `nonce`, the
        uppercase method, `path`, `canonicalQuery` and `bodyHash`. `path` is the
        request path including `/api/v1`, without the query string, for example
        `/api/v1/limit-order/<id>`. `canonicalQuery` is the query parameters
        decoded (`+` is a space), sorted by key and then by value, re-encoded
        per RFC 3986 and joined with `&`, or the empty string when there is no
        query. Headers signed for one request are rejected on any other. See
        [Sign requests](https://docs.olympex.io/authentication/sign-requests).

````

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