{"openapi":"3.1.0","info":{"title":"AStockEvent — A-share filing State API","description":"Live **State** folded from A-share regulatory filings — not a raw event dump.\n\n**Coverage today: 3 event types** — share reduction by major shareholders, administrative-penalty proceedings, and exchange inquiry letters. More types are being added.\n\nEvery value links back to the source PDF so you can verify it yourself. We report what happened; we never rate, score, or attribute.","version":"v1 (pre-release)"},"paths":{"/v1/coverage":{"get":{"tags":["state"],"summary":"Get Coverage","description":"🔴 裁定 14 的落点之一：**调用方是 agent 不是人，agent 不读门户网页**\n⇒ 覆盖面必须能被查到，否则它会反复试探不存在的类型然后判定我们数据不全。","operationId":"get_coverage_v1_coverage_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Get Coverage V1 Coverage Get"}}}}}}},"/v1/entity_state":{"get":{"tags":["state"],"summary":"Get Entity State","description":"裁定 10 的双键入口。**校验在 service 层**（两壳共用），这里只转协议。","operationId":"get_entity_state_v1_entity_state_get","parameters":[{"name":"code","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"A-share ticker, e.g. 000029","title":"Code"},"description":"A-share ticker, e.g. 000029"},{"name":"market","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"SH | SZ | BJ","title":"Market"},"description":"SH | SZ | BJ"},{"name":"aent_","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Opaque entity id from a prior response","title":"Aent "},"description":"Opaque entity id from a prior response"},{"name":"locale","in":"query","required":false,"schema":{"type":"string","pattern":"^(en|zh)$","default":"en","title":"Locale"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Entity State V1 Entity State Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/events/{aevt}":{"get":{"tags":["state"],"summary":"Get Event With Context","description":"设计 §4.2：**一次调用拿到这条事件的完整活脉络**（裁定 1）。","operationId":"get_event_with_context_v1_events__aevt__get","parameters":[{"name":"aevt","in":"path","required":true,"schema":{"type":"string","title":"Aevt"}},{"name":"locale","in":"query","required":false,"schema":{"type":"string","pattern":"^(en|zh)$","default":"en","title":"Locale"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Event With Context V1 Events  Aevt  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/whats_new":{"get":{"tags":["state"],"summary":"Whats New","operationId":"whats_new_v1_whats_new_get","parameters":[{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"last_updated_at from a prior page","title":"Cursor"},"description":"last_updated_at from a prior page"},{"name":"cursor_aevt","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"aevt_ from a prior page (tiebreak)","title":"Cursor Aevt"},"description":"aevt_ from a prior page (tiebreak)"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":50,"title":"Limit"}},{"name":"locale","in":"query","required":false,"schema":{"type":"string","pattern":"^(en|zh)$","default":"en","title":"Locale"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Whats New V1 Whats New Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/scan":{"get":{"tags":["state"],"summary":"Scan Events","operationId":"scan_events_v1_scan_get","parameters":[{"name":"event_type","in":"query","required":true,"schema":{"type":"string","description":"share_reduction | violation_penalty | regulatory_letter","enum":["share_reduction","violation_penalty","regulatory_letter"],"title":"Event Type"},"description":"share_reduction | violation_penalty | regulatory_letter"},{"name":"since","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Since"}},{"name":"until","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Until"}},{"name":"phase","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Phase"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":50,"title":"Limit"}},{"name":"locale","in":"query","required":false,"schema":{"type":"string","pattern":"^(en|zh)$","default":"en","title":"Locale"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Scan Events V1 Scan Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/filings":{"get":{"tags":["state"],"summary":"List Filings","description":"一只股票最近的公告：**标题 + 日期 + 源文件链接 + 抽出来的关键信息**。\n\n🔴 这是「四件交付物」的第 ①② 条，也是绝大多数调用方的第一站 ——\n   他们要的往往不是折叠状态，而是\"这家公司最近发了什么、原文在哪\"。\n🔴 **没有 `locale` 参数**：公告标题是原文，我们不翻译它（翻译=改写事实）。\n\n⚠️ **`published_at` 常为 `null`（实测约 93 个百分点）**：只有源方自己给出了发布时刻\n   才有值，我们**不拿抓取时刻冒充**。要「哪天发的」用恒有值的 `ann_date`。\n   字段保留是 Fernando 2026-08-20 的裁定（选了保留而非去掉）。","operationId":"list_filings_v1_filings_get","parameters":[{"name":"code","in":"query","required":true,"schema":{"type":"string","description":"A-share ticker, e.g. 000029","title":"Code"},"description":"A-share ticker, e.g. 000029"},{"name":"market","in":"query","required":true,"schema":{"type":"string","description":"SH | SZ | BJ","title":"Market"},"description":"SH | SZ | BJ"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":50,"minimum":1,"default":20,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response List Filings V1 Filings Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/filings/{aann}/parsed":{"get":{"tags":["state"],"summary":"Get Parsed Filing","description":"第 2 层：**一份**公告的解析产物 —— 规范化正文 + 结构化表格（需求 1.8 第 2 层）。\n\n🔴 **单份取，不是列表**（Fernando 2026-09-06）：列表就是 `/v1/filings`\n   （标题/日期/源链接），拿它给的 `aann_` 到这里换那一份的正文与表格。\n🔴 **只服务最近一周**：更早的公告本身与源 PDF 链接照常在第 1 层能查到全历史。\n🔴 **不返回任何置信度**（1.8 §4.0）。","operationId":"get_parsed_filing_v1_filings__aann__parsed_get","parameters":[{"name":"aann","in":"path","required":true,"schema":{"type":"string","title":"Aann"}},{"name":"text_offset","in":"query","required":false,"schema":{"type":"integer","description":"0-based offset into the filing's full text","default":0,"title":"Text Offset"},"description":"0-based offset into the filing's full text"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Parsed Filing V1 Filings  Aann  Parsed Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/stats/archived":{"get":{"tags":["state"],"summary":"Archived Count","description":"首页那个「已归档公告」计数器的数据源（G-87.6 / 裁定 18）。\n\n🔴 **不查库** —— 数字来自后台线程低频刷新的缓存（那个去重查询实测 9.6–17.6 秒，\n   随生产库负载差近 2 倍，绝不能放在请求路径上）。\n🔴 **还没刷到过基数时返回 503，不返回 0** —— 0 是一个错误的事实陈述，\n   比\"暂时没有\"更糟。前端据此隐藏整块。\n⚠️ 本端点**不计入 `sources` 统计表**（见 `app._meter`）：那张表是\n   「有没有人回来」的唯一仪器，门户流量不该冒充 API 采用信号。","operationId":"archived_count_v1_stats_archived_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Archived Count V1 Stats Archived Get"}}}}}}},"/v1/feedback":{"get":{"tags":["state"],"summary":"Feedback Capability","description":"反馈表单的**能力探测** —— 页面加载时先问一次，别等用户填完九题才发现发不出去。\n\n🔴 这是评审第 1 轮三家独立提的同一条：降级路径若只在**提交时**暴露，\n   用户会**白填九道题**才被告知失败 —— 而「发不出去」恰恰是上线首日的\n   **默认状态**（发信凭据挂在 G-194 等 Fernando 用电脑配）。\n   ⇒ 能力必须**前置可查**，页面据此一开始就显示正确的路径。\n⚠️ 本端点**只做 REST，不做 MCP 工具**（设计 2.22 §10：两壳能力对等的第一条显式例外\n   —— 反馈要人填九道题，agent 填不了也不该替人填）。","operationId":"feedback_capability_v1_feedback_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Feedback Capability V1 Feedback Get"}}}}}},"post":{"tags":["state"],"summary":"Submit Feedback","description":"收下一份反馈答卷（裁定 14 / 1.7）。\n\n🔴 **语义必须精确，不许含糊成一个 `received: true`**（评审第 1 轮 Kimi 指出）：\n   · 凭据没配 → **503**，并在响应里给出可直接点的兜底邮箱；\n   · 真发失败 → **502**，同样给兜底邮箱。**绝不谎报成功。**\n   · 成功 → 202 + `confirmation_sent` 如实反映\"用户有没有留邮箱\"。\n   丢一条真实反馈的代价，远大于让用户多点一下邮箱链接。\n🔴 **额度自保**：反馈端点有自己的小时上限（见 `FEEDBACK_MAX_PER_HOUR`），\n   远低于全局限速 —— 否则一个循环脚本能在 50 秒内烧光当日发信配额。","operationId":"submit_feedback_v1_feedback_post","requestBody":{"content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Payload"}}},"required":true},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Submit Feedback V1 Feedback Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/healthz":{"get":{"summary":"Healthz","operationId":"healthz_healthz_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Healthz Healthz Get"}}}}}}}},"components":{"schemas":{"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"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"}}}}