Response envelope
Every endpoint wraps its result in the same six outer fields, and the payload itself lives in data, which comes in more than one shape. Some errors (missing parameter, over the limit, a paid endpoint without a key) use a different structure — do not parse those as the envelope.
What it looks like
Except for /v1/health, every successful response has these six outer fields:
{
"ok": true,
"endpoint": "kline",
"tier": "free",
"elapsed_ms": 701,
"source": "multi",
"data": [ "…the actual data is here…" ]
}
| Field | Type | Meaning |
|---|---|---|
ok |
boolean | Whether data was retrieved. Check this before reading data |
endpoint |
string | Endpoint name (e.g. kline, quote) |
tier |
string | The tier this request was served at (free for anonymous calls; the key’s tier when a key is used) |
elapsed_ms |
number | Server-side latency in milliseconds |
source |
string | Data-source label |
data |
depends on endpoint | The actual payload |
The shapes data can take
data differs by endpoint, so check the type before reading it:
| Shape | Appears on | How to read it |
|---|---|---|
| Array (one row per element) | kline, quote, hot … |
data[0], then a field, e.g. data[0].last |
| Object | single-record endpoints | read fields directly |
| Pre-rendered text (a string) | market-overview, changedist … |
structured / tables are added alongside; use those for programmatic access |
| Multi-segment | endpoints that return several tables at once | pick segments out of tables |
For text endpoints: data is a block of markdown, and two extra fields appear — structured is the first table ([{column: value}]) and tables is every table. data itself is unchanged: text clients keep using data, programmatic clients use structured.
Can you trust source?
source is a data-source label. You may look at it, but do not branch on it in business logic — its value is not guaranteed to be stable, and it does not identify any particular upstream.
What a failure looks like
ok: false means no data was retrieved this time (data may be empty or absent). Two things to note:
- The HTTP status is still 200 (the envelope is the body);
- Check
okfirst, then decide whether to usedata.
Responses that are not the envelope
These do not use the structure above — do not parse them as the envelope:
| Situation | HTTP | What comes back |
|---|---|---|
Missing required parameter (e.g. no code) |
422 | {"detail": [{"loc": ["query", "code"], "msg": "Field required", "input": null}]} |
| Paid endpoint called anonymously | 401 | {"error": "需要 API Key(此端点属付费层)", "docs": "/docs"} |
| Anonymous rate limit exceeded | 429 | {"error": "匿名限流 …", "pow": { … }, "how_to": "…"} |
The common trait: no ok field — the top level is error or detail. A robust client should therefore check the HTTP status first, then check for ok. Other error codes are listed under Errors and rate limits.
/v1/health is the exception
/v1/health returns no data; it returns service status:
{ "ok": true, "uptime_s": 123456, "data_ready": true, "tiers": ["free", "pro"] }
data_ready: true means the data channel is available.
Last updated: 2026-10-05
Field meanings and failure semantics taken from live responses and the endpoint definitions on 2026-10-05; error shapes measured against free endpoints such as /v1/kline.