{
  "openapi": "3.1.0",
  "info": {
    "title": "EX7 Capital API",
    "description": "Trading signal delivery and portfolio management",
    "version": "1.0.0",
    "x-ex7-generated": {
      "generated_at": "2026-06-06T19:37:55.626Z",
      "source": "https://api.ex7capital.com/openapi.json",
      "note": "Filtered build; admin/internal routes stripped."
    }
  },
  "paths": {
    "/api/health": {
      "get": {
        "tags": [
          "health"
        ],
        "summary": "Health",
        "operationId": "health_api_health_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          }
        }
      }
    },
    "/api/legacy/signals": {
      "get": {
        "tags": [
          "signals-legacy"
        ],
        "summary": "Get Signals",
        "description": "Get all signals from the last N hours.",
        "operationId": "get_signals_api_legacy_signals_get",
        "parameters": [
          {
            "name": "hours",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 168,
              "minimum": 1,
              "default": 24,
              "title": "Hours"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/legacy/signals/{instrument}": {
      "get": {
        "tags": [
          "signals-legacy"
        ],
        "summary": "Get Signals By Instrument",
        "description": "Get signals for a specific instrument.",
        "operationId": "get_signals_by_instrument_api_legacy_signals__instrument__get",
        "parameters": [
          {
            "name": "instrument",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Instrument"
            }
          },
          {
            "name": "hours",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 168,
              "minimum": 1,
              "default": 24,
              "title": "Hours"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/portfolio": {
      "get": {
        "tags": [
          "portfolio"
        ],
        "summary": "Get Portfolio",
        "description": "Portfolio summary: signals taken today, cumulative stats.",
        "operationId": "get_portfolio_api_portfolio_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          }
        }
      }
    },
    "/api/risk": {
      "get": {
        "tags": [
          "risk"
        ],
        "summary": "Get Risk",
        "description": "Per-user, per-mode risk state. Mirrors signals/risk_gate.is_blocked.\n\nResponse shape: see risk-route-rewrite-2026-04-19.md §4.\n\nAuth: required via `current_user` (Supabase JWT). 401 if missing/invalid.\nMode: validated against {'paper', 'live'}, 422 on anything else.\nPool: acquired from `app.state.supabase` (where `signals` lives).\n\nOn DB error: returns `trading_allowed=false` with `blocked_reason.breaker='error'`.\nNever returns 500 — fail-closed at the reporting layer too, so the UI\nshows \"trading blocked\" during an outage instead of silently reverting\nto \"trading_allowed=true\" and confusing the user.",
        "operationId": "get_risk_api_risk_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "mode",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Risk pool to report on ('paper' | 'live'). Paper losses do NOT consume live slots and vice versa.",
              "default": "paper",
              "title": "Mode"
            },
            "description": "Risk pool to report on ('paper' | 'live'). Paper losses do NOT consume live slots and vice versa."
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true,
                  "title": "Response Get Risk Api Risk Get"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/risk/blocked": {
      "get": {
        "tags": [
          "risk"
        ],
        "summary": "Get Blocked",
        "description": "List the current user's recently-blocked signals.\n\nBacked by `signals_blocked` (migration 021), which is written by\nthe publisher-boundary risk gate (see src/api/signals/risk_gate.py\n::record_blocked) every time IRON LAW §4 denies a would-be\npublication.\n\nEach row answers \"why didn't my signal fire?\" with enough context\nfor a forensic post-mortem:\n  - triggered_limit: breaker name ('daily_loss_limit', ...)\n  - reason:          machine-readable tag ('daily_loss_limit_breached')\n  - observed:        the tripping value ('-500.00' or '6')\n  - limit:           the threshold ('-500.00' or '6')\n  - reason_json:     full BlockedReason snapshot (limits + checked_at)\n\nAuth: required via `current_user` (Supabase JWT). 401 if missing.\nPool: acquired from `app.state.supabase` (where `signals_blocked`\n  lives). 503 when the pool isn't wired (dev env).\nRLS: `signals_blocked_select_own` restricts SELECT to the\n  authenticated user. The helper also filters by user_id explicitly.\n\nResponse shape:\n  {\n    \"timestamp\": \"2026-04-20T...\",\n    \"items\": [\n      {\n        \"id\": \"<uuid>\",\n        \"user_id\": \"<uuid>\",\n        \"strategy_id\": \"<uuid|null>\",\n        \"strategy_version\": <int|null>,\n        \"instrument\": \"MNQ\",\n        \"timeframe\": \"2m\",\n        \"bar_ts\": \"2026-04-20T13:30:00+00:00\",\n        \"mode\": \"paper\" | \"live\",\n        \"side\": \"long\" | \"short\" | null,\n        \"triggered_limit\": \"daily_loss_limit\",\n        \"reason\": \"daily_loss_limit_breached\",\n        \"observed\": \"-500.00\",\n        \"limit\": \"-500.00\",\n        \"reason_json\": { ... },\n        \"blocked_at\": \"2026-04-20T13:30:05+00:00\"\n      },\n      ...\n    ],\n    \"total\": <int>,\n    \"limit\": <int>,\n    \"offset\": <int>,\n  }",
        "operationId": "get_blocked_api_risk_blocked_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 200,
              "minimum": 1,
              "description": "Max rows to return (newest first). 1-200.",
              "default": 50,
              "title": "Limit"
            },
            "description": "Max rows to return (newest first). 1-200."
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "description": "Rows to skip (for simple pagination). >= 0.",
              "default": 0,
              "title": "Offset"
            },
            "description": "Rows to skip (for simple pagination). >= 0."
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true,
                  "title": "Response Get Blocked Api Risk Blocked Get"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/performance": {
      "get": {
        "tags": [
          "performance"
        ],
        "summary": "Get Performance",
        "description": "Per-strategy backtest performance and live stats.",
        "operationId": "get_performance_api_performance_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          }
        }
      }
    },
    "/api/instruments": {
      "get": {
        "tags": [
          "instruments"
        ],
        "summary": "Get Instruments",
        "description": "List all instruments with current market data.",
        "operationId": "get_instruments_api_instruments_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          }
        }
      }
    },
    "/api/waitlist": {
      "post": {
        "tags": [
          "waitlist"
        ],
        "summary": "Add To Waitlist",
        "description": "Add email to waitlist.",
        "operationId": "add_to_waitlist_api_waitlist_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WaitlistEntry"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/waitlist/count": {
      "get": {
        "tags": [
          "waitlist"
        ],
        "summary": "Waitlist Count",
        "description": "Public count of waitlist signups.",
        "operationId": "waitlist_count_api_waitlist_count_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          }
        }
      }
    },
    "/api/engines": {
      "get": {
        "tags": [
          "strategies"
        ],
        "summary": "List Engines",
        "description": "List all node types the strategy-builder can render.\n\nAuth required so we don't leak our stack to scrapers; the info is not secret\nbut there's no reason for anonymous traffic to hit it either.",
        "operationId": "list_engines_api_engines_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "items": {
                    "$ref": "#/components/schemas/EngineOut"
                  },
                  "type": "array",
                  "title": "Response List Engines Api Engines Get"
                }
              }
            }
          }
        },
        "security": [
          {
            "HTTPBearer": []
          }
        ]
      }
    },
    "/api/strategies": {
      "get": {
        "tags": [
          "strategies"
        ],
        "summary": "List Strategies",
        "operationId": "list_strategies_api_strategies_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Status"
            }
          },
          {
            "name": "instrument",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Instrument"
            }
          },
          {
            "name": "tag",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Tag"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "updated_at cursor from previous page",
              "title": "Cursor"
            },
            "description": "updated_at cursor from previous page"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 200,
              "minimum": 1,
              "default": 50,
              "title": "Limit"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StrategyList"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "strategies"
        ],
        "summary": "Create Strategy",
        "operationId": "create_strategy_api_strategies_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/StrategyCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StrategyCreateOut"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/strategies/{strategy_id}": {
      "get": {
        "tags": [
          "strategies"
        ],
        "summary": "Get Strategy",
        "operationId": "get_strategy_api_strategies__strategy_id__get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "strategy_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Strategy Id"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StrategyOut"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "put": {
        "tags": [
          "strategies"
        ],
        "summary": "Update Strategy",
        "operationId": "update_strategy_api_strategies__strategy_id__put",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "strategy_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Strategy Id"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/StrategyUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StrategyUpdateOut"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "strategies"
        ],
        "summary": "Delete Strategy",
        "operationId": "delete_strategy_api_strategies__strategy_id__delete",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "strategy_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Strategy Id"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/strategies/{strategy_id}/versions": {
      "get": {
        "tags": [
          "strategies-versions"
        ],
        "summary": "List Strategy Versions",
        "description": "Return one page of version summaries. Most recent version first.\n\nResponse shape:\n  {\n    \"items\": [VersionSummary, ...],\n    \"next_cursor\": int | null\n  }",
        "operationId": "list_strategy_versions_api_strategies__strategy_id__versions_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "strategy_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Strategy Id"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "integer",
                  "minimum": 1
                },
                {
                  "type": "null"
                }
              ],
              "description": "last version integer from previous page (DESC pagination)",
              "title": "Cursor"
            },
            "description": "last version integer from previous page (DESC pagination)"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 200,
              "minimum": 1,
              "default": 50,
              "title": "Limit"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true,
                  "title": "Response List Strategy Versions Api Strategies  Strategy Id  Versions Get"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/strategies/{strategy_id}/versions/{version}": {
      "get": {
        "tags": [
          "strategies-versions"
        ],
        "summary": "Get Strategy Version",
        "operationId": "get_strategy_version_api_strategies__strategy_id__versions__version__get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "strategy_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Strategy Id"
            }
          },
          {
            "name": "version",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "title": "Version"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VersionDetail"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/strategies/{strategy_id}/rollback": {
      "post": {
        "tags": [
          "strategies-versions"
        ],
        "summary": "Rollback Strategy",
        "description": "Create a new version whose graph matches `to_version`.\n\nReturns { id, current_version }. Maps:\n  StrategyNotFound          → 404\n  VersionNotFound           → 404\n  CannotRollbackToCurrent   → 409",
        "operationId": "rollback_strategy_api_strategies__strategy_id__rollback_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "strategy_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Strategy Id"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RollbackRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true,
                  "title": "Response Rollback Strategy Api Strategies  Strategy Id  Rollback Post"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/strategies/{source_id}/clone": {
      "post": {
        "tags": [
          "strategies-clone"
        ],
        "summary": "Clone Strategy",
        "description": "Clone one of the caller's strategies into a new strategies row at version 1.",
        "operationId": "clone_strategy_api_strategies__source_id__clone_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "source_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Source Id"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CloneRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StrategyCreateOut"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/strategies/from-fixture/{slug}": {
      "post": {
        "tags": [
          "fixtures"
        ],
        "summary": "Create Strategy From Fixture",
        "operationId": "create_strategy_from_fixture_api_strategies_from_fixture__slug__post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Slug"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateFromFixtureBody"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StrategyCreateOut"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/strategies/{strategy_id}/export": {
      "get": {
        "tags": [
          "strategies-import-export"
        ],
        "summary": "Export Strategy",
        "description": "Return a portable JSON representation of a strategy's head version.\n\nPayload shape is defined by spec §8: format stamp, exported_at ISO8601,\nname/description/instrument/timeframe/tags, and the full graph (nodes,\nedges, meta). Internal ids, user_id, and timestamps other than\n`exported_at` are stripped before the payload leaves this process.",
        "operationId": "export_strategy_api_strategies__strategy_id__export_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "strategy_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Strategy Id"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ExportPayload"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/strategies/import": {
      "post": {
        "tags": [
          "strategies-import-export"
        ],
        "summary": "Import Strategy",
        "description": "Validate + persist an imported strategy payload.\n\nBody is a JSON document that matches the ExportPayload shape, plus two\nimport-only keys:\n    format            — must equal \"ex7.strategy/v1\".\n    name_on_conflict  — \"suffix\" to auto-disambiguate, else errors out\n                        with 409 on name collision.\n\nWe parse the raw body (not the Pydantic model directly) because the\nexisting `ImportPayload` schema has `extra=\"ignore\"` — the format and\nconflict-strategy fields would otherwise be silently dropped before we\never saw them.",
        "operationId": "import_strategy_api_strategies_import_post",
        "responses": {
          "201": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StrategyCreateOut"
                }
              }
            }
          }
        },
        "security": [
          {
            "HTTPBearer": []
          }
        ]
      }
    },
    "/api/strategies/{strategy_id}/promote": {
      "post": {
        "tags": [
          "strategies-status"
        ],
        "summary": "Promote Strategy",
        "description": "Move the strategy one step forward: draft→ready or ready→live.\n\nAny other source status yields 409 with the per-status allowed set so the\nclient can render a helpful message (e.g. \"can't promote live → ready;\narchive instead\").",
        "operationId": "promote_strategy_api_strategies__strategy_id__promote_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "strategy_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Strategy Id"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/_PromoteBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/_StatusResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/strategies/{strategy_id}/archive": {
      "post": {
        "tags": [
          "strategies-status"
        ],
        "summary": "Archive Strategy",
        "description": "Soft-stop: set status=archived. Reversible via /unarchive.\n\nArchive is a valid target from every non-archived status, so this never\nreturns 409 for lifecycle reasons — only 404 (not found) or 409 if the\nrow is already archived (archived→archived is not a legal edge).",
        "operationId": "archive_strategy_api_strategies__strategy_id__archive_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "strategy_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Strategy Id"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/_StatusResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/strategies/{strategy_id}/unarchive": {
      "post": {
        "tags": [
          "strategies-status"
        ],
        "summary": "Unarchive Strategy",
        "description": "Bring an archived strategy back to ``draft``.\n\nThe service resets to draft (rather than the pre-archive status) because\nthe pre-archive status isn't recorded. Callers who want live again must\nre-promote explicitly, which re-triggers the live-promotion validation.",
        "operationId": "unarchive_strategy_api_strategies__strategy_id__unarchive_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "strategy_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Strategy Id"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/_StatusResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/signals/health": {
      "get": {
        "tags": [
          "signals-live-health"
        ],
        "summary": "Signals Health",
        "description": "Aggregate pipeline health for status pages + UI ops panels.\n\nReturns:\n  {\n    \"dispatcher\": \"ok\" | \"stale\",\n    \"market_data\": {\n      \"<instrument>\": {\"last_bar_ts\": iso, \"lag_seconds\": float,\n                         \"status\": \"fresh\"|\"stale\"|\"closed\"},\n      ...\n    },\n    \"runtimes\": {\"<status>\": count, ...},\n    \"now\": iso8601-utc\n  }\n\nNot user-scoped — exposes the pipeline as a whole. No PII, no user_ids.\nSafe for a public status page.",
        "operationId": "signals_health_api_signals_health_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "type": "object",
                  "title": "Response Signals Health Api Signals Health Get"
                }
              }
            }
          }
        }
      }
    },
    "/api/signals/health/me": {
      "get": {
        "tags": [
          "signals-live-health"
        ],
        "summary": "Signals Health Me",
        "description": "Per-user runtime rows — the data behind \"my strategies are running\".\n\nReturns {\"items\": [...]} where each item mirrors `strategy_runtimes`\nfields the UI needs. Scoped to `user_id` via the strategies join so a\nuser can only see their own runtimes (defense in depth over RLS).\n\nReturning a wrapped `items` (rather than a bare list) future-proofs for\nadding sibling fields (pagination cursor, totals, etc.) without breaking\nclients that parsed the top-level type.",
        "operationId": "signals_health_me_api_signals_health_me_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "type": "object",
                  "title": "Response Signals Health Me Api Signals Health Me Get"
                }
              }
            }
          }
        },
        "security": [
          {
            "HTTPBearer": []
          }
        ]
      }
    },
    "/api/signals/stream": {
      "get": {
        "tags": [
          "signals-live"
        ],
        "summary": "Signal Stream",
        "description": "SSE endpoint for live signal delivery.\n\nLifecycle:\n  1. Emit retry hint (client reconnect delay).\n  2. Emit one-time compliance banner.\n  3. If Last-Event-ID provided, replay any signals fired after that id\n     via replay_since_event_id(user_id, last_event_id, strategy_id).\n  4. Subscribe to BROADCASTER with (user.id, strategy_id).\n  5. Pump the subscriber queue:\n     - wait up to _HEARTBEAT_INTERVAL_SECONDS for a payload\n     - on payload: materialize the full SignalOut via fetch_signal,\n       apply the instrument filter if set, yield a `signal` or\n       `signal_closed` frame\n     - on timeout: yield heartbeat, then check client disconnect\n  6. On disconnect / generator close, unsubscribe cleanly so the\n     broadcaster's queue dict doesn't leak references.\n\nInstrument filter is post-queue: the broadcaster routes by\n(user_id, strategy_id) only. Handful of bytes per skipped event is\ncheaper than a broadcaster-side index when v1 has maybe a dozen\nconnected clients per user.",
        "operationId": "signal_stream_api_signals_stream_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "strategy_id",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string",
                  "format": "uuid"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Strategy Id"
            }
          },
          {
            "name": "instrument",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Instrument"
            }
          },
          {
            "name": "Last-Event-ID",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Last-Event-Id"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/signals/audit": {
      "get": {
        "tags": [
          "signals-live-audit"
        ],
        "summary": "Get Audit",
        "description": "Return a page of signal_audit rows owned by the caller.\n\nOrdering is newest-first (bar_ts DESC, id DESC). Pagination uses the\nkeyset cursor returned as next_cursor — pass it back unchanged to\nwalk the page boundary without OFFSET-scan cost.\n\nThe `from` query param arrives as `from_` because `from` is a Python\nkeyword; the HTTP name is preserved via FastAPI's alias so the wire\nspec in §7.1 stays correct.",
        "operationId": "get_audit_api_signals_audit_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "strategy_id",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string",
                  "format": "uuid"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Strategy Id"
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "From"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "To"
            }
          },
          {
            "name": "decision",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string",
                  "pattern": "^(fire|no_fire|blocked_news|blocked_risk|error)$"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Decision"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Cursor"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 500,
              "minimum": 1,
              "default": 100,
              "title": "Limit"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SignalAuditListOut"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/signals/runtimes": {
      "get": {
        "tags": [
          "signals-live-runtimes"
        ],
        "summary": "List Runtimes",
        "description": "Return every (strategy, mode) runtime row owned by the caller.\n\nOrdered so the most recently started worker bubbles up; never-started\nrows (started_at IS NULL) sink to the bottom with NULLS LAST.",
        "operationId": "list_runtimes_api_signals_runtimes_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "items": {
                    "$ref": "#/components/schemas/RuntimeOut"
                  },
                  "type": "array",
                  "title": "Response List Runtimes Api Signals Runtimes Get"
                }
              }
            }
          }
        },
        "security": [
          {
            "HTTPBearer": []
          }
        ]
      }
    },
    "/api/signals/runtimes/{strategy_id}/start": {
      "post": {
        "tags": [
          "signals-live-runtimes"
        ],
        "summary": "Start Runtime",
        "description": "Start (or idempotently re-start) a strategy runtime.\n\nGates (in order):\n  1. Strategy exists and is not soft-deleted -> 404 otherwise.\n  2. Strategy belongs to caller -> 403 otherwise (NOT 404, to avoid\n     timing-based strategy id enumeration).\n  3. Strategy status is one of ('ready','live','paused') -> 409 with\n     code ``strategy_not_startable`` otherwise. Draft / archived\n     strategies cannot fire live signals.\n  4. body.mode == 'live' -> 403 `live_mode_disabled_v1` (§6). v1 blocks\n     all live starts regardless of tier until the live gate ships.\n  5. UPSERT into strategy_runtimes. The ON CONFLICT clause preserves\n     an already-active row's status. If the returned status is still\n     'running' / 'draining' we raise 409 so the client sees the\n     current state instead of a silent no-op.\n\nIdempotent: a caller that POSTs /start while the row is already\n'starting' gets a clean 200 `status='starting'`. A caller that POSTs\n/start while the row is 'running' gets 409 with the current state so\nthey can tell the difference between \"we brought it up\" and \"it was\nalready up.\"",
        "operationId": "start_runtime_api_signals_runtimes__strategy_id__start_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "strategy_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Strategy Id"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RuntimeStartRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RuntimeStartResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/signals/runtimes/{strategy_id}/stop": {
      "post": {
        "tags": [
          "signals-live-runtimes"
        ],
        "summary": "Stop Runtime",
        "description": "Graceful drain: flip 'running' to 'draining' and let the dispatcher\nfinish the current bar before it settles on 'stopped'.\n\nSemantics (per §7.2):\n  - Row in 'running' -> flipped to 'draining', response status='draining'.\n  - Row already 'stopped' / 'error' / 'draining' / 'starting' -> return\n    the current status unchanged (200). Stop is idempotent and\n    side-effect-free for non-running states.\n  - No such row -> 404.\n\nWe do NOT check the strategies table here: ownership is already\nenforced by the user_id predicate on the UPDATE. If a caller POSTs\n/stop for a strategy_id they don't own, they hit 404 (no row matches),\nwhich is the right shape for an idempotent stop.",
        "operationId": "stop_runtime_api_signals_runtimes__strategy_id__stop_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "strategy_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Strategy Id"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RuntimeStopResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/signals/runtimes/{strategy_id}/force-close-all": {
      "post": {
        "tags": [
          "signals-live-runtimes"
        ],
        "summary": "Force Close All",
        "description": "Emergency lever: cancel every 'open' signal for a strategy.\n\nFlow:\n  1. Verify the strategy belongs to the caller. 404 if it doesn't\n     exist (or is soft-deleted); 403 if someone else owns it. This\n     mirrors the ownership gating in `start_runtime` so a hostile\n     client can't distinguish \"your strategy, nothing open\" from\n     \"someone else's strategy\" via response timing.\n  2. UPDATE every open signal with close_reason='force_close'.\n     close_price falls back to entry_price (safe null-free default —\n     no realized PnL for an emergency cancel).\n  3. For every closed signal id, emit pg_notify('signal_closed', ...)\n     so the SSE broadcaster refreshes connected clients and the\n     alerts pipeline can fire any \"position closed\" notifications.\n\nReturns the number of signals that transitioned to 'cancelled'.",
        "operationId": "force_close_all_api_signals_runtimes__strategy_id__force_close_all_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "strategy_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Strategy Id"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ForceCloseAllResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/signals/{signal_id}/close": {
      "post": {
        "tags": [
          "signals-live"
        ],
        "summary": "Close Signal",
        "description": "Manually close a still-open paper signal.\n\nWorkflow (§7.3):\n  1. SELECT ... FOR UPDATE on the target row scoped by (id, user_id).\n     Missing → 404 (either not found or not owned — we do not leak\n     the distinction to avoid a user-enumeration oracle).\n  2. If status != 'open' → 409 with the current row in the detail so\n     the UI can reconcile without a refetch.\n  3. If mode != 'paper' → 403. v1 has no broker path; a manual close\n     on a live-mode signal would desync our book from the market.\n  4. Compute P&L via ``compute_pnl(instrument, side, size,\n     entry_price, close_price)`` — this is the one-and-only P&L\n     formula (2-tick slippage 2-sided, per-instrument commission,\n     all Decimal, no float drift).\n  5. UPDATE with status='cancelled' (per SignalClose.reason Literal\n     'user'), close_reason='user', pnl fields populated, and\n     slippage_ticks=2.0 (IRON LAW §7). The WHERE status='open'\n     guard makes the UPDATE a no-op if a concurrent writer already\n     closed the row — in which case we re-raise as 409.\n  6. pg_notify('signal_closed', <json>) inside the same transaction\n     so the SSE broadcaster sees the close on commit only.",
        "operationId": "close_signal_api_signals__signal_id__close_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "signal_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Signal Id"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SignalClose"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SignalOut"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/signals": {
      "get": {
        "tags": [
          "signals-live"
        ],
        "summary": "List Signals",
        "description": "Cursor-paginated list of the caller's signals.\n\nFilters (all optional): strategy_id, from/to (ISO-8601), side, status,\ninstrument. Ordering is `(fired_at DESC, id DESC)` — stable even for\nsignals that fire on the same bar close.\n\nCursor strategy: we fetch N+1 rows where N = `limit`. If we got back\nN+1, the Nth row's (fired_at, id) becomes `next_cursor` and we truncate\nto N rows in the response. This is a keyset / seek pagination scheme.",
        "operationId": "list_signals_api_signals_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "strategy_id",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string",
                  "format": "uuid"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Strategy Id"
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "From"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "To"
            }
          },
          {
            "name": "side",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string",
                  "pattern": "^(long|short)$"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Side"
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Status"
            }
          },
          {
            "name": "instrument",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Instrument"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Cursor"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 200,
              "minimum": 1,
              "default": 50,
              "title": "Limit"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SignalListOut"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/signals/{signal_id}": {
      "get": {
        "tags": [
          "signals-live"
        ],
        "summary": "Get Signal",
        "description": "Fetch a single signal the caller owns. 404 if missing or not owned.\n\nWe intentionally return 404 (not 403) for signals owned by another user:\nleaking existence-of-resource to an unauthorized user is an info-disclosure\nsmell, and a 404 is the standard \"nothing here for you\" for RLS-style scoping.",
        "operationId": "get_signal_api_signals__signal_id__get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "signal_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Signal Id"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SignalOut"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/billing/tiers": {
      "get": {
        "tags": [
          "billing"
        ],
        "summary": "List Tiers",
        "description": "Public. Returns every tier with prices + feature caps.",
        "operationId": "list_tiers_api_billing_tiers_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "items": {
                    "$ref": "#/components/schemas/TierOut"
                  },
                  "type": "array",
                  "title": "Response List Tiers Api Billing Tiers Get"
                }
              }
            }
          }
        }
      }
    },
    "/api/billing/disclaimer": {
      "get": {
        "tags": [
          "billing"
        ],
        "summary": "Get Disclaimer",
        "description": "Public. CFTC Rule 4.41 disclaimer + current required doc versions.",
        "operationId": "get_disclaimer_api_billing_disclaimer_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "additionalProperties": {
                          "type": "string"
                        },
                        "type": "object"
                      }
                    ]
                  },
                  "type": "object",
                  "title": "Response Get Disclaimer Api Billing Disclaimer Get"
                }
              }
            }
          }
        }
      }
    },
    "/api/billing/me": {
      "get": {
        "tags": [
          "billing"
        ],
        "summary": "Billing Me",
        "operationId": "billing_me_api_billing_me_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BillingMeOut"
                }
              }
            }
          }
        },
        "security": [
          {
            "HTTPBearer": []
          }
        ]
      }
    },
    "/api/billing/compliance": {
      "get": {
        "tags": [
          "billing"
        ],
        "summary": "Get Compliance Status",
        "operationId": "get_compliance_status_api_billing_compliance_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ComplianceStatusOut"
                }
              }
            }
          }
        },
        "security": [
          {
            "HTTPBearer": []
          }
        ]
      }
    },
    "/api/billing/compliance/accept": {
      "post": {
        "tags": [
          "billing"
        ],
        "summary": "Accept Compliance",
        "operationId": "accept_compliance_api_billing_compliance_accept_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ComplianceAccept"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": {
                    "type": "string"
                  },
                  "type": "object",
                  "title": "Response Accept Compliance Api Billing Compliance Accept Post"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "security": [
          {
            "HTTPBearer": []
          }
        ]
      }
    },
    "/api/billing/checkout": {
      "post": {
        "tags": [
          "billing"
        ],
        "summary": "Checkout",
        "operationId": "checkout_api_billing_checkout_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CheckoutCreate"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CheckoutOut"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "security": [
          {
            "HTTPBearer": []
          }
        ]
      }
    },
    "/api/billing/portal": {
      "post": {
        "tags": [
          "billing"
        ],
        "summary": "Portal",
        "operationId": "portal_api_billing_portal_post",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PortalOut"
                }
              }
            }
          }
        },
        "security": [
          {
            "HTTPBearer": []
          }
        ]
      }
    },
    "/api/billing/cancel": {
      "post": {
        "tags": [
          "billing"
        ],
        "summary": "Cancel",
        "operationId": "cancel_api_billing_cancel_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CancelRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CancelOut"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "security": [
          {
            "HTTPBearer": []
          }
        ]
      }
    },
    "/api/billing/resume": {
      "post": {
        "tags": [
          "billing"
        ],
        "summary": "Resume",
        "operationId": "resume_api_billing_resume_post",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CancelOut"
                }
              }
            }
          }
        },
        "security": [
          {
            "HTTPBearer": []
          }
        ]
      }
    },
    "/api/billing/comp": {
      "post": {
        "tags": [
          "billing"
        ],
        "summary": "Admin Comp",
        "operationId": "admin_comp_api_billing_comp_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CompRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CompOut"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "security": [
          {
            "HTTPBearer": []
          }
        ]
      }
    },
    "/api/billing/webhook": {
      "post": {
        "tags": [
          "billing"
        ],
        "summary": "Stripe Webhook",
        "description": "Stripe → us. Signature verified BEFORE parse.\n\nReturns 200 on success or already-processed. 400 on bad signature.\n500 on handler error (so Stripe retries).",
        "operationId": "stripe_webhook_api_billing_webhook_post",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          }
        }
      }
    },
    "/api/alerts/channels": {
      "get": {
        "tags": [
          "alerts"
        ],
        "summary": "List Channels",
        "operationId": "list_channels_api_alerts_channels_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ChannelListOut"
                }
              }
            }
          }
        },
        "security": [
          {
            "HTTPBearer": []
          }
        ]
      },
      "post": {
        "tags": [
          "alerts"
        ],
        "summary": "Create Channel",
        "operationId": "create_channel_api_alerts_channels_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ChannelCreate"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ChannelCreateResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "security": [
          {
            "HTTPBearer": []
          }
        ]
      }
    },
    "/api/alerts/channels/{channel_id}/verify": {
      "post": {
        "tags": [
          "alerts"
        ],
        "summary": "Verify Channel",
        "operationId": "verify_channel_api_alerts_channels__channel_id__verify_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "channel_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Channel Id"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ChannelVerifyRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true,
                  "title": "Response Verify Channel Api Alerts Channels  Channel Id  Verify Post"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/alerts/channels/{channel_id}/resend": {
      "post": {
        "tags": [
          "alerts"
        ],
        "summary": "Resend Verification",
        "operationId": "resend_verification_api_alerts_channels__channel_id__resend_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "channel_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Channel Id"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true,
                  "title": "Response Resend Verification Api Alerts Channels  Channel Id  Resend Post"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/alerts/channels/{channel_id}": {
      "delete": {
        "tags": [
          "alerts"
        ],
        "summary": "Delete Channel",
        "operationId": "delete_channel_api_alerts_channels__channel_id__delete",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "channel_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Channel Id"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/alerts/subscriptions": {
      "get": {
        "tags": [
          "alerts"
        ],
        "summary": "List Subscriptions",
        "operationId": "list_subscriptions_api_alerts_subscriptions_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "strategy_id",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string",
                  "format": "uuid"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Strategy Id"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SubscriptionListOut"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "alerts"
        ],
        "summary": "Create Subscription",
        "operationId": "create_subscription_api_alerts_subscriptions_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SubscriptionCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true,
                  "title": "Response Create Subscription Api Alerts Subscriptions Post"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/alerts/subscriptions/{sub_id}": {
      "patch": {
        "tags": [
          "alerts"
        ],
        "summary": "Patch Subscription",
        "operationId": "patch_subscription_api_alerts_subscriptions__sub_id__patch",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "sub_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Sub Id"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SubscriptionPatch"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true,
                  "title": "Response Patch Subscription Api Alerts Subscriptions  Sub Id  Patch"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "alerts"
        ],
        "summary": "Delete Subscription",
        "operationId": "delete_subscription_api_alerts_subscriptions__sub_id__delete",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "sub_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Sub Id"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/alerts/deliveries": {
      "get": {
        "tags": [
          "alerts"
        ],
        "summary": "List Deliveries",
        "operationId": "list_deliveries_api_alerts_deliveries_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "strategy_id",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string",
                  "format": "uuid"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Strategy Id"
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Status"
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "From"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "To"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Cursor"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 200,
              "minimum": 1,
              "default": 50,
              "title": "Limit"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeliveryListOut"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/alerts/deliveries/{delivery_id}": {
      "get": {
        "tags": [
          "alerts"
        ],
        "summary": "Get Delivery",
        "operationId": "get_delivery_api_alerts_deliveries__delivery_id__get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "delivery_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Delivery Id"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeliveryOut"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/alerts/unsubscribe": {
      "get": {
        "tags": [
          "alerts"
        ],
        "summary": "Unsubscribe Landing",
        "operationId": "unsubscribe_landing_api_alerts_unsubscribe_get",
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Token"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "alerts"
        ],
        "summary": "Unsubscribe Confirm",
        "operationId": "unsubscribe_confirm_api_alerts_unsubscribe_post",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UnsubscribePost"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UnsubscribeResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/alerts/webhooks/resend": {
      "post": {
        "tags": [
          "alerts"
        ],
        "summary": "Resend Webhook",
        "description": "Handle Resend delivery / bounce / complaint callbacks.\n\nResend event shapes (https://resend.com/docs/dashboard/webhooks/event-types):\n  {\n    \"type\": \"email.delivered\" | \"email.bounced\" | \"email.complained\" | ...,\n    \"created_at\": \"...\",\n    \"data\": {\n      \"email_id\": \"<uuid>\",         # matches provider_msg_id on our side\n      \"to\": [\"recipient@...\"],\n      \"from\": \"sender@...\",\n      \"subject\": \"...\",\n      # bounce/complained events add `reason` or `type` in `data.bounce`\n    }\n  }",
        "operationId": "resend_webhook_api_alerts_webhooks_resend_post",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "type": "object",
                  "title": "Response Resend Webhook Api Alerts Webhooks Resend Post"
                }
              }
            }
          }
        }
      }
    },
    "/api/alerts/webhooks/twilio": {
      "post": {
        "tags": [
          "alerts"
        ],
        "summary": "Twilio Webhook",
        "description": "Twilio form-encoded delivery receipt + STOP/HELP keyword handler.\n\nv1: signature validation is a no-op (SMS deferred). We still accept the\nPOST so a webhook-configured Twilio account doesn't 404 during the\nv2 rollout pre-flight.",
        "operationId": "twilio_webhook_api_alerts_webhooks_twilio_post",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "type": "object",
                  "title": "Response Twilio Webhook Api Alerts Webhooks Twilio Post"
                }
              }
            }
          }
        }
      }
    },
    "/api/alerts/webhooks/telegram": {
      "post": {
        "tags": [
          "alerts"
        ],
        "summary": "Telegram Webhook",
        "description": "Handle inbound Telegram updates.\n\nAuthentication: shared secret in the webhook URL query string. The bot's\nsetWebhook was called with `?secret=<TELEGRAM_WEBHOOK_SECRET>`. If it\ndoesn't match, we 401.\n\nSupported update types:\n  * /start <token>  — verification handshake. chat_id becomes the channel\n    destination, verified=true.\n  * text messages   — logged, no-op (bot is write-only for alerts).",
        "operationId": "telegram_webhook_api_alerts_webhooks_telegram_post",
        "parameters": [
          {
            "name": "secret",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Secret"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true,
                  "title": "Response Telegram Webhook Api Alerts Webhooks Telegram Post"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/vix/generate-strategy": {
      "post": {
        "tags": [
          "vix"
        ],
        "summary": "Generate Strategy",
        "operationId": "generate_strategy_api_vix_generate_strategy_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/GenerateStrategyRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenerateStrategyResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "security": [
          {
            "HTTPBearer": []
          }
        ]
      }
    },
    "/api/vix/quota": {
      "get": {
        "tags": [
          "vix"
        ],
        "summary": "Get Quota",
        "operationId": "get_quota_api_vix_quota_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QuotaResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "HTTPBearer": []
          }
        ]
      }
    }
  },
  "components": {
    "schemas": {
      "BillingMeOut": {
        "properties": {
          "tier": {
            "type": "string",
            "title": "Tier"
          },
          "status": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Status"
          },
          "current_period_end": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Current Period End"
          },
          "cancel_at_period_end": {
            "type": "boolean",
            "title": "Cancel At Period End",
            "default": false
          },
          "trial_end": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Trial End"
          },
          "stripe_customer_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Stripe Customer Id"
          }
        },
        "type": "object",
        "required": [
          "tier"
        ],
        "title": "BillingMeOut"
      },
      "CancelOut": {
        "properties": {
          "effective_at": {
            "type": "string",
            "format": "date-time",
            "title": "Effective At"
          },
          "status": {
            "type": "string",
            "title": "Status"
          }
        },
        "type": "object",
        "required": [
          "effective_at",
          "status"
        ],
        "title": "CancelOut"
      },
      "CancelRequest": {
        "properties": {
          "reason_category": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "too_expensive",
                  "missing_feature",
                  "not_using",
                  "trial_ended",
                  "other"
                ]
              },
              {
                "type": "null"
              }
            ],
            "title": "Reason Category"
          },
          "reason_text": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 500
              },
              {
                "type": "null"
              }
            ],
            "title": "Reason Text"
          }
        },
        "additionalProperties": false,
        "type": "object",
        "title": "CancelRequest"
      },
      "ChannelCreate": {
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "email",
              "sms",
              "telegram"
            ],
            "title": "Type"
          },
          "destination": {
            "type": "string",
            "maxLength": 320,
            "minLength": 1,
            "title": "Destination"
          },
          "consent": {
            "type": "boolean",
            "title": "Consent",
            "description": "User checked the consent box."
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "type",
          "destination",
          "consent"
        ],
        "title": "ChannelCreate",
        "description": "POST /api/alerts/channels body."
      },
      "ChannelCreateResponse": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "verification_required": {
            "type": "boolean",
            "title": "Verification Required",
            "default": true
          },
          "telegram_start_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Telegram Start Url"
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "id"
        ],
        "title": "ChannelCreateResponse",
        "description": "POST /api/alerts/channels response."
      },
      "ChannelListOut": {
        "properties": {
          "items": {
            "items": {
              "$ref": "#/components/schemas/ChannelOut"
            },
            "type": "array",
            "title": "Items"
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "items"
        ],
        "title": "ChannelListOut",
        "description": "GET /api/alerts/channels response."
      },
      "ChannelOut": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "type": {
            "type": "string",
            "enum": [
              "email",
              "sms",
              "telegram"
            ],
            "title": "Type"
          },
          "destination_masked": {
            "type": "string",
            "title": "Destination Masked"
          },
          "verified": {
            "type": "boolean",
            "title": "Verified"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "id",
          "type",
          "destination_masked",
          "verified",
          "created_at"
        ],
        "title": "ChannelOut",
        "description": "GET /api/alerts/channels response row. Destination is MASKED."
      },
      "ChannelVerifyRequest": {
        "properties": {
          "token": {
            "type": "string",
            "maxLength": 128,
            "minLength": 4,
            "title": "Token"
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "token"
        ],
        "title": "ChannelVerifyRequest",
        "description": "POST /api/alerts/channels/{id}/verify body."
      },
      "CheckoutCreate": {
        "properties": {
          "price_id": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 200,
                "minLength": 4
              },
              {
                "type": "null"
              }
            ],
            "title": "Price Id"
          },
          "cadence": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "monthly",
                  "annual"
                ]
              },
              {
                "type": "null"
              }
            ],
            "title": "Cadence"
          },
          "success_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Success Url"
          },
          "cancel_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Cancel Url"
          }
        },
        "additionalProperties": false,
        "type": "object",
        "title": "CheckoutCreate"
      },
      "CheckoutOut": {
        "properties": {
          "url": {
            "type": "string",
            "title": "Url"
          },
          "session_id": {
            "type": "string",
            "title": "Session Id"
          }
        },
        "type": "object",
        "required": [
          "url",
          "session_id"
        ],
        "title": "CheckoutOut"
      },
      "CloneRequest": {
        "properties": {
          "new_name": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 80,
                "minLength": 1
              },
              {
                "type": "null"
              }
            ],
            "title": "New Name"
          }
        },
        "additionalProperties": false,
        "type": "object",
        "title": "CloneRequest"
      },
      "CompOut": {
        "properties": {
          "subscription_id": {
            "type": "string",
            "format": "uuid",
            "title": "Subscription Id"
          },
          "stripe_subscription_id": {
            "type": "string",
            "title": "Stripe Subscription Id"
          },
          "tier": {
            "type": "string",
            "title": "Tier"
          },
          "effective_until": {
            "type": "string",
            "format": "date-time",
            "title": "Effective Until"
          }
        },
        "type": "object",
        "required": [
          "subscription_id",
          "stripe_subscription_id",
          "tier",
          "effective_until"
        ],
        "title": "CompOut"
      },
      "CompRequest": {
        "properties": {
          "user_id": {
            "type": "string",
            "format": "uuid",
            "title": "User Id"
          },
          "tier": {
            "type": "string",
            "enum": [
              "pro",
              "premium",
              "enterprise"
            ],
            "title": "Tier",
            "default": "pro"
          },
          "duration_months": {
            "type": "integer",
            "maximum": 120,
            "minimum": 1,
            "title": "Duration Months",
            "default": 12
          },
          "reason": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 200
              },
              {
                "type": "null"
              }
            ],
            "title": "Reason"
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "user_id"
        ],
        "title": "CompRequest"
      },
      "ComplianceAccept": {
        "properties": {
          "document_type": {
            "type": "string",
            "enum": [
              "tos",
              "risk_disclosure",
              "privacy"
            ],
            "title": "Document Type"
          },
          "document_version": {
            "type": "string",
            "maxLength": 64,
            "minLength": 1,
            "title": "Document Version"
          },
          "acknowledge_cftc_rule_4_41": {
            "type": "boolean",
            "title": "Acknowledge Cftc Rule 4 41",
            "default": true
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "document_type",
          "document_version"
        ],
        "title": "ComplianceAccept"
      },
      "ComplianceStatusOut": {
        "properties": {
          "tos_accepted": {
            "type": "boolean",
            "title": "Tos Accepted"
          },
          "tos_version": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Tos Version"
          },
          "risk_disclosure_accepted": {
            "type": "boolean",
            "title": "Risk Disclosure Accepted"
          },
          "risk_disclosure_version": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Risk Disclosure Version"
          },
          "privacy_accepted": {
            "type": "boolean",
            "title": "Privacy Accepted"
          },
          "privacy_version": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Privacy Version"
          }
        },
        "type": "object",
        "required": [
          "tos_accepted",
          "risk_disclosure_accepted",
          "privacy_accepted"
        ],
        "title": "ComplianceStatusOut",
        "description": "Latest acceptance state per doc type."
      },
      "CreateFromFixtureBody": {
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 80,
            "minLength": 1,
            "title": "Name"
          },
          "description": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 500
              },
              {
                "type": "null"
              }
            ],
            "title": "Description"
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "name"
        ],
        "title": "CreateFromFixtureBody"
      },
      "DeliveryListOut": {
        "properties": {
          "items": {
            "items": {
              "$ref": "#/components/schemas/DeliveryOut"
            },
            "type": "array",
            "title": "Items"
          },
          "next_cursor": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Next Cursor"
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "items"
        ],
        "title": "DeliveryListOut",
        "description": "GET /api/alerts/deliveries response."
      },
      "DeliveryOut": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "subscription_id": {
            "type": "string",
            "format": "uuid",
            "title": "Subscription Id"
          },
          "signal_id": {
            "type": "string",
            "format": "uuid",
            "title": "Signal Id"
          },
          "channel_id": {
            "type": "string",
            "format": "uuid",
            "title": "Channel Id"
          },
          "transport": {
            "type": "string",
            "enum": [
              "email",
              "sms",
              "telegram"
            ],
            "title": "Transport"
          },
          "provider": {
            "type": "string",
            "enum": [
              "resend",
              "twilio",
              "telegram"
            ],
            "title": "Provider"
          },
          "provider_msg_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Provider Msg Id"
          },
          "status": {
            "type": "string",
            "enum": [
              "queued",
              "sending",
              "sent",
              "delivered",
              "bounced",
              "failed",
              "muted",
              "unsubscribed"
            ],
            "title": "Status"
          },
          "error_code": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Error Code"
          },
          "error_detail": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Error Detail"
          },
          "attempts": {
            "type": "integer",
            "title": "Attempts"
          },
          "scheduled_at": {
            "type": "string",
            "format": "date-time",
            "title": "Scheduled At"
          },
          "sent_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Sent At"
          },
          "delivered_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Delivered At"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "id",
          "subscription_id",
          "signal_id",
          "channel_id",
          "transport",
          "provider",
          "provider_msg_id",
          "status",
          "error_code",
          "error_detail",
          "attempts",
          "scheduled_at",
          "sent_at",
          "delivered_at",
          "created_at"
        ],
        "title": "DeliveryOut",
        "description": "GET /api/alerts/deliveries row."
      },
      "EngineOut": {
        "properties": {
          "type": {
            "type": "string",
            "title": "Type"
          },
          "display_name": {
            "type": "string",
            "title": "Display Name"
          },
          "description": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Description"
          },
          "category": {
            "type": "string",
            "enum": [
              "data_source",
              "signal",
              "filter",
              "risk",
              "output"
            ],
            "title": "Category"
          },
          "config_schema": {
            "additionalProperties": true,
            "type": "object",
            "title": "Config Schema"
          },
          "supported_instruments": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Supported Instruments"
          },
          "supported_timeframes": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Supported Timeframes"
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "type",
          "display_name",
          "description",
          "category",
          "config_schema",
          "supported_instruments",
          "supported_timeframes"
        ],
        "title": "EngineOut"
      },
      "ExportPayload": {
        "properties": {
          "format": {
            "type": "string",
            "const": "ex7.strategy/v1",
            "title": "Format",
            "default": "ex7.strategy/v1"
          },
          "name": {
            "type": "string",
            "title": "Name"
          },
          "description": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Description"
          },
          "instrument": {
            "type": "string",
            "enum": [
              "MNQ",
              "NQ",
              "MCL",
              "CL",
              "ES",
              "MES"
            ],
            "title": "Instrument"
          },
          "timeframe": {
            "type": "string",
            "enum": [
              "1m",
              "2m",
              "5m",
              "15m",
              "1h"
            ],
            "title": "Timeframe"
          },
          "graph_json": {
            "$ref": "#/components/schemas/Graph"
          },
          "exported_at": {
            "type": "string",
            "format": "date-time",
            "title": "Exported At"
          },
          "schema_version": {
            "type": "string",
            "title": "Schema Version"
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "name",
          "description",
          "instrument",
          "timeframe",
          "graph_json",
          "exported_at",
          "schema_version"
        ],
        "title": "ExportPayload"
      },
      "FixtureOut": {
        "properties": {
          "slug": {
            "type": "string",
            "title": "Slug"
          },
          "name": {
            "type": "string",
            "title": "Name"
          },
          "description": {
            "type": "string",
            "title": "Description"
          },
          "category": {
            "type": "string",
            "enum": [
              "beginner",
              "validated",
              "experimental"
            ],
            "title": "Category"
          },
          "graph_json": {
            "$ref": "#/components/schemas/Graph"
          },
          "display_order": {
            "type": "integer",
            "title": "Display Order"
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "slug",
          "name",
          "description",
          "category",
          "graph_json",
          "display_order"
        ],
        "title": "FixtureOut"
      },
      "ForceCloseAllResponse": {
        "properties": {
          "closed_count": {
            "type": "integer",
            "title": "Closed Count"
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "closed_count"
        ],
        "title": "ForceCloseAllResponse",
        "description": "Response for POST /runtime/{strategy_id}/force-close-all."
      },
      "GenerateStrategyRequest": {
        "properties": {
          "prompt": {
            "type": "string",
            "maxLength": 2000,
            "minLength": 1,
            "title": "Prompt"
          },
          "instrument": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "MNQ",
                  "NQ",
                  "MCL",
                  "CL",
                  "ES",
                  "MES"
                ]
              },
              {
                "type": "null"
              }
            ],
            "title": "Instrument"
          },
          "timeframe": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "1m",
                  "2m",
                  "5m",
                  "15m",
                  "1h"
                ]
              },
              {
                "type": "null"
              }
            ],
            "title": "Timeframe"
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "prompt"
        ],
        "title": "GenerateStrategyRequest"
      },
      "GenerateStrategyResponse": {
        "properties": {
          "graph": {
            "$ref": "#/components/schemas/Graph"
          },
          "generation_id": {
            "type": "string",
            "format": "uuid",
            "title": "Generation Id"
          },
          "tokens_used": {
            "$ref": "#/components/schemas/TokenUsage"
          },
          "quota_remaining": {
            "type": "integer",
            "title": "Quota Remaining"
          },
          "attempts": {
            "type": "integer",
            "title": "Attempts"
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "graph",
          "generation_id",
          "tokens_used",
          "quota_remaining",
          "attempts"
        ],
        "title": "GenerateStrategyResponse"
      },
      "Graph": {
        "properties": {
          "nodes": {
            "items": {
              "$ref": "#/components/schemas/GraphNode"
            },
            "type": "array",
            "title": "Nodes"
          },
          "edges": {
            "items": {
              "$ref": "#/components/schemas/GraphEdge"
            },
            "type": "array",
            "title": "Edges"
          },
          "meta": {
            "$ref": "#/components/schemas/GraphMeta"
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "nodes",
          "edges"
        ],
        "title": "Graph",
        "description": "Full DAG the user builds. Detailed validation in validators.py."
      },
      "GraphEdge": {
        "properties": {
          "from": {
            "type": "string",
            "maxLength": 64,
            "minLength": 1,
            "title": "From"
          },
          "to": {
            "type": "string",
            "maxLength": 64,
            "minLength": 1,
            "title": "To"
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "from",
          "to"
        ],
        "title": "GraphEdge"
      },
      "GraphMeta": {
        "properties": {
          "schema_version": {
            "type": "string",
            "title": "Schema Version",
            "default": "1.0"
          },
          "created_with": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Created With"
          }
        },
        "additionalProperties": true,
        "type": "object",
        "title": "GraphMeta"
      },
      "GraphNode": {
        "properties": {
          "id": {
            "type": "string",
            "maxLength": 64,
            "minLength": 1,
            "title": "Id"
          },
          "type": {
            "type": "string",
            "maxLength": 80,
            "minLength": 1,
            "title": "Type"
          },
          "config": {
            "additionalProperties": true,
            "type": "object",
            "title": "Config"
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "id",
          "type"
        ],
        "title": "GraphNode"
      },
      "HTTPValidationError": {
        "properties": {
          "detail": {
            "items": {
              "$ref": "#/components/schemas/ValidationError"
            },
            "type": "array",
            "title": "Detail"
          }
        },
        "type": "object",
        "title": "HTTPValidationError"
      },
      "LastVerdict": {
        "properties": {
          "run_id": {
            "type": "string",
            "format": "uuid",
            "title": "Run Id"
          },
          "verdict": {
            "type": "string",
            "title": "Verdict"
          },
          "score": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Score"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "run_id",
          "verdict",
          "created_at"
        ],
        "title": "LastVerdict",
        "description": "Denormalized verdict snapshot for list view (§7 option C lateral join)."
      },
      "PortalOut": {
        "properties": {
          "url": {
            "type": "string",
            "title": "Url"
          }
        },
        "type": "object",
        "required": [
          "url"
        ],
        "title": "PortalOut"
      },
      "QuotaResponse": {
        "properties": {
          "used_this_month": {
            "type": "integer",
            "title": "Used This Month"
          },
          "limit": {
            "type": "integer",
            "title": "Limit"
          },
          "remaining": {
            "type": "integer",
            "title": "Remaining"
          },
          "tier": {
            "type": "string",
            "title": "Tier"
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "used_this_month",
          "limit",
          "remaining",
          "tier"
        ],
        "title": "QuotaResponse"
      },
      "RollbackRequest": {
        "properties": {
          "to_version": {
            "type": "integer",
            "minimum": 1,
            "title": "To Version"
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "to_version"
        ],
        "title": "RollbackRequest"
      },
      "RuntimeOut": {
        "properties": {
          "strategy_id": {
            "type": "string",
            "format": "uuid",
            "title": "Strategy Id"
          },
          "mode": {
            "type": "string",
            "enum": [
              "paper",
              "live"
            ],
            "title": "Mode"
          },
          "status": {
            "type": "string",
            "enum": [
              "stopped",
              "starting",
              "running",
              "error",
              "draining"
            ],
            "title": "Status"
          },
          "last_bar_ts": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last Bar Ts"
          },
          "last_signal_id": {
            "anyOf": [
              {
                "type": "string",
                "format": "uuid"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last Signal Id"
          },
          "heartbeat_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Heartbeat At"
          },
          "started_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Started At"
          },
          "error_message": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Error Message"
          },
          "error_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Error At"
          },
          "worker_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Worker Id"
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "strategy_id",
          "mode",
          "status",
          "last_bar_ts",
          "last_signal_id",
          "heartbeat_at",
          "started_at",
          "error_message",
          "error_at",
          "worker_id"
        ],
        "title": "RuntimeOut",
        "description": "Per-strategy runtime state as returned by GET /runtime/{strategy_id}."
      },
      "RuntimeStartRequest": {
        "properties": {
          "mode": {
            "type": "string",
            "enum": [
              "paper",
              "live"
            ],
            "title": "Mode"
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "mode"
        ],
        "title": "RuntimeStartRequest",
        "description": "Body for POST /runtime/{strategy_id}/start."
      },
      "RuntimeStartResponse": {
        "properties": {
          "strategy_id": {
            "type": "string",
            "format": "uuid",
            "title": "Strategy Id"
          },
          "mode": {
            "type": "string",
            "enum": [
              "paper",
              "live"
            ],
            "title": "Mode"
          },
          "status": {
            "type": "string",
            "enum": [
              "starting",
              "running"
            ],
            "title": "Status"
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "strategy_id",
          "mode",
          "status"
        ],
        "title": "RuntimeStartResponse",
        "description": "Response for POST /runtime/{strategy_id}/start."
      },
      "RuntimeStopResponse": {
        "properties": {
          "strategy_id": {
            "type": "string",
            "format": "uuid",
            "title": "Strategy Id"
          },
          "status": {
            "type": "string",
            "enum": [
              "stopped",
              "draining"
            ],
            "title": "Status"
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "strategy_id",
          "status"
        ],
        "title": "RuntimeStopResponse",
        "description": "Response for POST /runtime/{strategy_id}/stop."
      },
      "SignalAuditListOut": {
        "properties": {
          "items": {
            "items": {
              "$ref": "#/components/schemas/SignalAuditOut"
            },
            "type": "array",
            "title": "Items"
          },
          "next_cursor": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Next Cursor"
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "items"
        ],
        "title": "SignalAuditListOut",
        "description": "Paginated list response for GET /signals/audit."
      },
      "SignalAuditOut": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "strategy_id": {
            "type": "string",
            "format": "uuid",
            "title": "Strategy Id"
          },
          "bar_ts": {
            "type": "string",
            "format": "date-time",
            "title": "Bar Ts"
          },
          "decision": {
            "type": "string",
            "enum": [
              "fire",
              "no_fire",
              "blocked_news",
              "blocked_risk",
              "error"
            ],
            "title": "Decision"
          },
          "reason_json": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Reason Json"
          },
          "signal_id": {
            "anyOf": [
              {
                "type": "string",
                "format": "uuid"
              },
              {
                "type": "null"
              }
            ],
            "title": "Signal Id"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "id",
          "strategy_id",
          "bar_ts",
          "decision",
          "reason_json",
          "signal_id",
          "created_at"
        ],
        "title": "SignalAuditOut",
        "description": "One audit row — why the engine did (or did not) fire on a bar."
      },
      "SignalClose": {
        "properties": {
          "close_price": {
            "anyOf": [
              {
                "type": "number",
                "exclusiveMinimum": 0
              },
              {
                "type": "string",
                "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"
              }
            ],
            "title": "Close Price"
          },
          "reason": {
            "type": "string",
            "const": "user",
            "title": "Reason",
            "default": "user"
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "close_price"
        ],
        "title": "SignalClose",
        "description": "Body for POST /signals/{id}/close — manual user close."
      },
      "SignalListOut": {
        "properties": {
          "items": {
            "items": {
              "$ref": "#/components/schemas/SignalOut"
            },
            "type": "array",
            "title": "Items"
          },
          "next_cursor": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Next Cursor"
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "items"
        ],
        "title": "SignalListOut",
        "description": "Paginated list response for GET /signals."
      },
      "SignalOut": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "strategy_id": {
            "type": "string",
            "format": "uuid",
            "title": "Strategy Id"
          },
          "strategy_version": {
            "type": "integer",
            "title": "Strategy Version"
          },
          "user_id": {
            "type": "string",
            "format": "uuid",
            "title": "User Id"
          },
          "instrument": {
            "type": "string",
            "enum": [
              "MNQ",
              "NQ",
              "MCL",
              "CL",
              "ES",
              "MES"
            ],
            "title": "Instrument"
          },
          "timeframe": {
            "type": "string",
            "enum": [
              "1m",
              "2m",
              "5m",
              "15m",
              "1h"
            ],
            "title": "Timeframe"
          },
          "bar_ts": {
            "type": "string",
            "format": "date-time",
            "title": "Bar Ts"
          },
          "fired_at": {
            "type": "string",
            "format": "date-time",
            "title": "Fired At"
          },
          "side": {
            "type": "string",
            "enum": [
              "long",
              "short"
            ],
            "title": "Side"
          },
          "entry_price": {
            "type": "string",
            "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$",
            "title": "Entry Price"
          },
          "stop_price": {
            "type": "string",
            "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$",
            "title": "Stop Price"
          },
          "target_price": {
            "type": "string",
            "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$",
            "title": "Target Price"
          },
          "size": {
            "type": "integer",
            "title": "Size"
          },
          "mode": {
            "type": "string",
            "enum": [
              "paper",
              "live"
            ],
            "title": "Mode"
          },
          "market_state": {
            "additionalProperties": true,
            "type": "object",
            "title": "Market State"
          },
          "dedup_key": {
            "type": "string",
            "title": "Dedup Key"
          },
          "status": {
            "type": "string",
            "enum": [
              "open",
              "won",
              "lost",
              "expired",
              "cancelled"
            ],
            "title": "Status"
          },
          "close_ts": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Close Ts"
          },
          "close_price": {
            "anyOf": [
              {
                "type": "string",
                "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"
              },
              {
                "type": "null"
              }
            ],
            "title": "Close Price"
          },
          "close_reason": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "target",
                  "stop",
                  "eod",
                  "force_close",
                  "user"
                ]
              },
              {
                "type": "null"
              }
            ],
            "title": "Close Reason"
          },
          "pnl_points": {
            "anyOf": [
              {
                "type": "string",
                "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"
              },
              {
                "type": "null"
              }
            ],
            "title": "Pnl Points"
          },
          "pnl_dollars": {
            "anyOf": [
              {
                "type": "string",
                "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"
              },
              {
                "type": "null"
              }
            ],
            "title": "Pnl Dollars"
          },
          "commission": {
            "type": "string",
            "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$",
            "title": "Commission",
            "default": "0"
          },
          "slippage_ticks": {
            "type": "string",
            "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$",
            "title": "Slippage Ticks",
            "default": "2.0"
          },
          "paper_mode_footer": {
            "type": "string",
            "title": "Paper Mode Footer",
            "default": "PAPER MODE — no orders are placed. Signals are for education."
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "id",
          "strategy_id",
          "strategy_version",
          "user_id",
          "instrument",
          "timeframe",
          "bar_ts",
          "fired_at",
          "side",
          "entry_price",
          "stop_price",
          "target_price",
          "size",
          "mode",
          "market_state",
          "dedup_key",
          "status"
        ],
        "title": "SignalOut",
        "description": "Canonical signal row as returned by GET /signals and SSE payloads."
      },
      "StrategyCreate": {
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 80,
            "minLength": 1,
            "title": "Name"
          },
          "description": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 500
              },
              {
                "type": "null"
              }
            ],
            "title": "Description"
          },
          "instrument": {
            "type": "string",
            "enum": [
              "MNQ",
              "NQ",
              "MCL",
              "CL",
              "ES",
              "MES"
            ],
            "title": "Instrument"
          },
          "timeframe": {
            "type": "string",
            "enum": [
              "1m",
              "2m",
              "5m",
              "15m",
              "1h"
            ],
            "title": "Timeframe"
          },
          "graph_json": {
            "$ref": "#/components/schemas/Graph"
          },
          "tags": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Tags"
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "name",
          "instrument",
          "timeframe",
          "graph_json"
        ],
        "title": "StrategyCreate"
      },
      "StrategyCreateOut": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "current_version": {
            "type": "integer",
            "title": "Current Version"
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "id",
          "current_version"
        ],
        "title": "StrategyCreateOut"
      },
      "StrategyList": {
        "properties": {
          "items": {
            "items": {
              "$ref": "#/components/schemas/StrategyListItem"
            },
            "type": "array",
            "title": "Items"
          },
          "next_cursor": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Next Cursor"
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "items"
        ],
        "title": "StrategyList"
      },
      "StrategyListItem": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "name": {
            "type": "string",
            "title": "Name"
          },
          "instrument": {
            "type": "string",
            "enum": [
              "MNQ",
              "NQ",
              "MCL",
              "CL",
              "ES",
              "MES"
            ],
            "title": "Instrument"
          },
          "timeframe": {
            "type": "string",
            "enum": [
              "1m",
              "2m",
              "5m",
              "15m",
              "1h"
            ],
            "title": "Timeframe"
          },
          "status": {
            "type": "string",
            "enum": [
              "draft",
              "ready",
              "live",
              "paused",
              "archived"
            ],
            "title": "Status"
          },
          "current_version": {
            "type": "integer",
            "title": "Current Version"
          },
          "tags": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Tags"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "title": "Updated At"
          },
          "last_verdict": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/LastVerdict"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "id",
          "name",
          "instrument",
          "timeframe",
          "status",
          "current_version",
          "tags",
          "updated_at"
        ],
        "title": "StrategyListItem"
      },
      "StrategyOut": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "name": {
            "type": "string",
            "title": "Name"
          },
          "description": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Description"
          },
          "instrument": {
            "type": "string",
            "enum": [
              "MNQ",
              "NQ",
              "MCL",
              "CL",
              "ES",
              "MES"
            ],
            "title": "Instrument"
          },
          "timeframe": {
            "type": "string",
            "enum": [
              "1m",
              "2m",
              "5m",
              "15m",
              "1h"
            ],
            "title": "Timeframe"
          },
          "status": {
            "type": "string",
            "enum": [
              "draft",
              "ready",
              "live",
              "paused",
              "archived"
            ],
            "title": "Status"
          },
          "current_version": {
            "type": "integer",
            "title": "Current Version"
          },
          "graph_json": {
            "$ref": "#/components/schemas/Graph"
          },
          "tags": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Tags"
          },
          "visibility": {
            "type": "string",
            "enum": [
              "private",
              "unlisted",
              "public"
            ],
            "title": "Visibility"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "title": "Updated At"
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "id",
          "name",
          "description",
          "instrument",
          "timeframe",
          "status",
          "current_version",
          "graph_json",
          "tags",
          "visibility",
          "created_at",
          "updated_at"
        ],
        "title": "StrategyOut"
      },
      "StrategyUpdate": {
        "properties": {
          "name": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 80,
                "minLength": 1
              },
              {
                "type": "null"
              }
            ],
            "title": "Name"
          },
          "description": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 500
              },
              {
                "type": "null"
              }
            ],
            "title": "Description"
          },
          "graph_json": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Graph"
              },
              {
                "type": "null"
              }
            ]
          },
          "commit_message": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 200
              },
              {
                "type": "null"
              }
            ],
            "title": "Commit Message"
          },
          "tags": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Tags"
          }
        },
        "additionalProperties": false,
        "type": "object",
        "title": "StrategyUpdate",
        "description": "PUT body. All fields optional; only present fields are written.\n\nGraph change → new version row + current_version bump.\nMeta-only change (name/tags/description) → no new version, updates in place."
      },
      "StrategyUpdateOut": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "current_version": {
            "type": "integer",
            "title": "Current Version"
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "id",
          "current_version"
        ],
        "title": "StrategyUpdateOut",
        "description": "PUT /api/strategies/{id} response.\n\n``current_version`` is the version AFTER the update. If the payload\ncontained a graph_json, this is the newly-inserted version (N+1);\notherwise it's unchanged from before the call."
      },
      "SubscriptionChannelEmbed": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "type": {
            "type": "string",
            "enum": [
              "email",
              "sms",
              "telegram"
            ],
            "title": "Type"
          },
          "destination_masked": {
            "type": "string",
            "title": "Destination Masked"
          },
          "verified": {
            "type": "boolean",
            "title": "Verified"
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "id",
          "type",
          "destination_masked",
          "verified"
        ],
        "title": "SubscriptionChannelEmbed",
        "description": "Embedded channel summary inside a SubscriptionOut."
      },
      "SubscriptionCreate": {
        "properties": {
          "strategy_id": {
            "type": "string",
            "format": "uuid",
            "title": "Strategy Id"
          },
          "channel_id": {
            "type": "string",
            "format": "uuid",
            "title": "Channel Id"
          },
          "mode": {
            "type": "string",
            "enum": [
              "realtime",
              "digest_daily",
              "digest_weekly"
            ],
            "title": "Mode",
            "default": "realtime"
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "strategy_id",
          "channel_id"
        ],
        "title": "SubscriptionCreate",
        "description": "POST /api/alerts/subscriptions body."
      },
      "SubscriptionListOut": {
        "properties": {
          "items": {
            "items": {
              "$ref": "#/components/schemas/SubscriptionOut"
            },
            "type": "array",
            "title": "Items"
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "items"
        ],
        "title": "SubscriptionListOut",
        "description": "GET /api/alerts/subscriptions response."
      },
      "SubscriptionOut": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "strategy_id": {
            "type": "string",
            "format": "uuid",
            "title": "Strategy Id"
          },
          "channel": {
            "$ref": "#/components/schemas/SubscriptionChannelEmbed"
          },
          "mode": {
            "type": "string",
            "enum": [
              "realtime",
              "digest_daily",
              "digest_weekly"
            ],
            "title": "Mode"
          },
          "muted_until": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Muted Until"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "id",
          "strategy_id",
          "channel",
          "mode",
          "created_at"
        ],
        "title": "SubscriptionOut",
        "description": "GET /api/alerts/subscriptions row."
      },
      "SubscriptionPatch": {
        "properties": {
          "mode": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "realtime",
                  "digest_daily",
                  "digest_weekly"
                ]
              },
              {
                "type": "null"
              }
            ],
            "title": "Mode"
          },
          "muted_until": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Muted Until"
          }
        },
        "additionalProperties": false,
        "type": "object",
        "title": "SubscriptionPatch",
        "description": "PATCH /api/alerts/subscriptions/{id} body."
      },
      "TierOut": {
        "properties": {
          "id": {
            "type": "string",
            "title": "Id"
          },
          "name": {
            "type": "string",
            "title": "Name"
          },
          "price_month_cents": {
            "type": "integer",
            "title": "Price Month Cents"
          },
          "price_year_cents": {
            "type": "integer",
            "title": "Price Year Cents"
          },
          "price_month_usd": {
            "type": "number",
            "title": "Price Month Usd"
          },
          "price_year_usd": {
            "type": "number",
            "title": "Price Year Usd"
          },
          "stripe_price_month": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Stripe Price Month"
          },
          "stripe_price_year": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Stripe Price Year"
          },
          "trial_days": {
            "type": "integer",
            "title": "Trial Days"
          },
          "strategies_cap": {
            "type": "integer",
            "title": "Strategies Cap"
          },
          "backtests_per_day": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Backtests Per Day"
          },
          "instruments": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Instruments"
          },
          "live_signals": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Live Signals"
          },
          "alert_channels": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Alert Channels"
          },
          "alert_rate_per_day": {
            "type": "integer",
            "title": "Alert Rate Per Day"
          },
          "vix_prompts_per_month": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Vix Prompts Per Month"
          },
          "audit_logs": {
            "type": "string",
            "title": "Audit Logs"
          },
          "prop_firm_risk_profiles": {
            "type": "boolean",
            "title": "Prop Firm Risk Profiles"
          },
          "priority_support": {
            "title": "Priority Support",
            "default": false
          },
          "api_webhooks": {
            "type": "boolean",
            "title": "Api Webhooks"
          },
          "white_label": {
            "type": "boolean",
            "title": "White Label"
          },
          "sla": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Sla"
          }
        },
        "type": "object",
        "required": [
          "id",
          "name",
          "price_month_cents",
          "price_year_cents",
          "price_month_usd",
          "price_year_usd",
          "trial_days",
          "strategies_cap",
          "instruments",
          "alert_channels",
          "alert_rate_per_day",
          "audit_logs",
          "prop_firm_risk_profiles",
          "api_webhooks",
          "white_label"
        ],
        "title": "TierOut"
      },
      "TokenUsage": {
        "properties": {
          "in": {
            "type": "integer",
            "minimum": 0,
            "title": "In"
          },
          "out": {
            "type": "integer",
            "minimum": 0,
            "title": "Out"
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "in",
          "out"
        ],
        "title": "TokenUsage"
      },
      "UnsubscribePost": {
        "properties": {
          "token": {
            "type": "string",
            "maxLength": 256,
            "minLength": 16,
            "title": "Token"
          },
          "reason": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 500
              },
              {
                "type": "null"
              }
            ],
            "title": "Reason"
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "token"
        ],
        "title": "UnsubscribePost",
        "description": "POST /api/alerts/unsubscribe body."
      },
      "UnsubscribeResponse": {
        "properties": {
          "unsubscribed": {
            "type": "boolean",
            "title": "Unsubscribed"
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "unsubscribed"
        ],
        "title": "UnsubscribeResponse"
      },
      "ValidationError": {
        "properties": {
          "loc": {
            "items": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "integer"
                }
              ]
            },
            "type": "array",
            "title": "Location"
          },
          "msg": {
            "type": "string",
            "title": "Message"
          },
          "type": {
            "type": "string",
            "title": "Error Type"
          },
          "input": {
            "title": "Input"
          },
          "ctx": {
            "type": "object",
            "title": "Context"
          }
        },
        "type": "object",
        "required": [
          "loc",
          "msg",
          "type"
        ],
        "title": "ValidationError"
      },
      "VersionDetail": {
        "properties": {
          "version": {
            "type": "integer",
            "title": "Version"
          },
          "commit_message": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Commit Message"
          },
          "created_by": {
            "type": "string",
            "format": "uuid",
            "title": "Created By"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          },
          "graph_json": {
            "$ref": "#/components/schemas/Graph"
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "version",
          "commit_message",
          "created_by",
          "created_at",
          "graph_json"
        ],
        "title": "VersionDetail"
      },
      "WaitlistEntry": {
        "properties": {
          "email": {
            "type": "string",
            "maxLength": 254,
            "minLength": 3,
            "title": "Email"
          },
          "source": {
            "type": "string",
            "maxLength": 64,
            "title": "Source",
            "default": "website"
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "email"
        ],
        "title": "WaitlistEntry"
      },
      "_PromoteBody": {
        "properties": {
          "target": {
            "type": "string",
            "enum": [
              "ready",
              "live"
            ],
            "title": "Target"
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "target"
        ],
        "title": "_PromoteBody"
      },
      "_StatusResponse": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "status": {
            "type": "string",
            "enum": [
              "draft",
              "ready",
              "live",
              "paused",
              "archived"
            ],
            "title": "Status"
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "id",
          "status"
        ],
        "title": "_StatusResponse"
      }
    },
    "securitySchemes": {
      "HTTPBearer": {
        "type": "http",
        "scheme": "bearer"
      }
    }
  }
}