Skip to content

feat(docs): API Reference — 全量 REST 接口文档 + AI 可读层 - #1257

Open
hogan-yuan wants to merge 84 commits into
mainfrom
feat/api-reference-expansion
Open

hogan-yuan wants to merge 84 commits into
mainfrom
feat/api-reference-expansion

Conversation

@hogan-yuan

@hogan-yuan hogan-yuan commented Sep 14, 2026

Copy link
Copy Markdown
Member

⚠️ Merge blocker — depends on two upstream PRs.
The counter_id → symbol migration in this PR must not be published until both of these merge:

Until both land, production still speaks counter_id; publishing symbol-only docs first would mismatch live behavior. Every counter_id → symbol change here is gated on this: screener_search / industry_rank / industry_peers response fields → symbol, profit_analysis_summary drops *_counter_id and *_symbol, request params (industry_peers / grid_symbol_info) → symbol, and the aligned .mdx pages (top_movers, valuation_comparison, industry_rank/peers, cli industry-rank/peers, grid symbol_info). Exceptions kept as-is: monitor_counter_id (conditional-order monitor) and the order files' "Counter order ID".


Overview

Adds an API Reference to the docs site (/docs/api) covering all 142 REST endpoints from openapi-rust, trilingual (en / zh-CN / zh-HK), plus an AI-readable Markdown layer. Styling matches the docs pages exactly.

What's included

  • Full endpoint coverage: 142 REST operations, authored/extracted against the Rust core as the source of truth — parameters split into path/query/body, request examples (raw HTTP in 8 languages), response properties, response JSON, and error codes.
  • AI-readable layer: /docs/api.md and /docs/api/{op}.md (all three locales), wired into llms.txt / llms-full.txt so an LLM can consume the reference directly.
  • Authentication page: OAuth 2.0 (Bearer, default) + API-Key (HMAC-SHA256) with signing reference implementations in 7 languages.
  • Three-level sidebar: mirrors the docs tree (section › subsection › endpoint), trilingual, in docs order.
  • Path-based URLs: /docs/api/{operationId} is the canonical, shareable URL (legacy ?op= still works), with canonical / hreflang / rel="alternate" type="text/markdown" links.
  • Docs-matched callouts: quote-permission cards and :::warning / :::tip colored admonition boxes.

Issues found and fixed during audit

Reviewed against "can an LLM build a working call", cross-checking the Rust source as ground truth:

  • Restored 4 silently dropped operations: list_alerts / delete_alert / list_sharelists / sharelist_remove_securities — an earlier generator pass rebuilding multi-method paths had removed their GET/DELETE siblings.
  • Auth timestamp unit: X-Timestamp was documented as milliseconds but is actually seconds; fixed the headers table and all 7 signing examples (copying the old docs produced a 403 — seconds verified against the live API).
  • Wire-name fidelity: 6 endpoints (screener/search, broker-holding, finance_calendar, …) used SDK argument names → corrected to the real serde wire names.
  • Nested request-body examples: submit_order and siblings now emit real nested JSON instead of malformed dotted keys.
  • Content/AI params: 10 endpoints documented via the ### Request Body format had their parameters extracted.
  • Readability cleanup: dead type anchors, dead relative links, <br/>, and escape artifacts removed; enum values inlined.

Verification

  • Unit tests 10/10, oxlint clean.
  • Both auth methods tested live against read-only endpoints: API-Key (HMAC) 4/4 with real data; OAuth requires an OAuth-issued token.
  • Cross-checked against the Rust Path: declarations: 0 missing, 0 fabricated paths, methods match.

…ers/Request Example tabs, Response Properties, Response JSON, Error Code, On-this-page TOC, light code); regenerate DCA
…signature) in raw-HTTP examples, add Authentication page, fix code highlighter corrupting URLs
…are page group, dividers, collapsible tag sections with caret, rounded brand highlight)
…cture (docs-layout/sidebar/docs-body/docs-inner/docs-main/article.docs-content/docs-toc) so HTML + styling match docs exactly
…nner), suppress big marketing footer — full docs parity
…eal HTTP wire field names; drop 'SDK method parameters' note; regenerate DCA (wire request)
…stale rows leaking across endpoints on CSR navigation
…r-language API-Key signing helpers to Authentication page; link endpoints to it
…n Authentication page (cURL/Python/Node/Java/Rust/C++/Go)
…prefix (dca_list DcaPlan under plans, unify with dca_history)
…content typography (match endpoint page style)
16 trade/asset ops had raw <br/><br/> / <br/> in param & response descriptions
(carried from docs table cells). With the reference's markdown-it html:false,
these rendered as literal '<br/>' in the CSR and .md. Convert consecutive <br/>
to '. ' (paragraph) and single <br/> to ', ' (inline enum lists) across 359
fields.
Make /docs/api/<operationId> the canonical shareable URL for an endpoint
(previously only /docs/api?op=<id> worked). The React app now reads the op from
the pathname (query ?op= kept as a fallback for old links) and pushes path URLs
on navigation. Add prerendered [op].astro routes (en + zh-CN/zh-HK) so direct
load, refresh, and sharing of /docs/api/<op> resolve — rendering the same
interactive reference, with the endpoint summary in the page title.
list_alerts (GET /v1/notify/reminders), delete_alert (DELETE same),
list_sharelists (GET /v1/sharelists) and sharelist_remove_securities
(DELETE /v1/sharelists/{id}/items) were silently lost: an earlier
request-example regeneration rebuilt only body-bearing methods (post/put) for
each path and its removePaths+reinsert dropped the GET/DELETE siblings on those
multi-method paths. Restore them (verified against the Rust Path: doc-comments —
0 operations now missing) and clean their descriptions. 138 → 142 ops.
X-Timestamp is unix SECONDS, not milliseconds. Verified against a live API call
(seconds pass, ms fail the timestamp check) and the Rust SDK
(Timestamp::now() uses as_secs()). The headers table and all 7 signing
reference implementations (cURL/Python/Node/Java/Rust/C++/Go) computed
milliseconds — copying any of them produced a 403. Corrected to seconds.
…check

@types/markdown-it-container targets a different @types/markdown-it build, so
its plugin signature doesn't unify with our MarkdownIt instance — astro check
(tsc) failed. Cast it to the expected use() parameter type.
The language switcher used the server-rendered currentPath, which goes stale
after the API reference navigates client-side (pushState to /docs/api/<op>) —
switching locale dropped back to /docs/api. Read the live window.location when
the menu opens, and preserve any ?query (e.g. ?page=) across locales.
Traditional Chinese nav/search used 文件 (file) for documentation; zh-CN uses
文档, so zh-HK should be 文檔. Fixes the top-nav Docs entry and the
nav.docs / nav.searchDocs / search.placeholder strings.
counter_id (internal identifier, e.g. ST/HK/700) is not meaningful to API
consumers. Remove it from response properties of top_movers,
valuation_comparison, today_orders, history_orders. Kept for industry_rank /
industry_peers, which are counter_id-based endpoints; params left untouched.
…oints)

Verified against the live API: docs had SDK-shaped/wrong response fields. Rewrite
to the actual raw shape:
- option_volume: c / p (docs wrongly said call_volume / put_volume)
- short_positions_hk/us, short_trades_hk/us: real data[] item fields (HK and US
  differ; docs used one wrong shape for both)
- institution_rating: evaluate{}/target{}/industry_* (docs shape was entirely wrong)
…and company_profile

option_volume_daily documented SDK-transformed names (call_volume, pc_vol,
date, top-level symbol) instead of the raw HTTP wire shape. The Rust SDK's
RawDailyStat deserializes total_call_volume/total_put_volume/
total_call_open_interest/total_put_open_interest/total_volume/
total_open_interest/put_call_volume_ratio/put_call_open_interest_ratio with a
per-record timestamp, and the top-level symbol is injected from the request
param (not in the response). Rewrote x-response-properties accordingly.

company_profile documented 'phone' but the wire field is 'Phone' (the SDK
maps it via #[serde(rename = "Phone")]).
…shape

Verified against the live API: the response is { total, items:[{ counter_id,
name, indicators:[{key,name,value,unit}] }] } — nested indicators, not the
flat SDK-transformed { symbol, pettm, marketcap, ... } that was documented.
Indicator keys carry the filter_ prefix and values are strings; the SDK strips
the prefix and the old docs described that transformed output. Also corrected
the JSON-output warning box and removed redundant hardcoded 'interface: POST ...'
lines duplicated across five screener endpoints (zh/zh-HK only).
…e raw API

The response definitions for 46 endpoints described the SDK-transformed shape
rather than the raw HTTP wire shape. Regenerated x-response-properties directly
from live API responses (captured with real credentials), so field names,
nesting, and types now match what the API actually returns.

Key corrections include: nested structures that were wrongly flattened
(valuation_comparison, industry_valuation, industry_valuation_dist,
financial_report_snapshot, us_company_dividends, us_valuation_overview,
security_facts, profit_analysis_summary), SDK-invented fields removed
(history-order fields, executives), and raw metric names restored
(price_close, market_value, div_yld, roe, net_margin, etc.).

counter_id policy: where the raw response carries both counter_id and a
sibling symbol, only symbol is documented; where counter_id is the sole
identifier it is kept.

Endpoints whose live sample contained an empty array/object (params could not
populate the data) were intentionally left untouched to avoid dropping
documented fields; those will be handled with correct params or manually.
etf_asset_allocation, us_etf_files, short_positions_us, short_trades_us —
re-captured with correct params/symbols (SPY.US for ETFs, AAPL.US for US short
data) and regenerated x-response-properties from the real responses.
…aw API

Relaxed the empty-container guard so an endpoint whose top-level payload is
populated is regenerated even when a deeper array/object is empty in the sample
(the empty container is kept as a leaf field rather than discarding the whole
endpoint). This recovers history_orders (35 real fields, replacing 65
SDK-invented ones), screener_indicators (nested groups[].indicators[]),
index_components, business_segments_history, popular_sharelists, operating, and
others — all with field names/nesting from the real responses.

valuation and valuation_history are excluded from auto-regeneration (empty-string
metric key / per-symbol dynamic map) and will be handled manually.
…ecutions

today_orders and today_executions return the same Order/Execution types as
history_orders and history_executions (verified in rust/src/trade/context.rs),
and share the same wire response format. The account had no same-day data to
capture live, so their response fields are reused from the history_* siblings
(already rebuilt from live data).
Verified against rust/src/trade/types.rs FundPosition: the account had no fund
holdings to capture live (empty list), so the field was cross-checked from the
Rust wire struct. holding_units was missing from the documented item shape.
…riptions

Let the example value carry the meaning instead of explaining the prefix in
prose: indicator key descriptions now read 'e.g. `filter_pettm`' and the
filters param description drops the trailing '— the indicator key is prefixed
with filter_' clause (the `filter_<indicator>` example already shows it).
…ors/screener_strategy keys

The response 'key' field for screener_indicators and screener_strategy was
documented as 'no filter_ prefix', but the raw API actually returns keys WITH
the prefix (verified live: filter_market, filter_industry, ...) — the SDK strips
it. Corrected to show the real prefixed example instead.
…ecision

- screener_search: item counter_id -> symbol
- industry_rank: industry counter_id -> symbol (usable as symbol in industry_peers)
- industry_peers: sector counter_id -> symbol
- profit_analysis_summary: drop profit_max_counter_id / loss_max_counter_id
  (profit_max_symbol / loss_max_symbol already present)

monitor_counter_id on today_orders / history_orders is intentionally kept.
…profit_analysis_summary

Per decision, the max-profit/max-loss security identifiers are not exposed at
all — only the amounts (profit_max/loss_max) and display names (*_name) remain.
… with CLI #319 / MCP #128)

industry_peers and grid_symbol_info query params counter_id -> symbol, matching
longbridge-terminal#319 and longbridge-mcp#128 which move every raw endpoint to
symbol-based requests. No counter_id request params remain in the reference.
top_movers, valuation_comparison, industry_rank, industry_peers, cli
industry-rank/peers, and grid symbol_info now show symbol instead of the
internal counter_id, matching the openapi.yaml reference. Value examples
converted (ST/US/AAPL -> AAPL.US, BK/US/IN00258 -> IN00258.US); the top_movers
logo URL and the order files' 'Counter order ID' are intentionally untouched.

NOTE: this counter_id -> symbol migration depends on longbridge-mcp#128 and
longbridge-terminal#319 — the docs must not be published until BOTH PRs merge
(they move requests/responses to symbol end to end; until then production still
speaks counter_id).
industry_rank / industry_peers: response-example JSON counter_id -> symbol
(BK/US/IN00258 -> IN00258.US) and request-example query params counter_id ->
symbol. Same cleanup for grid_symbol_info request examples and top_movers /
valuation_comparison examples (dropping counter_id where a symbol sibling
already exists).

Only today_orders / history_orders retain counter_id: monitor_counter_id
(conditional-order monitor) and the order response's 'Counter order ID', both
intentionally kept.

NOTE: depends on longbridge-mcp#128 and longbridge-terminal#319 — do not publish
until both merge.
An earlier `git add docs/` swept six untracked docs/superpowers plan and spec
files into the tree; one of them (2026-06-11-macroeconomic-docs.md) failed the
autocorrect CI on CJK-colon punctuation. These are local planning artifacts that
should not be version-controlled — removed from git (kept on disk).
…endpoints

The API Reference documents the raw HTTP response, so notes that explain how the
SDK/CLI reshape it are noise. Removed the 'JSON output format' warning on
screener_search and the 'SDK response' warning on screener_indicators, and fixed
the screener_indicators key description which wrongly said 'no filter_ prefix'
(the raw response keys DO carry the prefix, e.g. filter_market). Also simplified
the returns-param prefix wording to an example (e.g. `filter_pettm`).
…ilters description

Replace the <indicator>/<min>/<max> placeholders with a real example
(filter_pettm, 10, 30), consistent with the other filter_ key descriptions.
The CLI --filter flag takes the bare indicator name (e.g. marketcap); it adds the
filter_ prefix internally before calling the gateway. Corrected the screener
search CLI examples in openapi.yaml and the screener .mdx pages from
--filter filter_marketcap:... to --filter marketcap:... (response keys still
carry the filter_ prefix — that is the raw wire field, unaffected).
Comment thread docs/superpowers/plans/2026-06-11-macroeconomic-docs.md Outdated
Comment thread docs/superpowers/plans/2026-06-11-macroeconomic-docs.md Outdated
Comment thread docs/superpowers/plans/2026-06-11-macroeconomic-docs.md Outdated
Comment thread docs/superpowers/plans/2026-06-11-macroeconomic-docs.md Outdated
Comment thread docs/superpowers/plans/2026-06-11-macroeconomic-docs.md Outdated
Comment thread docs/superpowers/plans/2026-06-11-macroeconomic-docs.md Outdated
Comment thread docs/superpowers/specs/2026-04-21-mcp-menu-and-tools-design.md Outdated
Comment thread docs/superpowers/specs/2026-04-21-mcp-menu-and-tools-design.md Outdated
Comment thread docs/superpowers/specs/2026-04-21-mcp-menu-and-tools-design.md Outdated
Comment thread docs/superpowers/specs/2026-04-21-mcp-menu-and-tools-design.md Outdated
…ded plans/specs

The previous .gitignore un-ignored docs/superpowers/{plans,specs}/** wholesale,
so a broad `git add docs/` kept re-adding local planning docs (one failed
autocorrect CI on CJK punctuation). Simplified to ignore docs/superpowers/*
entirely and removed the six plan/spec files that slipped in. Already-tracked
astro-migration docs on main are unaffected (gitignore does not touch tracked
files).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant