{
  "openapi": "3.1.0",
  "info": {
    "title": "OptAlgo API",
    "version": "1",
    "description": "The OptAlgo API for agents (Claude Code, Codex) and scripts: read the account, run personal bots, send signals, read results, run engine backtests (/v1/backtests). Authenticate with the X-API-Key header - create a key in OptAlgo → AI agents, or let an agent log in with POST /v1/agent/login so the key is never pasted into a chat. Scopes: read = read the account, bots and results; backtest = run engine backtests of your own strategy code (check + submit), nothing else; bots = manage bots and trade them on paper; trade = live trading: signals and closes on live bots, switching to live, creating live bots, webhook keys. A missing scope is 403 scope_required with required_scope and fix_url - a link the owner opens to turn that scope on for this key. Errors are {\"error\": <code>, \"detail\": <message>}. /v1 only gains fields and routes; a breaking change ships as /v2 with 90 days of overlap. Guide for agents: https://docs.optalgo.com/optalgo-llm.md"
  },
  "servers": [
    {
      "url": "https://api.optalgo.com"
    }
  ],
  "tags": [
    {
      "name": "Account"
    },
    {
      "name": "Exchanges"
    },
    {
      "name": "Bots"
    },
    {
      "name": "Multi-symbol"
    },
    {
      "name": "Signals"
    },
    {
      "name": "Results"
    },
    {
      "name": "Backtests"
    },
    {
      "name": "Hosted strategies"
    },
    {
      "name": "Tickets"
    },
    {
      "name": "Connect"
    },
    {
      "name": "Agent login"
    }
  ],
  "paths": {
    "/v1/me": {
      "get": {
        "summary": "Me",
        "description": "The account behind the key: plan, multi-symbol limits, the key itself (scopes, autonomy, limits, pause),\ntickets left today, strike_count {used, max} (strikes of forbidden strategy code; at max API access is\nsuspended), the webhook URL and - when the key has a daily loss limit - today's live realized PnL.",
        "operationId": "me_v1_me_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          }
        },
        "tags": [
          "Account"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v1/exchanges": {
      "get": {
        "summary": "Exchanges",
        "description": "Active exchanges with their account types, and whether the user has connected each one.",
        "operationId": "exchanges_v1_exchanges_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          }
        },
        "tags": [
          "Exchanges"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v1/exchanges/{exchange_id}/symbols": {
      "get": {
        "summary": "Exchange Symbols",
        "description": "Tradable symbols of one exchange account type. `id` is what a bot's symbol and a signal's ticker use\n(BTCUSDT.P = futures, BTCUSDT = spot).",
        "operationId": "exchange_symbols_v1_exchanges__exchange_id__symbols_get",
        "parameters": [
          {
            "required": true,
            "schema": {
              "type": "string",
              "title": "Exchange Id"
            },
            "name": "exchange_id",
            "in": "path"
          },
          {
            "required": true,
            "schema": {
              "type": "string",
              "title": "Account Type"
            },
            "name": "account_type",
            "in": "query"
          },
          {
            "required": false,
            "schema": {
              "type": "string",
              "title": "Q"
            },
            "name": "q",
            "in": "query"
          },
          {
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 500,
              "minimum": 1,
              "title": "Limit",
              "default": 50
            },
            "name": "limit",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "tags": [
          "Exchanges"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v1/prices": {
      "get": {
        "summary": "Prices",
        "description": "The live price of up to 20 symbols, in the order paper fills use (services/live_prices.py): freedx-data's\nprice book first, the exchange ticker only when data has no fresh price (5 s):\n{data: {prices: [{exchange, symbol, price, at, source: data | exchange}][, unavailable: [symbol]]}, next}.\nprice = the last trade (else the bid / ask mid), at = when it was last confirmed (ISO UTC). An agent never\nneeds a price from the web: a signal's stop loss / take profit without entry_price is measured from this price.\n422 invalid_request (every bad symbol at once, in findings), 503 price_unavailable when none has a fresh price.",
        "operationId": "prices_v1_prices_get",
        "parameters": [
          {
            "description": "Comma-separated tickers: BTCUSDT.P (perpetual), BTCUSDT (spot). At most 20.",
            "required": true,
            "schema": {
              "type": "string",
              "maxLength": 1000,
              "title": "Symbols",
              "description": "Comma-separated tickers: BTCUSDT.P (perpetual), BTCUSDT (spot). At most 20."
            },
            "name": "symbols",
            "in": "query"
          },
          {
            "description": "BINANCE (default) or BYBIT",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 32,
              "title": "Exchange",
              "description": "BINANCE (default) or BYBIT",
              "default": "BINANCE"
            },
            "name": "exchange",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "tags": [
          "Exchanges"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v1/connections": {
      "get": {
        "summary": "Connections",
        "description": "The user's exchange connections (never their keys). Connecting an exchange is done in the app.",
        "operationId": "connections_v1_connections_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          }
        },
        "tags": [
          "Exchanges"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v1/bots": {
      "get": {
        "summary": "List Bots",
        "description": "The user's personal bots (\"My Bots\"), newest first; a multi-symbol bot lists its tickers as children.",
        "operationId": "list_bots_v1_bots_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          }
        },
        "tags": [
          "Bots"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      },
      "post": {
        "summary": "Create Bot",
        "description": "single: a bot on one exchange symbol (exchange_id, account_type, symbol, allocated_amount; paper by\ndefault). auto: a paper bot its first signal configures. multi: a multi-symbol bot (max_positions,\nallocated_amount, optional account_type) - its first signal sets exchange, market type and quote. A LIVE\nbot (is_paper false) needs the trade scope (403 scope_required) and its creation is announced to the user\non Telegram.",
        "operationId": "create_bot_v1_bots_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateBotBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "tags": [
          "Bots"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v1/bots/{bot_id}": {
      "get": {
        "summary": "Get Bot",
        "description": "One personal bot in full: settings, mode and its recent paper <-> live flips, PnL, open trade; a\nmulti-symbol bot with its tickers. 404 for another user's bot or a system strategy.",
        "operationId": "get_bot_v1_bots__bot_id__get",
        "parameters": [
          {
            "required": true,
            "schema": {
              "type": "string",
              "title": "Bot Id"
            },
            "name": "bot_id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "tags": [
          "Bots"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      },
      "delete": {
        "summary": "Delete Bot",
        "description": "409 while the bot has an open trade: close (or stop) it first.",
        "operationId": "delete_bot_v1_bots__bot_id__delete",
        "parameters": [
          {
            "required": true,
            "schema": {
              "type": "string",
              "title": "Bot Id"
            },
            "name": "bot_id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "tags": [
          "Bots"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      },
      "patch": {
        "summary": "Update Bot",
        "description": "Only the fields sent change. 409 while the bot has an open trade (and for paper <-> live on a\nmulti-symbol bot with open tickers). max_positions cannot go below the sum of the tickers' weights (422\nweight_budget_exceeded). A paper -> live switch needs the trade scope (403 scope_required); live -> paper and\nevery other field need bots only. A changed allocation, mode or max_positions is announced to the user on\nTelegram; a paper <-> live flip is recorded in the bot's mode_history as this key.",
        "operationId": "update_bot_v1_bots__bot_id__patch",
        "parameters": [
          {
            "required": true,
            "schema": {
              "type": "string",
              "title": "Bot Id"
            },
            "name": "bot_id",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateBotBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "tags": [
          "Bots"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v1/bots/{bot_id}/start": {
      "post": {
        "summary": "Start Bot",
        "description": "Start (activate) the bot so the listener accepts its signals again. Idempotent: an active bot stays\nactive. A live bot does not start while the key is paused (403 key_paused).",
        "operationId": "start_bot_v1_bots__bot_id__start_post",
        "parameters": [
          {
            "required": true,
            "schema": {
              "type": "string",
              "title": "Bot Id"
            },
            "name": "bot_id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "tags": [
          "Bots"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v1/bots/{bot_id}/stop": {
      "post": {
        "summary": "Stop Bot",
        "description": "Stopping a bot CLOSES its open positions (one CLOSE_ALL per open trade), as in the app.",
        "operationId": "stop_bot_v1_bots__bot_id__stop_post",
        "parameters": [
          {
            "required": true,
            "schema": {
              "type": "string",
              "title": "Bot Id"
            },
            "name": "bot_id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "tags": [
          "Bots"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v1/bots/{bot_id}/convert-to-multi": {
      "post": {
        "summary": "Convert Bot",
        "description": "A single bot becomes the first ticker of a new multi-symbol bot; its key and TradingView alert keep\nworking. Returns the new multi-symbol bot.",
        "operationId": "convert_bot_v1_bots__bot_id__convert_to_multi_post",
        "parameters": [
          {
            "required": true,
            "schema": {
              "type": "string",
              "title": "Bot Id"
            },
            "name": "bot_id",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ConvertBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "tags": [
          "Multi-symbol"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v1/bots/{bot_id}/children": {
      "get": {
        "summary": "List Children",
        "description": "The tickers of a multi-symbol bot with their weight, pause state, open position, PnL and slot_amount (what\nthe next entry on that ticker is sized on). weight_sum is what max_positions bounds.",
        "operationId": "list_children_v1_bots__bot_id__children_get",
        "parameters": [
          {
            "required": true,
            "schema": {
              "type": "string",
              "title": "Bot Id"
            },
            "name": "bot_id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "tags": [
          "Multi-symbol"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v1/bots/{bot_id}/children/{ticker}": {
      "delete": {
        "summary": "Remove Child",
        "description": "Remove a ticker from a multi-symbol bot: 409 while it has an open position (close it first). Its trades\nstay in history; a later entry signal for the ticker spawns it again with weight 1.",
        "operationId": "remove_child_v1_bots__bot_id__children__ticker__delete",
        "parameters": [
          {
            "required": true,
            "schema": {
              "type": "string",
              "title": "Bot Id"
            },
            "name": "bot_id",
            "in": "path"
          },
          {
            "required": true,
            "schema": {
              "type": "string",
              "title": "Ticker"
            },
            "name": "ticker",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "tags": [
          "Multi-symbol"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      },
      "patch": {
        "summary": "Update Child",
        "description": "weight: the ticker's share of a slot (0 < weight <= max_positions; 1 = one slot). The next entry on it is\nsized budget / max_positions * weight; an open position is not resized. The weights of all tickers (unset =\n1) must add up to at most max_positions, else 422 weight_budget_exceeded with the sum they would reach.\npaused: true refuses new entries on the ticker (its exits still pass), false resumes it - only while the\nbot is active (409). Note: stopping the bot pauses every ticker and starting it resumes every ticker.\nReturns the ticker's row.",
        "operationId": "update_child_v1_bots__bot_id__children__ticker__patch",
        "parameters": [
          {
            "required": true,
            "schema": {
              "type": "string",
              "title": "Bot Id"
            },
            "name": "bot_id",
            "in": "path"
          },
          {
            "required": true,
            "schema": {
              "type": "string",
              "title": "Ticker"
            },
            "name": "ticker",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ChildBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "tags": [
          "Multi-symbol"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v1/bots/{bot_id}/alert-templates": {
      "get": {
        "summary": "Alert Templates",
        "description": "Ready-to-paste TradingView alert messages for this bot (field names as freedx-signal-listener\nmodels/request_models.py reads them): entry_long, entry_short, close, close_partial, move_stops. A single\nbot's exchange and ticker are filled in; a multi-symbol bot (or a bot still waiting for its first signal)\nkeeps TradingView's {{ticker}} / {{exchange}}. strategy_key is filled in only for a key with the trade\nscope - any other key gets a placeholder to replace from the app.",
        "operationId": "alert_templates_v1_bots__bot_id__alert_templates_get",
        "parameters": [
          {
            "required": true,
            "schema": {
              "type": "string",
              "title": "Bot Id"
            },
            "name": "bot_id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "tags": [
          "Signals"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v1/bots/{bot_id}/signal": {
      "post": {
        "summary": "Send Signal",
        "description": "Send one TradingView-style signal to the bot. 202 = handed to the signal service, NOT executed: poll\nstatus_url for the outcome (rejections are only visible there). A paper bot takes signals from a key with\nthe bots scope; a LIVE bot needs the trade scope (403 scope_required). The checks and the send are\nservices/bot_signals.validate_and_send (shared with hosted strategies).",
        "operationId": "send_signal_v1_bots__bot_id__signal_post",
        "parameters": [
          {
            "required": true,
            "schema": {
              "type": "string",
              "title": "Bot Id"
            },
            "name": "bot_id",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SignalBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "tags": [
          "Signals"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v1/bots/{bot_id}/close": {
      "post": {
        "summary": "Close Position",
        "description": "Close the bot's open position: all of it (no close_ratio, or 1) or a part (close_ratio 0..1 of the filled\nsize). A multi-symbol bot closes one ticker, or every open ticker when no ticker is given. 409 when there is\nnothing open. A paper bot is closed with the bots scope; a LIVE bot needs the trade scope (403\nscope_required).",
        "operationId": "close_position_v1_bots__bot_id__close_post",
        "parameters": [
          {
            "required": true,
            "schema": {
              "type": "string",
              "title": "Bot Id"
            },
            "name": "bot_id",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CloseBody"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "tags": [
          "Signals"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v1/signals/{transaction_id}": {
      "get": {
        "summary": "Signal Outcome",
        "description": "What happened to a signal sent through /v1 (or any signal of the user carrying this transaction_id):\nreceived -> dispatched -> executed, or rejected / skipped / failed / dropped with the reason. Outcomes are\nkept 30 days.",
        "operationId": "signal_outcome_v1_signals__transaction_id__get",
        "parameters": [
          {
            "required": true,
            "schema": {
              "type": "string",
              "title": "Transaction Id"
            },
            "name": "transaction_id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "tags": [
          "Signals"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v1/trades": {
      "get": {
        "summary": "List Trades",
        "description": "The user's trades, newest first. mode: paper / live trades only (all by default). since / until: epoch\nseconds on opened_at. Pass the last row's opened_at as `before` for the next page. format=csv streams up to\nCSV_MAX_ROWS rows (limit ignored) for spreadsheets and dashboards.",
        "operationId": "list_trades_v1_trades_get",
        "parameters": [
          {
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "open",
                "closed",
                "all"
              ],
              "title": "Status",
              "default": "open"
            },
            "name": "status",
            "in": "query"
          },
          {
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "paper",
                "live",
                "all"
              ],
              "title": "Mode",
              "default": "all"
            },
            "name": "mode",
            "in": "query"
          },
          {
            "required": false,
            "schema": {
              "type": "string",
              "title": "Bot Id"
            },
            "name": "bot_id",
            "in": "query"
          },
          {
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 100,
              "minimum": 1,
              "title": "Limit",
              "default": 50
            },
            "name": "limit",
            "in": "query"
          },
          {
            "required": false,
            "schema": {
              "type": "number",
              "title": "Before"
            },
            "name": "before",
            "in": "query"
          },
          {
            "required": false,
            "schema": {
              "type": "number",
              "title": "Since"
            },
            "name": "since",
            "in": "query"
          },
          {
            "required": false,
            "schema": {
              "type": "number",
              "title": "Until"
            },
            "name": "until",
            "in": "query"
          },
          {
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "json",
                "csv"
              ],
              "title": "Format",
              "default": "json"
            },
            "name": "format",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "tags": [
          "Results"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v1/summary": {
      "get": {
        "summary": "Summary",
        "description": "One read for a status report: bots, open trades, PnL (overall and per bot), the monthly trade quota.\n\npnl.total is the account's PnL as the app computes it (StrategyService.get_overall_pnl: realized and\nunrealized, system-strategy subscriptions included). pnl.paper / pnl.live split the REALIZED part by the\ntrade rows' paper flag (_realized_by_mode) - they are summed from the trades collection, so they can differ\nfrom total.realized by what the app's per-strategy PnL counts differently (deleted bots, fees). Unrealized\nPnL needs live prices per open position and is not split: paper.unrealized and live.unrealized are null.",
        "operationId": "summary_v1_summary_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          }
        },
        "tags": [
          "Results"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v1/logs": {
      "get": {
        "summary": "Bot Logs",
        "description": "The bot log feed the app shows (signals received, orders, rejections with their reason), newest first;\nevery personal bot when bot_id is left out. trade_id / transaction_id select the rows of one trade / one\nsignal (system-strategy trades of the user included) and always come with detail. detail=true adds each\nrow's steps (the listener / worker trail) and extra (the signal as received, error details; secrets\nredacted).",
        "operationId": "bot_logs_v1_logs_get",
        "parameters": [
          {
            "required": false,
            "schema": {
              "type": "string",
              "title": "Bot Id"
            },
            "name": "bot_id",
            "in": "query"
          },
          {
            "required": false,
            "schema": {
              "type": "string",
              "title": "Trade Id"
            },
            "name": "trade_id",
            "in": "query"
          },
          {
            "required": false,
            "schema": {
              "type": "string",
              "title": "Transaction Id"
            },
            "name": "transaction_id",
            "in": "query"
          },
          {
            "required": false,
            "schema": {
              "type": "boolean",
              "title": "Detail",
              "default": false
            },
            "name": "detail",
            "in": "query"
          },
          {
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 200,
              "minimum": 1,
              "title": "Limit",
              "default": 50
            },
            "name": "limit",
            "in": "query"
          },
          {
            "required": false,
            "schema": {
              "type": "number",
              "title": "Before"
            },
            "name": "before",
            "in": "query"
          },
          {
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "INFO",
                "WARNING",
                "ERROR"
              ],
              "title": "Level"
            },
            "name": "level",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "tags": [
          "Results"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v1/tickets": {
      "get": {
        "summary": "My Tickets",
        "description": "The user's tickets and in-app reports, newest first (100 max), with the OptAlgo team's reply.",
        "operationId": "my_tickets_v1_tickets_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          }
        },
        "tags": [
          "Tickets"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      },
      "post": {
        "summary": "Submit Tickets",
        "description": "File bug reports, feature requests and questions in ONE batch (1-10 items). Each NEW item becomes its own\nticket in the OptAlgo team's inbox; at most ticket_limit_per_day new tickets per user per UTC day (registry,\ndefault 20; the answer says how many are left). An item that repeats one of the user's open tickets (same\nkind + normalized title, last TICKET_DEDUPE_DAYS days, or earlier in the same batch) is merged into it\n(extra.report.repeats + 1): it answers that ticket's fingerprint with duplicate true and counts nothing.\nA connector (optalgo-mcp report_issue) files with channel \"connector\" and at most CONNECTOR_TICKETS_PER_HOUR\nnew tickets per grant per hour (429 ticket_rate_limited) on top of the daily limit.",
        "operationId": "submit_tickets_v1_tickets_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TicketBatch"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "tags": [
          "Tickets"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v1/bots/{bot_id}/stats": {
      "get": {
        "summary": "Bot Stats",
        "description": "Win / loss, PnL, fees, drawdown and durations of the bot's CLOSED trades (a multi-symbol bot: its\ntickers' trades, also split per ticker), for the whole history or the last 7 / 30 / 90 days by close\ntime; `all` / `paper` / `live` split the same trades by mode. `open_positions` counts the trades open\nnow, whatever the period. Backtest trades are never counted.",
        "operationId": "bot_stats_v1_bots__bot_id__stats_get",
        "parameters": [
          {
            "required": true,
            "schema": {
              "type": "string",
              "title": "Bot Id"
            },
            "name": "bot_id",
            "in": "path"
          },
          {
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "7d",
                "30d",
                "90d",
                "all"
              ],
              "title": "Period",
              "default": "all"
            },
            "name": "period",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "tags": [
          "Results"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v1/bots/{bot_id}/equity": {
      "get": {
        "summary": "Bot Equity",
        "description": "The bot's cumulative realized PnL series, exactly the chart the app draws for it (routes/chart.py with\nstrategy_id: trade_service.get_chart, or the merged children of a multi-symbol bot): one point per\ninterval from the first trade to now, `pnl` being the realized total at the START of that interval;\ncurrent_realized is the total now (trades closed in the current interval).",
        "operationId": "bot_equity_v1_bots__bot_id__equity_get",
        "parameters": [
          {
            "required": true,
            "schema": {
              "type": "string",
              "title": "Bot Id"
            },
            "name": "bot_id",
            "in": "path"
          },
          {
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "1h",
                "1d",
                "3d"
              ],
              "title": "Interval",
              "default": "1d"
            },
            "name": "interval",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "tags": [
          "Results"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v1/equity": {
      "get": {
        "summary": "Combined Equity",
        "description": "The combined cumulative realized PnL curve. scope my_bots: every personal bot of the user (single,\nauto and multi-symbol with their tickers) summed - the My Bots view. scope all: the dashboard curve the\napp draws (personal bots plus OptAlgo strategy subscriptions and funds, routes/chart.py without\nstrategy_id, same cache).",
        "operationId": "combined_equity_v1_equity_get",
        "parameters": [
          {
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "1h",
                "1d",
                "3d"
              ],
              "title": "Interval",
              "default": "1d"
            },
            "name": "interval",
            "in": "query"
          },
          {
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "my_bots",
                "all"
              ],
              "title": "Scope",
              "default": "my_bots"
            },
            "name": "scope",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "tags": [
          "Results"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v1/trades/{trade_id}": {
      "get": {
        "summary": "Get Trade",
        "description": "One trade of the user in full - by trade_id or by the row's _id (a paper trade may have no trade_id),\nas GET /v1/logs?trade_id= accepts. Adds to the list row: exit_history (every partial / final close),\nstop_loss / take_profit / trailing, entry fill state, the PnL percentages and the duration. Exchange\nsecrets never appear in a trade row.",
        "operationId": "get_trade_v1_trades__trade_id__get",
        "parameters": [
          {
            "required": true,
            "schema": {
              "type": "string",
              "title": "Trade Id"
            },
            "name": "trade_id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "tags": [
          "Results"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v1/positions": {
      "get": {
        "summary": "Positions",
        "description": "What the EXCHANGE holds right now: the open futures positions of every connected live exchange account,\nread from the exchange (not from OptAlgo's trades), each attributed to the user's bot when exactly one\nopen trade matches it. `paper` lists the open paper trades (no mark price: paper has no exchange).\nAn exchange account that cannot be read is an `errors` entry, never a failure of the call. Cached\n10 s per user.",
        "operationId": "positions_v1_positions_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          }
        },
        "tags": [
          "Exchanges"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v1/balance": {
      "get": {
        "summary": "Balance",
        "description": "Balances of every connected live exchange account (exchange_service.get_exchange_balance_with_status, the\napp's /exchanges/balance) and of the paper exchange (10,000 USDT per exchange account type, the app's\n/paper_exchanges/balance), with what is allocated to bots and what is free for a new one. `complete` is\nfalse when an account did not answer (it is then missing from `live`). Cached 10 s per user.",
        "operationId": "balance_v1_balance_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          }
        },
        "tags": [
          "Exchanges"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v1/connections/binance/oauth": {
      "post": {
        "summary": "Start Binance Oauth",
        "description": "A Binance authorize link for the key's user. The user opens it, approves on Binance, and the API creates\nthe connection (Binance mints the API key: no secrets pass through the agent). Poll status_url.",
        "operationId": "start_binance_oauth_v1_connections_binance_oauth_post",
        "responses": {
          "201": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          }
        },
        "tags": [
          "Connect"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v1/connections/binance/oauth/{connect_id}": {
      "get": {
        "summary": "Binance Oauth Status",
        "description": "pending -> connected (connection_id) | failed (reason, detail) | expired (link not approved in 15 min).\n404 for an unknown id, another user's, or one older than an hour.",
        "operationId": "binance_oauth_status_v1_connections_binance_oauth__connect_id__get",
        "parameters": [
          {
            "required": true,
            "schema": {
              "type": "string",
              "title": "Connect Id"
            },
            "name": "connect_id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "tags": [
          "Connect"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v1/c/{token}": {
      "get": {
        "summary": "Open a short Binance connect link",
        "description": "The short_url of POST /v1/connections/binance/oauth, opened in a browser (no X-API-Key): 302 to the\nBinance authorize page while the link lives (15 minutes), else 404 text/plain.",
        "operationId": "open_short_link_v1_c__token__get",
        "parameters": [
          {
            "required": true,
            "schema": {
              "type": "string",
              "maxLength": 32,
              "title": "Token"
            },
            "name": "token",
            "in": "path"
          }
        ],
        "responses": {
          "302": {
            "description": "To the Binance authorize page."
          },
          "404": {
            "description": "Unknown or expired link (plain text).",
            "content": {
              "text/plain": {}
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          },
          "429": {
            "description": "More than 30 opens per minute from one IP (plain text).",
            "content": {
              "text/plain": {}
            }
          }
        },
        "tags": [
          "Connect"
        ]
      }
    },
    "/v1/agent/login": {
      "post": {
        "summary": "Start an agent login",
        "description": "Start an agent login. Show the user ONLY verification_uri_complete (or verification_uri + user_code);\nkeep device_code to yourself and poll POST /v1/agent/token with it every `interval` seconds until it\nanswers 200 (or 403 / 410). The login expires after `expires_in` seconds. Ask for the scopes you need with\n`scopes` (e.g. [\"backtest\"] to run engine backtests only, [\"bots\"] to run bots on paper, [\"bots\", \"trade\"] for live trading): the user sees them\npre-ticked and decides; check the scopes the key actually got in the token answer.",
        "operationId": "agent_login_v1_agent_login_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AgentLoginBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "tags": [
          "Agent login"
        ]
      }
    },
    "/v1/agent/token": {
      "post": {
        "summary": "Poll an agent login for the key",
        "description": "Poll an agent login. 428 authorization_pending (poll again after `interval`), 429 slow_down (polling too\nfast), 403 access_denied (the user denied), 410 expired_token (unknown, expired or already used). Approved:\n200 with the new key, minted now and returned ONCE - save the body to a file (curl -o), never print it.\nThe mint can still answer 403 plan_required or 409 key_limit_reached (5 active keys); start again then.",
        "operationId": "agent_token_v1_agent_token_post",
        "parameters": [
          {
            "description": "env: text/plain credentials file",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "json",
                "env"
              ],
              "title": "Format",
              "description": "env: text/plain credentials file",
              "default": "json"
            },
            "name": "format",
            "in": "query"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AgentTokenBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "tags": [
          "Agent login"
        ]
      }
    },
    "/v1/agent/claim": {
      "post": {
        "summary": "Redeem a claim code for the key",
        "description": "Redeem a one-time claim code the user created in the app (OptAlgo → AI agents → claim code): 200 with the\nnew key, minted now and returned ONCE - save the body to a file (curl -o), never print it. 410 expired_token\nfor an unknown, used or expired code; 429 after 5 failed codes from one IP in 10 minutes.",
        "operationId": "agent_claim_v1_agent_claim_post",
        "parameters": [
          {
            "description": "env: text/plain credentials file",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "json",
                "env"
              ],
              "title": "Format",
              "description": "env: text/plain credentials file",
              "default": "json"
            },
            "name": "format",
            "in": "query"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AgentClaimBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "tags": [
          "Agent login"
        ]
      }
    },
    "/v1/backtests/limits": {
      "get": {
        "summary": "V1 Limits",
        "description": "What this account may run on the engine: {plan, enabled, limits, active_jobs, quota: {period, units, used,\nremaining, resets_at, ...}, strike_count: {used, max}} + next. strike_count: strikes of forbidden strategy code;\nat max, API access is suspended.",
        "operationId": "v1_limits_v1_backtests_limits_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          }
        },
        "tags": [
          "Backtests"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v1/backtests/capabilities": {
      "get": {
        "summary": "V1 Capabilities",
        "description": "How to write a strategy: the strategy SDK and primitives, the intents, the RunSpec schema, fee profiles,\nhonesty counters. Read it before writing strategy.py. No strategies are listed: you run your own code.",
        "operationId": "v1_capabilities_v1_backtests_capabilities_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          }
        },
        "tags": [
          "Backtests"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v1/markets": {
      "get": {
        "summary": "V1 Markets",
        "description": "Every market a backtest can use: {data: {exchanges, timeframes, symbols: [{exchange, symbol, type,\nshort_allowed, timeframes: [{timeframe, data_start}], data_start, tick_size, step_size, min_qty,\nmin_notional, backtest[, reason]}], updated_at}, next}. Cached 10 minutes. Only these symbols can be\nbacktested (the platform's market data); `backtest: false` says why.",
        "operationId": "v1_markets_v1_markets_get",
        "parameters": [
          {
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 32,
              "title": "Exchange"
            },
            "name": "exchange",
            "in": "query"
          },
          {
            "description": "FUTURES | SPOT",
            "required": false,
            "schema": {
              "type": "string",
              "title": "Type",
              "description": "FUTURES | SPOT"
            },
            "name": "type",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "tags": [
          "Backtests"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v1/backtests/validate": {
      "post": {
        "summary": "V1 Validate",
        "description": "Free dry run (no quota, nothing queued): {data: {ok, findings: [{code, severity, field, message, fix,\nvalue?, allowed?, example?, suggestion?, symbol?, line?, rule?, snippet?, data_start?}], estimate: {run_s,\nsymbols, bars_per_leg, ...}, cost: {units, run_s, seconds_per_unit}, quota, limits[, inputs]}, next}. Every\nproblem at once: code check, spec schema, symbols / timeframe / data for the window, limits, quota. inputs: what a\nstrategy declaring legs / references / data reads and from when (references_detail[], data_detail[], hosted).",
        "operationId": "v1_validate_v1_backtests_validate_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ValidateBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "tags": [
          "Backtests"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v1/backtests/check": {
      "post": {
        "summary": "V1 Check",
        "description": "Static check of strategy source (nothing runs): {ok, findings: [{line, col, rule, message}], legs, references,\ndata} + next (legs / references / data: what the source declares, 1 / [] / [] when nothing). POST\n/v1/backtests/validate checks the code AND the spec, with a fix per finding.",
        "operationId": "v1_check_v1_backtests_check_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CheckBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "tags": [
          "Backtests"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v1/backtests": {
      "get": {
        "summary": "V1 List",
        "description": "This account's backtests, newest first (via: app | api_key; favorite=true: the starred ones only, starring\nis done in the app) + next.",
        "operationId": "v1_list_v1_backtests_get",
        "parameters": [
          {
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 100,
              "minimum": 1,
              "title": "Limit",
              "default": 50
            },
            "name": "limit",
            "in": "query"
          },
          {
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "title": "Skip",
              "default": 0
            },
            "name": "skip",
            "in": "query"
          },
          {
            "required": false,
            "schema": {
              "type": "string",
              "title": "Status"
            },
            "name": "status",
            "in": "query"
          },
          {
            "required": false,
            "schema": {
              "type": "string",
              "title": "Via"
            },
            "name": "via",
            "in": "query"
          },
          {
            "required": false,
            "schema": {
              "type": "boolean",
              "title": "Favorite"
            },
            "name": "favorite",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "tags": [
          "Backtests"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      },
      "post": {
        "summary": "V1 Submit",
        "description": "Run your strategy code (`source`) as a backtest (spec.research absent) or a research job (spec.research\npresent): 202 {id, status, units, units_estimated, position, eta_s, poll} + next. Without source: 422\nsource_required. Costs quota units by run time (1 unit = up to 10 s; reserved from the estimate, settled to\nthe real run time); over the quota 429 daily_quota / monthly_quota. When busy it queues (fair order: plan\npriority, then round-robin per user). execution.magnify_load defaults to lazy.",
        "operationId": "v1_submit_v1_backtests_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SubmitBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "tags": [
          "Backtests"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v1/backtests/{backtest_id}": {
      "get": {
        "summary": "V1 Get",
        "description": "One backtest: status (queued: position + eta_s), and when done a compact `summary` first (grade, return,\ndrawdown, trades, honesty findings, units charged) then the full result; failed: `fix`. + next.",
        "operationId": "v1_get_v1_backtests__backtest_id__get",
        "parameters": [
          {
            "required": true,
            "schema": {
              "type": "string",
              "title": "Backtest Id"
            },
            "name": "backtest_id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "tags": [
          "Backtests"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v1/backtests/{backtest_id}/files/{name}": {
      "get": {
        "summary": "V1 File",
        "description": "A file of a finished run (equity.arrow, trades.arrow, result.json, ...).",
        "operationId": "v1_file_v1_backtests__backtest_id__files__name__get",
        "parameters": [
          {
            "required": true,
            "schema": {
              "type": "string",
              "title": "Backtest Id"
            },
            "name": "backtest_id",
            "in": "path"
          },
          {
            "required": true,
            "schema": {
              "type": "string",
              "title": "Name"
            },
            "name": "name",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "tags": [
          "Backtests"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v1/backtests/{backtest_id}/source": {
      "get": {
        "summary": "V1 Source",
        "description": "Your own strategy code this backtest ran, as a file (text/x-python, attachment \"<name>-<sha8>.py\", the\nsha256 in X-Source-SHA256). 404 no_source when the run had no code of yours.",
        "operationId": "v1_source_v1_backtests__backtest_id__source_get",
        "parameters": [
          {
            "required": true,
            "schema": {
              "type": "string",
              "title": "Backtest Id"
            },
            "name": "backtest_id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "tags": [
          "Backtests"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v1/backtests/{backtest_id}/chart": {
      "get": {
        "summary": "V1 Chart",
        "description": "A finished backtest's chart data: equity + drawdown downsampled to at most `points` (default 1500, max 5000)\nwith the extremes kept, the trades (2000 most recent), window and symbols. 409 not_ready before it is done.",
        "operationId": "v1_chart_v1_backtests__backtest_id__chart_get",
        "parameters": [
          {
            "required": true,
            "schema": {
              "type": "string",
              "title": "Backtest Id"
            },
            "name": "backtest_id",
            "in": "path"
          },
          {
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 100000,
              "minimum": 1,
              "title": "Points"
            },
            "name": "points",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "tags": [
          "Backtests"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v1/backtests/{backtest_id}/candles": {
      "get": {
        "summary": "V1 Candles",
        "description": "One symbol of a finished backtest: OHLCV in the window (`from` / `to` epoch s) at the backtest timeframe,\naggregated to a coarser bucket past `max_points` (default 2000), the strategy's plot series on the same buckets,\nand the trades + fills in the range. 409 not_ready before it is done.",
        "operationId": "v1_candles_v1_backtests__backtest_id__candles_get",
        "parameters": [
          {
            "required": true,
            "schema": {
              "type": "string",
              "title": "Backtest Id"
            },
            "name": "backtest_id",
            "in": "path"
          },
          {
            "description": "one of the backtest's symbols (default: the first)",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 64,
              "title": "Symbol",
              "description": "one of the backtest's symbols (default: the first)"
            },
            "name": "symbol",
            "in": "query"
          },
          {
            "description": "bucket: a multiple of the run's timeframe (15m, 1h, 4h, 1d, 1w)",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 8,
              "title": "Tf",
              "description": "bucket: a multiple of the run's timeframe (15m, 1h, 4h, 1d, 1w)"
            },
            "name": "tf",
            "in": "query"
          },
          {
            "description": "epoch seconds, clamped to the backtest window",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "title": "From",
              "description": "epoch seconds, clamped to the backtest window"
            },
            "name": "from",
            "in": "query"
          },
          {
            "description": "epoch seconds, clamped to the backtest window",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "title": "To",
              "description": "epoch seconds, clamped to the backtest window"
            },
            "name": "to",
            "in": "query"
          },
          {
            "description": "at most this many candles (default 2000, 50-5000)",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 100000,
              "minimum": 1,
              "title": "Max Points",
              "description": "at most this many candles (default 2000, 50-5000)"
            },
            "name": "max_points",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "tags": [
          "Backtests"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v1/backtests/{backtest_id}/trades.csv": {
      "get": {
        "summary": "V1 Trades Csv",
        "description": "Every trade of a finished backtest as CSV: symbol, side, entry_time, entry_price, exit_time, exit_price, size,\npnl, fees, reason (ISO 8601 UTC; pnl net of fees and funding).",
        "operationId": "v1_trades_csv_v1_backtests__backtest_id__trades_csv_get",
        "parameters": [
          {
            "required": true,
            "schema": {
              "type": "string",
              "title": "Backtest Id"
            },
            "name": "backtest_id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "tags": [
          "Backtests"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v1/strategies/limits": {
      "get": {
        "summary": "Strategies Limits",
        "description": "What this plan allows: hosted_strategy_limit, hosted_symbol_limit, hosted_cpu_s_per_day, slots used / left,\nlive allowed, paper trades left this month, the live eligibility rule, whether hosting is available.",
        "operationId": "strategies_limits_v1_strategies_limits_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          }
        },
        "tags": [
          "Hosted strategies"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v1/strategies": {
      "get": {
        "summary": "List Strategies",
        "description": "The account's hosted strategies, newest first (deleted ones left out).",
        "operationId": "list_strategies_v1_strategies_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          }
        },
        "tags": [
          "Hosted strategies"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      },
      "post": {
        "summary": "Deploy Strategy",
        "description": "Deploy a backtested strategy on paper (see the module docstring). dry_run=true runs the whole gate and\ncreates nothing.",
        "operationId": "deploy_strategy_v1_strategies_post",
        "parameters": [
          {
            "required": false,
            "schema": {
              "type": "boolean",
              "title": "Dry Run",
              "default": false
            },
            "name": "dry_run",
            "in": "query"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DeployBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "tags": [
          "Hosted strategies"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v1/strategies/{hosted_id}": {
      "get": {
        "summary": "Get Strategy",
        "operationId": "get_strategy_v1_strategies__hosted_id__get",
        "parameters": [
          {
            "required": true,
            "schema": {
              "type": "string",
              "title": "Hosted Id"
            },
            "name": "hosted_id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "tags": [
          "Hosted strategies"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      },
      "delete": {
        "summary": "Delete Strategy",
        "description": "Flat: removed now. Open positions: winding_down (only exits until flat), or close=true to close them now\n(a LIVE strategy's close needs the trade scope).",
        "operationId": "delete_strategy_v1_strategies__hosted_id__delete",
        "parameters": [
          {
            "required": true,
            "schema": {
              "type": "string",
              "title": "Hosted Id"
            },
            "name": "hosted_id",
            "in": "path"
          },
          {
            "required": false,
            "schema": {
              "type": "boolean",
              "title": "Close",
              "default": false
            },
            "name": "close",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "tags": [
          "Hosted strategies"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      },
      "patch": {
        "summary": "Patch Strategy",
        "description": "name / allocated_amount / on_leg_failure (unwind | keep, multi-leg strategies), on paper only (409\nlive_strategy otherwise; 409 while a position is open for an allocation change).",
        "operationId": "patch_strategy_v1_strategies__hosted_id__patch",
        "parameters": [
          {
            "required": true,
            "schema": {
              "type": "string",
              "title": "Hosted Id"
            },
            "name": "hosted_id",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PatchBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "tags": [
          "Hosted strategies"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v1/strategies/{hosted_id}/decisions": {
      "get": {
        "summary": "Strategy Decisions",
        "description": "Newest first: per bar a record row (symbol \"*\": decided / skipped / error / paused with a plain message),\na row per action (outcome sent / refused / skipped / duplicate + code + message; a sent one carries its\nsignal_status from the ledger, the transaction_id to follow and the trade_id when resolvable) and a row per\nquiet symbol. Kept 90 days.",
        "operationId": "strategy_decisions_v1_strategies__hosted_id__decisions_get",
        "parameters": [
          {
            "required": true,
            "schema": {
              "type": "string",
              "title": "Hosted Id"
            },
            "name": "hosted_id",
            "in": "path"
          },
          {
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 50,
              "title": "Symbol"
            },
            "name": "symbol",
            "in": "query"
          },
          {
            "description": "bar_t (epoch s): older rows only",
            "required": false,
            "schema": {
              "type": "integer",
              "title": "Before",
              "description": "bar_t (epoch s): older rows only"
            },
            "name": "before",
            "in": "query"
          },
          {
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 200,
              "minimum": 1,
              "title": "Limit",
              "default": 50
            },
            "name": "limit",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "tags": [
          "Hosted strategies"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v1/strategies/{hosted_id}/logs": {
      "get": {
        "summary": "Strategy Logs",
        "description": "The bot's log feed as My Bots shows it: signals received, orders, refusals with their reason, status lines.",
        "operationId": "strategy_logs_v1_strategies__hosted_id__logs_get",
        "parameters": [
          {
            "required": true,
            "schema": {
              "type": "string",
              "title": "Hosted Id"
            },
            "name": "hosted_id",
            "in": "path"
          },
          {
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 200,
              "minimum": 1,
              "title": "Limit",
              "default": 50
            },
            "name": "limit",
            "in": "query"
          },
          {
            "required": false,
            "schema": {
              "type": "number",
              "title": "Before"
            },
            "name": "before",
            "in": "query"
          },
          {
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "INFO",
                "WARNING",
                "ERROR"
              ],
              "title": "Level"
            },
            "name": "level",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "tags": [
          "Hosted strategies"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v1/strategies/{hosted_id}/source": {
      "get": {
        "summary": "Strategy Source",
        "description": "Your own strategy code this hosted strategy runs, as a .py file (match it with code.source_sha256).",
        "operationId": "strategy_source_v1_strategies__hosted_id__source_get",
        "parameters": [
          {
            "required": true,
            "schema": {
              "type": "string",
              "title": "Hosted Id"
            },
            "name": "hosted_id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "tags": [
          "Hosted strategies"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v1/strategies/{hosted_id}/pause": {
      "post": {
        "summary": "Pause Strategy",
        "operationId": "pause_strategy_v1_strategies__hosted_id__pause_post",
        "parameters": [
          {
            "required": true,
            "schema": {
              "type": "string",
              "title": "Hosted Id"
            },
            "name": "hosted_id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "tags": [
          "Hosted strategies"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v1/strategies/{hosted_id}/resume": {
      "post": {
        "summary": "Resume Strategy",
        "operationId": "resume_strategy_v1_strategies__hosted_id__resume_post",
        "parameters": [
          {
            "required": true,
            "schema": {
              "type": "string",
              "title": "Hosted Id"
            },
            "name": "hosted_id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "tags": [
          "Hosted strategies"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v1/strategies/{hosted_id}/request-live": {
      "post": {
        "summary": "Request Live",
        "description": "Ask the account owner to take the strategy live. Plus / Pro and the trade scope; it NEVER flips anything:\nthe owner confirms in the app (My Bots). Never gated by the recommended paper period (owner 2026-10-10): the\nanswer's live_eligibility carries the progress and recommended_ready; before it, the owner may still confirm\nearly by accepting the risk in the app. Never tell the user it is live until GET says status live.",
        "operationId": "request_live_v1_strategies__hosted_id__request_live_post",
        "parameters": [
          {
            "required": true,
            "schema": {
              "type": "string",
              "title": "Hosted Id"
            },
            "name": "hosted_id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "tags": [
          "Hosted strategies"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v1/strategies/{hosted_id}/compare": {
      "get": {
        "summary": "List Compares",
        "operationId": "list_compares_v1_strategies__hosted_id__compare_get",
        "parameters": [
          {
            "required": true,
            "schema": {
              "type": "string",
              "title": "Hosted Id"
            },
            "name": "hosted_id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "tags": [
          "Hosted strategies"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      },
      "post": {
        "summary": "Compare Strategy",
        "description": "Compare the strategy's real trades (paper or live) with a backtest of the same code, params and symbols over\nthe period it has been running. dry_run=true: the estimate (units, run_s, window, mode), free. Else 202: the\nbacktest is queued and charged by run time like any backtest (the same window end again is reused, free);\npoll GET .../compare/{id} until status is done.",
        "operationId": "compare_strategy_v1_strategies__hosted_id__compare_post",
        "parameters": [
          {
            "required": true,
            "schema": {
              "type": "string",
              "title": "Hosted Id"
            },
            "name": "hosted_id",
            "in": "path"
          },
          {
            "required": false,
            "schema": {
              "type": "boolean",
              "title": "Dry Run",
              "default": false
            },
            "name": "dry_run",
            "in": "query"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/routes__v1_strategies__CompareBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "tags": [
          "Hosted strategies"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v1/strategies/{hosted_id}/compare/{compare_id}": {
      "get": {
        "summary": "Get Compare",
        "description": "status queued / running (position, eta_s) until the backtest is done, then the report: summary\n{decisions_matched, decisions_total, match_rate, missed, extra, pnl_actual, pnl_backtest, pnl_diff,\navg_entry_slippage_bps, avg_exit_slippage_bps, fees_actual, fees_backtest, ...}, mismatches (each with bar_t\nand reason), matched (paged: offset / limit), histogram, open_positions; actual=true adds actual_trades.",
        "operationId": "get_compare_v1_strategies__hosted_id__compare__compare_id__get",
        "parameters": [
          {
            "required": true,
            "schema": {
              "type": "string",
              "title": "Hosted Id"
            },
            "name": "hosted_id",
            "in": "path"
          },
          {
            "required": true,
            "schema": {
              "type": "string",
              "title": "Compare Id"
            },
            "name": "compare_id",
            "in": "path"
          },
          {
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "title": "Offset",
              "default": 0
            },
            "name": "offset",
            "in": "query"
          },
          {
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 200,
              "minimum": 1,
              "title": "Limit",
              "default": 50
            },
            "name": "limit",
            "in": "query"
          },
          {
            "required": false,
            "schema": {
              "type": "boolean",
              "title": "Actual",
              "default": false
            },
            "name": "actual",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "tags": [
          "Hosted strategies"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    }
  },
  "components": {
    "schemas": {
      "AgentClaimBody": {
        "properties": {
          "claim_code": {
            "type": "string",
            "title": "Claim Code",
            "description": "OPTC-XXXX-XXXX-XXXX-XXXX from the app (case and dashes optional)."
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "claim_code"
        ],
        "title": "AgentClaimBody"
      },
      "AgentLoginBody": {
        "properties": {
          "client_name": {
            "type": "string",
            "maxLength": 60,
            "title": "Client Name",
            "description": "Shown to the user when they approve, e.g. \"Claude Code on MacBook\"."
          },
          "scopes": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "maxItems": 10,
            "title": "Scopes",
            "description": "The scopes the agent asks for (read, backtest, bots, trade; read is always added): pre-ticked on the approval page. A suggestion only - the user chooses the scopes the key gets. backtest = run engine backtests only; bots = manage bots and trade them on paper; trade = live trading. Unknown scope: 422 invalid_scope."
          }
        },
        "additionalProperties": false,
        "type": "object",
        "title": "AgentLoginBody"
      },
      "AgentTokenBody": {
        "properties": {
          "device_code": {
            "type": "string",
            "title": "Device Code",
            "description": "The device_code from POST /v1/agent/login."
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "device_code"
        ],
        "title": "AgentTokenBody"
      },
      "CheckBody": {
        "properties": {
          "source": {
            "type": "string",
            "title": "Source"
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "source"
        ],
        "title": "CheckBody"
      },
      "ChildBody": {
        "properties": {
          "weight": {
            "type": "number",
            "exclusiveMinimum": 0,
            "title": "Weight"
          },
          "paused": {
            "type": "boolean",
            "title": "Paused"
          }
        },
        "additionalProperties": false,
        "type": "object",
        "title": "ChildBody"
      },
      "CloseBody": {
        "properties": {
          "ticker": {
            "type": "string",
            "maxLength": 50,
            "title": "Ticker"
          },
          "close_ratio": {
            "type": "number",
            "maximum": 1,
            "exclusiveMinimum": 0,
            "title": "Close Ratio"
          }
        },
        "additionalProperties": false,
        "type": "object",
        "title": "CloseBody"
      },
      "ConvertBody": {
        "properties": {
          "max_positions": {
            "type": "integer",
            "minimum": 1,
            "title": "Max Positions"
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "max_positions"
        ],
        "title": "ConvertBody"
      },
      "CreateBotBody": {
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "single",
              "auto",
              "multi"
            ],
            "title": "Type"
          },
          "name": {
            "type": "string",
            "maxLength": 100,
            "title": "Name"
          },
          "exchange_id": {
            "type": "string",
            "title": "Exchange Id"
          },
          "account_type": {
            "type": "string",
            "enum": [
              "SPOT",
              "FUTURES",
              "MARGIN"
            ],
            "title": "Account Type"
          },
          "symbol": {
            "type": "string",
            "title": "Symbol"
          },
          "is_paper": {
            "type": "boolean",
            "title": "Is Paper",
            "default": true
          },
          "allocated_amount": {
            "type": "number",
            "minimum": 0,
            "title": "Allocated Amount"
          },
          "max_positions": {
            "type": "integer",
            "minimum": 1,
            "title": "Max Positions"
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "type"
        ],
        "title": "CreateBotBody"
      },
      "DeployBody": {
        "properties": {
          "backtest_id": {
            "type": "string",
            "maxLength": 64,
            "minLength": 1,
            "title": "Backtest Id"
          },
          "name": {
            "type": "string",
            "maxLength": 100,
            "title": "Name"
          },
          "symbols": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "maxItems": 50,
            "title": "Symbols"
          },
          "params": {
            "type": "object",
            "title": "Params"
          },
          "timeframe": {
            "type": "string",
            "maxLength": 10,
            "title": "Timeframe"
          },
          "exchange": {
            "type": "string",
            "maxLength": 20,
            "title": "Exchange"
          },
          "leverage": {
            "type": "number",
            "maximum": 125,
            "minimum": 1,
            "title": "Leverage"
          },
          "source": {
            "type": "string",
            "maxLength": 65536,
            "title": "Source"
          },
          "source_sha256": {
            "type": "string",
            "pattern": "^[0-9a-f]{64}$",
            "title": "Source Sha256"
          },
          "allocated_amount": {
            "type": "number",
            "exclusiveMinimum": 0,
            "title": "Allocated Amount"
          },
          "on_error": {
            "type": "string",
            "enum": [
              "hold",
              "close"
            ],
            "title": "On Error"
          },
          "on_leg_failure": {
            "type": "string",
            "enum": [
              "unwind",
              "keep"
            ],
            "title": "On Leg Failure"
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "backtest_id"
        ],
        "title": "DeployBody"
      },
      "HTTPValidationError": {
        "properties": {
          "detail": {
            "items": {
              "$ref": "#/components/schemas/ValidationError"
            },
            "type": "array",
            "title": "Detail"
          }
        },
        "type": "object",
        "title": "HTTPValidationError"
      },
      "PatchBody": {
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 100,
            "minLength": 1,
            "title": "Name"
          },
          "allocated_amount": {
            "type": "number",
            "exclusiveMinimum": 0,
            "title": "Allocated Amount"
          },
          "on_leg_failure": {
            "type": "string",
            "enum": [
              "unwind",
              "keep"
            ],
            "title": "On Leg Failure"
          }
        },
        "additionalProperties": false,
        "type": "object",
        "title": "PatchBody"
      },
      "SignalBody": {
        "properties": {
          "position_side": {
            "type": "string",
            "title": "Position Side"
          },
          "ticker": {
            "type": "string",
            "maxLength": 50,
            "title": "Ticker"
          },
          "exchange": {
            "type": "string",
            "maxLength": 50,
            "title": "Exchange"
          },
          "action": {
            "type": "string",
            "enum": [
              "BUY",
              "SELL"
            ],
            "title": "Action"
          },
          "trade_id": {
            "type": "string",
            "maxLength": 36,
            "title": "Trade Id"
          },
          "entry_price": {
            "type": "number",
            "title": "Entry Price"
          },
          "stop_loss_price": {
            "type": "number",
            "title": "Stop Loss Price"
          },
          "take_profit_price": {
            "type": "number",
            "title": "Take Profit Price"
          },
          "stop_loss_pct": {
            "type": "number",
            "exclusiveMaximum": 100,
            "exclusiveMinimum": 0,
            "title": "Stop Loss Pct"
          },
          "take_profit_pct": {
            "type": "number",
            "maximum": 1000,
            "exclusiveMinimum": 0,
            "title": "Take Profit Pct"
          },
          "entry_order_type": {
            "type": "string",
            "title": "Entry Order Type"
          },
          "entry_order_time_in_force_type": {
            "type": "string",
            "title": "Entry Order Time In Force Type"
          },
          "exit_order_type": {
            "type": "string",
            "title": "Exit Order Type"
          },
          "exit_order_time_in_force_type": {
            "type": "string",
            "title": "Exit Order Time In Force Type"
          },
          "chase_order_type": {
            "type": "string",
            "title": "Chase Order Type"
          },
          "chase_exit_order_type": {
            "type": "string",
            "title": "Chase Exit Order Type"
          },
          "margin_mode": {
            "type": "string",
            "enum": [
              "isolated",
              "cross"
            ],
            "title": "Margin Mode"
          },
          "multi_asset_mode": {
            "type": "boolean",
            "title": "Multi Asset Mode"
          },
          "leverage": {
            "type": "integer",
            "maximum": 125,
            "minimum": 1,
            "title": "Leverage"
          },
          "tradable_ratio": {
            "type": "number",
            "maximum": 1,
            "exclusiveMinimum": 0,
            "title": "Tradable Ratio"
          },
          "close_ratio": {
            "type": "number",
            "maximum": 1,
            "exclusiveMinimum": 0,
            "title": "Close Ratio"
          },
          "callback_rate": {
            "type": "number",
            "title": "Callback Rate"
          },
          "is_trailing_stop_enabled": {
            "type": "boolean",
            "title": "Is Trailing Stop Enabled"
          },
          "cancel_stop_loss": {
            "type": "boolean",
            "title": "Cancel Stop Loss"
          },
          "cancel_take_profit": {
            "type": "boolean",
            "title": "Cancel Take Profit"
          },
          "safety_check": {
            "type": "boolean",
            "title": "Safety Check"
          },
          "safety_check_interval_minutes": {
            "type": "integer",
            "title": "Safety Check Interval Minutes"
          },
          "in_position": {
            "type": "boolean",
            "title": "In Position"
          },
          "reason": {
            "type": "string",
            "maxLength": 200,
            "title": "Reason"
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "position_side"
        ],
        "title": "SignalBody",
        "description": "The TradingView webhook fields an agent may send (freedx-signal-listener models/request_models.py).\nstrategy_key, exchange of a configured bot and transaction_id are filled in by the API."
      },
      "SubmitBody": {
        "properties": {
          "spec": {
            "type": "object",
            "title": "Spec"
          },
          "source": {
            "type": "string",
            "title": "Source"
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "spec"
        ],
        "title": "SubmitBody"
      },
      "TicketBatch": {
        "properties": {
          "items": {
            "items": {
              "$ref": "#/components/schemas/TicketItem"
            },
            "type": "array",
            "title": "Items"
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "items"
        ],
        "title": "TicketBatch"
      },
      "TicketContext": {
        "properties": {
          "bot_id": {
            "type": "string",
            "maxLength": 100,
            "title": "Bot Id"
          },
          "transaction_id": {
            "type": "string",
            "maxLength": 100,
            "title": "Transaction Id"
          },
          "trade_id": {
            "type": "string",
            "maxLength": 100,
            "title": "Trade Id"
          },
          "backtest_id": {
            "type": "string",
            "maxLength": 100,
            "title": "Backtest Id"
          },
          "hosted_id": {
            "type": "string",
            "maxLength": 100,
            "title": "Hosted Id"
          },
          "request_id": {
            "type": "string",
            "maxLength": 100,
            "title": "Request Id"
          }
        },
        "additionalProperties": false,
        "type": "object",
        "title": "TicketContext"
      },
      "TicketItem": {
        "properties": {
          "kind": {
            "type": "string",
            "enum": [
              "bug",
              "feature",
              "question"
            ],
            "title": "Kind"
          },
          "title": {
            "type": "string",
            "title": "Title"
          },
          "body": {
            "type": "string",
            "title": "Body"
          },
          "context": {
            "$ref": "#/components/schemas/TicketContext"
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "kind",
          "title",
          "body"
        ],
        "title": "TicketItem"
      },
      "UpdateBotBody": {
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 100,
            "minLength": 1,
            "title": "Name"
          },
          "allocated_amount": {
            "type": "number",
            "minimum": 0,
            "title": "Allocated Amount"
          },
          "is_paper": {
            "type": "boolean",
            "title": "Is Paper"
          },
          "max_positions": {
            "type": "integer",
            "minimum": 1,
            "title": "Max Positions"
          }
        },
        "additionalProperties": false,
        "type": "object",
        "title": "UpdateBotBody"
      },
      "ValidateBody": {
        "properties": {
          "spec": {
            "type": "object",
            "title": "Spec"
          },
          "source": {
            "type": "string",
            "title": "Source"
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "spec"
        ],
        "title": "ValidateBody"
      },
      "ValidationError": {
        "properties": {
          "loc": {
            "items": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "integer"
                }
              ]
            },
            "type": "array",
            "title": "Location"
          },
          "msg": {
            "type": "string",
            "title": "Message"
          },
          "type": {
            "type": "string",
            "title": "Error Type"
          }
        },
        "type": "object",
        "required": [
          "loc",
          "msg",
          "type"
        ],
        "title": "ValidationError"
      },
      "routes__v1_strategies__CompareBody": {
        "properties": {
          "mode": {
            "type": "string",
            "enum": [
              "paper",
              "live"
            ],
            "title": "Mode"
          }
        },
        "additionalProperties": false,
        "type": "object",
        "title": "CompareBody"
      }
    },
    "securitySchemes": {
      "ApiKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "X-API-Key",
        "description": "An OptAlgo API key (oa_live_...). Scopes: read (always) = read the account, bots and results; backtest = run engine backtests (POST /v1/backtests, /v1/backtests/check) and nothing else; bots = manage bots and trade them on paper; trade = live trading: signals and closes on live bots, switching to live, creating live bots, webhook keys. bots and trade also allow backtests."
      }
    }
  }
}
