{
  "openapi": "3.1.0",
  "info": {
    "title": "SOS A股 Agent Gateway",
    "version": "1.0.0",
    "description": "免注册、免密钥的 A 股当日盘面查询与事实核验接口。数据源不可用时返回错误，不编造、不回退旧值。发布接口只登记任务，不执行发布。",
    "contact": {
      "name": "SOS",
      "url": "https://sos-a-share-gateway.pages.dev/llms.txt"
    },
    "license": {
      "name": "数据来自公开只读接口，仅供研究参考，不构成投资建议"
    }
  },
  "servers": [
    { "url": "https://sos-a-share-gateway.pages.dev", "description": "公网生产环境" }
  ],
  "tags": [
    { "name": "data", "description": "真实盘面数据（免费、无需密钥）" },
    { "name": "verify", "description": "一句话事实核验（免费、无需密钥）" },
    { "name": "publish", "description": "发布任务登记（不执行，人工确认报价）" },
    { "name": "meta", "description": "能力清单、任务与调用统计" }
  ],
  "paths": {
    "/v1/market": {
      "get": {
        "tags": ["data"],
        "operationId": "getMarket",
        "summary": "今日真实盘面",
        "description": "实时拉取上游 review/tianti/qingxu 三个公开接口，返回涨停家数、跌停家数、连板家数、最高板、连板梯队、情绪温度与阶段、封板率、炸板率、晋级率、主线题材及家数、成交额、指数。数据源失败返回 502 upstream_unavailable，不回退旧值。",
        "parameters": [
          {
            "name": "source",
            "in": "query",
            "required": false,
            "description": "可选的来源标识，仅用于调用统计，不参与鉴权。等价于 X-Agent-Source 请求头。",
            "schema": { "type": "string", "maxLength": 40 }
          }
        ],
        "responses": {
          "200": {
            "description": "真实盘面数据",
            "headers": {
              "X-Data-Date": { "description": "数据交易日 YYYYMMDD", "schema": { "type": "string" } },
              "X-Data-Stale": { "description": "是否非今日数据（true/false）", "schema": { "type": "string" } }
            },
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/MarketResponse" } }
            }
          },
          "502": { "$ref": "#/components/responses/UpstreamUnavailable" },
          "500": { "$ref": "#/components/responses/InternalError" }
        }
      },
      "options": {
        "tags": ["data"],
        "operationId": "marketPreflight",
        "summary": "CORS 预检",
        "responses": { "204": { "description": "无内容" } }
      }
    },
    "/v1/verify": {
      "get": {
        "tags": ["verify"],
        "operationId": "verifyTextGet",
        "summary": "一句话事实核验（GET）",
        "parameters": [
          {
            "name": "text",
            "in": "query",
            "required": true,
            "description": "待核验文本，1–2000 字",
            "schema": { "type": "string", "minLength": 1, "maxLength": 2000 }
          }
        ],
        "responses": {
          "200": {
            "description": "逐条核验结果",
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/VerifyResponse" } }
            }
          },
          "400": { "$ref": "#/components/responses/InvalidRequest" },
          "502": { "$ref": "#/components/responses/UpstreamUnavailable" }
        }
      },
      "post": {
        "tags": ["verify"],
        "operationId": "verifyTextPost",
        "summary": "一句话事实核验",
        "description": "判定句中数字/个股/题材是否与当日真实盘面一致，返回 match / mismatch / unknown / info 逐条结论与原始依据（含数据日期与来源 URL）。",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["text"],
                "properties": {
                  "text": { "type": "string", "minLength": 1, "maxLength": 2000 }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "逐条核验结果",
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/VerifyResponse" } }
            }
          },
          "400": { "$ref": "#/components/responses/InvalidRequest" },
          "502": { "$ref": "#/components/responses/UpstreamUnavailable" }
        }
      }
    },
    "/v1/publish": {
      "post": {
        "tags": ["publish"],
        "operationId": "submitPublishTask",
        "summary": "登记一条发布任务（不执行）",
        "description": "只把内容登记进队列，等运营方人工确认报价与合规后在运营方本机登录态浏览器执行。不自动发布、不自动扣款、无虚拟余额。",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["platform", "content"],
                "properties": {
                  "platform": { "type": "string", "enum": ["weibo", "zhihu", "toutiao", "taoguba", "xueqiu"] },
                  "title": { "type": "string", "maxLength": 120 },
                  "content": { "type": "string", "minLength": 10, "maxLength": 4000 },
                  "requester": { "type": "string", "maxLength": 80 }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "任务已入队",
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/PublishResponse" } }
            }
          },
          "400": { "$ref": "#/components/responses/InvalidRequest" },
          "405": {
            "description": "方法不允许（GET /v1/publish）",
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/Error" } }
            }
          },
          "429": {
            "description": "队列已满（上限 300 条）",
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/Error" } }
            }
          },
          "503": { "$ref": "#/components/responses/StorageUnavailable" }
        }
      }
    },
    "/v1/stats": {
      "get": {
        "tags": ["meta"],
        "operationId": "getStats",
        "summary": "真实调用计数",
        "description": "区分内部自测与外部来源，给出总次数、外部/内部次数、按来源次数与首次调用时间。唯一有效的验证指标是 external_calls 与 first_external_call_at。",
        "responses": {
          "200": {
            "description": "调用统计",
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/StatsResponse" } }
            }
          },
          "503": { "$ref": "#/components/responses/StorageUnavailable" }
        }
      }
    },
    "/tasks": {
      "get": {
        "tags": ["meta"],
        "operationId": "listTasks",
        "summary": "任务列表",
        "responses": {
          "200": {
            "description": "任务列表",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": { "type": "boolean" },
                    "count": { "type": "integer" },
                    "seed_count": { "type": "integer" },
                    "counts_by_status": { "type": "object", "additionalProperties": { "type": "integer" } },
                    "tasks": { "type": "array", "items": { "$ref": "#/components/schemas/Task" } }
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": ["publish"],
        "operationId": "submitTask",
        "summary": "提交任务（与 /v1/publish 等价）",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["platform", "content"],
                "properties": {
                  "platform": { "type": "string", "enum": ["weibo", "zhihu", "toutiao", "taoguba", "xueqiu"] },
                  "title": { "type": "string" },
                  "content": { "type": "string", "minLength": 10 },
                  "requester": { "type": "string" }
                }
              }
            }
          }
        },
        "responses": {
          "201": { "description": "已提交" },
          "400": { "$ref": "#/components/responses/InvalidRequest" }
        }
      }
    },
    "/tasks/{id}": {
      "get": {
        "tags": ["meta"],
        "operationId": "getTask",
        "summary": "任务详情",
        "parameters": [
          { "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }
        ],
        "responses": {
          "200": {
            "description": "任务详情",
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/TaskEnvelope" } }
            }
          },
          "404": { "description": "任务不存在" }
        }
      }
    },
    "/manifest.json": {
      "get": {
        "tags": ["meta"],
        "operationId": "getManifest",
        "summary": "能力清单",
        "description": "能力、验证状态、定价、结算方式、限制。settlement=manual，auto_settlement=false，金额在确认前为 null。",
        "responses": { "200": { "description": "能力清单 JSON" } }
      }
    },
    "/openapi.json": {
      "get": {
        "tags": ["meta"],
        "operationId": "getOpenapi",
        "summary": "本文件",
        "responses": { "200": { "description": "OpenAPI 3.1 定义" } }
      }
    },
    "/llms.txt": {
      "get": {
        "tags": ["meta"],
        "operationId": "getLlmsTxt",
        "summary": "精简版机器说明",
        "responses": { "200": { "description": "text/plain; charset=utf-8" } }
      }
    }
  },
  "components": {
    "responses": {
      "InvalidRequest": {
        "description": "参数不合法",
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }
      },
      "UpstreamUnavailable": {
        "description": "盘面数据源不可用；不返回旧值或缓存兜底",
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }
      },
      "StorageUnavailable": {
        "description": "服务端存储未绑定，无法持久化或统计",
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }
      },
      "InternalError": {
        "description": "网关内部异常",
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "required": ["ok", "error"],
        "properties": {
          "ok": { "const": false },
          "error": {
            "type": "object",
            "required": ["code", "message"],
            "properties": {
              "code": {
                "type": "string",
                "enum": ["invalid_request", "method_not_allowed", "queue_full", "internal_error", "upstream_unavailable", "storage_unavailable"]
              },
              "message": { "type": "string" },
              "details": { "type": "object", "additionalProperties": true }
            }
          }
        }
      },
      "SourceMeta": {
        "type": "object",
        "properties": {
          "name": { "type": "string" },
          "url": { "type": "string" },
          "http_status": { "type": "integer" },
          "latency_ms": { "type": "integer" },
          "fetched_at": { "type": "string" },
          "ok": { "type": "boolean" },
          "error": { "type": "string" }
        }
      },
      "MarketResponse": {
        "type": "object",
        "required": ["ok", "data_date", "data_stale", "breadth", "rates", "sentiment", "themes", "ladder", "sources"],
        "properties": {
          "ok": { "const": true },
          "data_date": { "type": ["string", "null"], "description": "YYYYMMDD" },
          "data_date_iso": { "type": ["string", "null"] },
          "prev_data_date": { "type": ["string", "null"] },
          "data_stale": { "type": "boolean", "description": "true 表示这不是今日数据，勿当作今日盘面使用" },
          "stale_reason": { "type": ["string", "null"] },
          "session": { "type": "string", "enum": ["pre_open", "morning_session", "lunch_break", "afternoon_session", "closed"] },
          "is_intraday": { "type": "boolean" },
          "as_of_shanghai": { "type": "string" },
          "fetched_at": { "type": "string" },
          "breadth": {
            "type": "object",
            "properties": {
              "limit_up": { "type": ["integer", "null"] },
              "limit_up_prev": { "type": ["integer", "null"] },
              "limit_down": { "type": ["integer", "null"] },
              "limit_down_prev": { "type": ["integer", "null"] },
              "lianban": { "type": ["integer", "null"] },
              "lianban_prev": { "type": ["integer", "null"] },
              "max_board": { "type": ["integer", "null"] },
              "max_board_prev": { "type": ["integer", "null"] },
              "advance": { "type": ["integer", "null"] },
              "decline": { "type": ["integer", "null"] },
              "red_pct": { "type": ["number", "null"] },
              "turnover_yi": { "type": ["number", "null"], "description": "成交额，单位亿元" }
            }
          },
          "rates": {
            "type": "object",
            "properties": {
              "seal_rate_pct": { "type": ["number", "null"] },
              "broken_count": { "type": ["integer", "null"] },
              "broken_rate_pct": { "type": ["number", "null"] },
              "promotion_rate_pct": { "type": ["number", "null"] },
              "promotion_rate_formula": { "type": "string" },
              "promotion_sample": { "type": ["integer", "null"] },
              "promotion_hits": { "type": ["integer", "null"] },
              "first_board_promotion_rate_pct": { "type": ["number", "null"] },
              "first_board_promotion_formula": { "type": "string" }
            }
          },
          "sentiment": {
            "type": "object",
            "properties": {
              "temperature": { "type": ["integer", "null"] },
              "phase": { "type": ["string", "null"] },
              "phase_label": { "type": ["string", "null"] },
              "consec": { "type": ["integer", "null"] },
              "recent": { "type": "array", "items": {} }
            }
          },
          "indices": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "name": { "type": "string" },
                "code": { "type": "string" },
                "change_pct": { "type": ["number", "null"] },
                "amount_yi": { "type": ["number", "null"] }
              }
            }
          },
          "themes": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "name": { "type": "string" },
                "limit_up_count": { "type": ["integer", "null"] },
                "leader": { "type": ["string", "null"] },
                "driver": { "type": ["string", "null"] }
              }
            }
          },
          "ladder": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "board": { "type": "integer" },
                "count": { "type": "integer" },
                "stocks": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "code": { "type": "string" },
                      "name": { "type": "string" },
                      "board": { "type": "integer" },
                      "tag": { "type": ["string", "null"] },
                      "first_seal_time": { "type": ["string", "null"] },
                      "open_times": { "type": ["integer", "null"] },
                      "limit_up_days": { "type": "integer" },
                      "window_days": { "type": ["integer", "null"] },
                      "window_count": { "type": ["integer", "null"] }
                    }
                  }
                }
              }
            }
          },
          "ladder_detail": {
            "type": ["object", "null"],
            "properties": {
              "total_rows": { "type": ["integer", "null"] },
              "promote_11d": { "type": ["object", "null"] },
              "relay": { "type": ["object", "null"] }
            }
          },
          "warnings": { "type": "array", "items": { "type": "string" } },
          "sources": { "type": "array", "items": { "$ref": "#/components/schemas/SourceMeta" } },
          "license_notice": { "type": "string" }
        }
      },
      "VerifyClaim": {
        "type": "object",
        "properties": {
          "type": { "type": "string", "enum": ["number", "stock", "stock_code", "theme"] },
          "metric": { "type": "string" },
          "label": { "type": "string" },
          "claim": { "type": "string" },
          "name": { "type": "string" },
          "code": { "type": "string" },
          "stated": { "type": ["number", "null"] },
          "actual": { "type": ["number", "null"] },
          "stated_board": { "type": ["integer", "null"] },
          "actual_board": { "type": ["integer", "null"] },
          "stated_count": { "type": ["integer", "null"] },
          "actual_count": { "type": ["integer", "null"] },
          "status": { "type": "string", "enum": ["match", "mismatch", "unknown", "info"] },
          "evidence": { "type": "object", "additionalProperties": true }
        }
      },
      "VerifyResponse": {
        "type": "object",
        "required": ["ok", "verdict", "claims", "data_date", "data_stale"],
        "properties": {
          "ok": { "const": true },
          "input": { "type": "string" },
          "verdict": { "type": "string", "enum": ["supported", "partially_supported", "contradicted", "unverifiable"] },
          "summary": {
            "type": "object",
            "properties": {
              "claims_total": { "type": "integer" },
              "matched": { "type": "integer" },
              "mismatched": { "type": "integer" },
              "info_only": { "type": "integer" },
              "unknown": { "type": "integer" },
              "unverified_numbers": { "type": "integer" }
            }
          },
          "claims": { "type": "array", "items": { "$ref": "#/components/schemas/VerifyClaim" } },
          "unverified_numbers": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "number": { "type": "string" },
                "context": { "type": "string" },
                "status": { "type": "string" },
                "reason": { "type": "string" }
              }
            }
          },
          "coverage": { "type": "object", "additionalProperties": true },
          "data_date": { "type": ["string", "null"] },
          "data_stale": { "type": "boolean" },
          "session": { "type": "string" },
          "as_of_shanghai": { "type": "string" },
          "warnings": { "type": "array", "items": { "type": "string" } },
          "sources": { "type": "array", "items": { "$ref": "#/components/schemas/SourceMeta" } },
          "verdict_note": { "type": "string" }
        }
      },
      "Task": {
        "type": "object",
        "properties": {
          "id": { "type": "string" },
          "type": { "type": "string" },
          "title": { "type": "string" },
          "platform": { "type": "string" },
          "content": { "type": "string" },
          "status": { "type": "string" },
          "requester": { "type": ["string", "null"] },
          "reward": { "type": "object", "additionalProperties": true },
          "settlement": { "type": "object", "additionalProperties": true },
          "created_at": { "type": "string" }
        },
        "additionalProperties": true
      },
      "TaskEnvelope": {
        "type": "object",
        "properties": {
          "ok": { "type": "boolean" },
          "task": { "$ref": "#/components/schemas/Task" },
          "source": { "type": "string" }
        },
        "additionalProperties": true
      },
      "PublishResponse": {
        "type": "object",
        "properties": {
          "ok": { "const": true },
          "task": { "$ref": "#/components/schemas/Task" },
          "execution": {
            "type": "object",
            "properties": {
              "mode": { "type": "string", "const": "local_browser_required" },
              "executes": { "type": "boolean", "const": false },
              "note": { "type": "string" }
            }
          },
          "next_step": { "type": "string" }
        }
      },
      "StatsResponse": {
        "type": "object",
        "properties": {
          "ok": { "type": "boolean" },
          "updated_at": { "type": "string" },
          "totals": {
            "type": "object",
            "properties": {
              "calls": { "type": "integer" },
              "external_calls": { "type": "integer" },
              "internal_calls": { "type": "integer" }
            }
          },
          "first_external_call_at": { "type": ["string", "null"] },
          "last_external_call_at": { "type": ["string", "null"] },
          "has_external_calls": { "type": "boolean" },
          "by_endpoint": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "endpoint": { "type": "string" },
                "calls": { "type": "integer" }
              }
            }
          },
          "by_source": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "source": { "type": "string" },
                "calls": { "type": "integer" },
                "first_call_at": { "type": ["string", "null"] },
                "last_call_at": { "type": ["string", "null"] }
              }
            }
          },
          "counting_note": { "type": "string" },
          "endpoints_note": { "type": "string" }
        }
      }
    }
  }
}
