参考

错误码

错误总会说明哪里出了问题,并在可能时说明正确的写法。本页按通道列出各种情况,并区分哪些值得重试、哪些不值得。

通过 MCP 连接的 AI 智能体会收到同样的错误码:失败的工具调用以 Error (HTTP NNN) 开头,以稳定的错误码结尾,AI 智能体可据此自行修正调用。见下文 MCP 服务器。

#错误的结构

所有错误只有一种形式,无论是哪一层拒绝(网关、服务或校验):status: "error"、server_time 和一个 error 对象,包含稳定的 code、英文 message,以及有参数出错时的 param。error.details 是错误带有结构化数据时出现的对象,以机器可读的方式给出相同信息:suggestion、accepted、history_depth 时你的方案窗口、按时间的拒绝中的 retry_after_s。error 旁边没有其他键。

{
  "status": "error",
  "server_time": "2026-09-30T16:07:27.808Z",
  "error": {
    "code": "invalid_symbol",
    "message": "Unknown symbol 'BTCUSD'. Did you mean 'BTCUSDT'? Accepted values: ADAUSDT, AVAXUSDT, BNBUSDT, BTCUSDT, DOGEUSDT, ETHUSDT, GRAMUSDT, HBARUSDT, HYPEUSDT, LINKUSDT, LTCUSDT, NEARUSDT, SOLUSDT, SUIUSDT, TAOUSDT, TRXUSDT, UNIUSDT, USDCUSDT, USDTUSDC, XLMUSDT, XMRUSDT, XRPUSDT.",
    "param": "symbol",
    "details": {
      "suggestion": "BTCUSDT",
      "accepted": [
        "ADAUSDT",
        "AVAXUSDT",
        "BNBUSDT",
        "BTCUSDT",
        "DOGEUSDT",
        "ETHUSDT",
        "GRAMUSDT",
        "HBARUSDT",
        "HYPEUSDT",
        "LINKUSDT",
        "LTCUSDT",
        "NEARUSDT",
        "SOLUSDT",
        "SUIUSDT",
        "TAOUSDT",
        "TRXUSDT",
        "UNIUSDT",
        "USDCUSDT",
        "USDTUSDC",
        "XLMUSDT",
        "XMRUSDT",
        "XRPUSDT"
      ]
    }
  }
}

与方案相关的拒绝具有相同的结构,基于时间的拒绝还会加上 error.details.retry_after_s(同样出现在 Retry-After 响应头中)。X-Deny-Reason 响应头指明原因:rate_limited、quota_exceeded、plan_family、plan_websocket、missing_api_key、invalid_api_key 或 history_depth。

{
  "status": "error",
  "server_time": "2026-09-30T16:07:27.808Z",
  "error": {
    "code": "rate_limited",
    "message": "Rate limit exceeded: your plan allows a limited number of requests per minute. Retry after the Retry-After delay.",
    "details": {
      "retry_after_s": 2
    }
  }
}

深度相关的 403 与其他方案相关的拒绝一样,带有 X-Deny-Reason: history_depth 和 error.code: history_depth;其消息会给出该周期下可使用的最大 limit。各方案的窗口见使用限制页面。

错误码列表

请依据 error.code 进行分支处理,绝不要依据消息文本:错误码是契约,消息可能会改写。新增错误码不属于破坏性变更;重命名或删除错误码才是。

error.code原因
depth_too_large某个快照字段的深度超过了其文档规定的上限。
edge_rate_limited来自该 IP 地址的请求在边缘网关处过多(防洪:每个地址每秒 20 个,突发 40 个)。请在 1 秒后重试。
history_depth所请求的历史早于你的方案所允许的范围。
https_requiredPlain HTTP is refused: call the same URL over https://. A key sent over http:// travelled unencrypted: rotate it.
insufficient_data历史数据不足,无法计算所请求的指标。
internal_error意外的服务端错误。以递增间隔重试可能成功;若持续出现,请附上响应的 X-Request-Id 头报告。
invalid_api_keyAPI 密钥缺失、无效或已吊销。
invalid_asset该市场数据族不提供此资产。错误会列出可接受的值。
invalid_channelWebSocket:频道名称格式错误或未知;错误信息会列出可接受的格式。
invalid_depth某个快照字段的深度不是正整数。
invalid_indicatorPOST /v1/indicators 的正文无效(id、type 或参数)。
invalid_messageWebSocket:消息不是可读的 JSON 对象。
invalid_parameter某个参数的类型或取值无效。
invalid_series该宏观序列不存在。请查看该市场数据族的 /series 目录。
invalid_symbol不提供该交易对。错误会列出可接受的值(见 /v1/symbols)。
invalid_time_rangesince_ms / until_ms 不是有效的 Unix 毫秒时间戳,或 since_ms > until_ms(until_ms 含边界),或 since_ms >= before_ms。
invalid_timeframe该接口不接受此周期。
method_not_allowed该接口存在,但不支持此 HTTP 方法。
missing_api_keyNo API key was sent: put it in the X-API-KEY header (or api_key in the WebSocket URL).
missing_parameter缺少必填参数。
not_applicableWebSocket:该频道对此资产没有意义(稳定币的期货频道)。REST API 对此类请求返回 200 和 unavailable: not_applicable。
not_authenticatedWebSocket:在尚未认证的会话上收到了 auth 以外的消息(少见:密钥在握手时校验,缺少密钥时返回 401 invalid_api_key)。
not_found未知接口。
plan_family你的方案不包含该市场数据族:消息中会给出其名称,GET /v1/limits 会列出你的密钥可用的市场数据族。
plan_websocket你的方案不包含 WebSocket 数据流。
quota_exceeded你的方案的月度配额已用尽。Retry-After(以及 error.details.retry_after_s)给出距离重置的秒数,重置时间为每月第一天(UTC)。
rate_limited超出你的方案的每分钟速率。请在 Retry-After 给出的秒数后重试。
repeated_parameter某个参数出现了不止一次。
service_unavailable暂时不可用。请在 Retry-After 给出的秒数后重试。
timeframe_not_served该序列存在,但不提供此周期(例如仅有日线的序列被以 1h 请求)。接口从不提供的周期返回 invalid_timeframe。
unknown_field?fields= 或快照中的字段名不存在。
unknown_parameter该接口未声明此参数。
upstream_timeout请求耗时过长。请缩小时间窗口或深度后重试。
TypeScript
const response = await fetch(url, { headers: { "X-API-KEY": key } });
const body = await response.json();

if (body.status === "error") {
  switch (body.error.code) {
    case "rate_limited":
    case "service_unavailable":
      // Transient: wait Retry-After seconds, then retry.
      break;
    case "history_depth":
      // Ask for less history, or upgrade: error.message gives the max limit.
      break;
    case "invalid_symbol":
    case "unknown_parameter":
      // Fix the request: error.param names the culprit, error.message the fix.
      break;
    default:
      throw new Error(body.error.code + ": " + body.error.message);
  }
}

#HTTP 状态码

状态码原因修复
401
API 密钥被拒绝
API 密钥缺失、无效或已吊销(error.code:invalid_api_key)。响应带有 WWW-Authenticate: ApiKey header="X-API-KEY"。请确认 X-API-KEY 请求头确实已发送:部分 HTTP 客户端在重定向后会丢失它。可在控制台创建或复制密钥。
403
被方案拒绝
密钥有效,但方案不涵盖该请求;X-Deny-Reason 响应头带有与 error.code 相同的代码:plan_family(市场数据族不在方案内)、plan_websocket(WebSocket 数据流不在方案内)或 history_depth(历史深度超出方案窗口)。对于 plan_family 和 plan_websocket,数据存在但不在你的方案中。对于 history_depth,error.message 会给出可使用的最大 limit。
404
未知接口
该路径不存在(error.code: not_found)。如有最接近的接口,消息会给出。请检查路径:如有最接近的接口,消息会给出;所有接口都在合约中。
405
不允许的方法
接口存在,但不支持该方法(error.code: method_not_allowed);Allow 响应头列出支持的方法。使用 GET(仅 /v1/indicators 使用 POST);HEAD 可用于所有 GET 接口,OPTIONS(CORS 预检)可用于所有接口。
422
参数缺失、未知或无效
交易对、资产或序列未知或已停用、深度超过该字段上限、指标参数越界,缺少 symbol、周期不在列表中、请求多周期字段时缺少 @tf 后缀、?fields= 中有未知字段、传入路由未声明的参数或重复的参数、since_ms 或 until_ms 以秒为单位或超出范围、JSON 正文无效。对于未知的字段或参数,响应会建议最接近的名称。对于周期,会列出可接受的值。
429
超出速率或配额
每分钟请求数超过方案允许,或突发过于密集(X-Deny-Reason: rate_limited,Retry-After:距下一个令牌的等待时间);或账户月度配额已用尽(X-Deny-Reason: quota_exceeded,Retry-After:距离重置的秒数)。对于 rate_limited,等待 Retry-After 给出的秒数。对于 quota_exceeded,计数在每月第一天(UTC)重置;你也可以在控制台更换方案。
503
暂时不可用
某个读取依赖正在恢复。在 WebSocket 握手时,表示数据流服务已达到其总容量(所有账户合计):这不是你方案的连接数上限,后者以 4003 关闭。在 Retry-After 给出的延迟后重试;若无该响应头,则以递增的间隔重试。此错误本质上是暂时的。
500
意外错误
服务端故障,绝不是由请求引起。请重试;若问题持续,请附上响应中的 X-Request-Id 响应头报告给我们。
504
请求耗时过长
所请求的时间窗口或深度导致查询耗时过长(error.code: upstream_timeout)。减小 limit 或时间范围(since_ms / until_ms)后重试:原样重放请求会耗费同样的时间。

最常见的混淆

症状真实原因
密钥有效却返回 403查看 X-Deny-Reason(即 error.code)。plan_family:该端点的市场数据族不在你的方案中。plan_websocket:方案不含数据流。history_depth:请求超出方案的回溯窗口,error.details 给出允许的最大 limit。无明显原因的 invalid_api_key:HTTP 客户端在重定向后丢弃了自定义请求头;请直接调用最终 URL。
请求频率不高却返回 429用尽的是账户的月度配额(X-Deny-Reason: quota_exceeded,Retry-After:距离重置的秒数),而不是速率限制。配额在每月第一天(UTC)重置,或在更换方案后立即恢复。
快照返回 422 但没有明确信息请求多周期字段时缺少 @tf 后缀,或在单一形式的字段上加了后缀。
看似合理的深度返回 422快照的每个字段都有自己的上限和单位。CVD 最多 200 个窗口,交易所间价差最多 50 个。
在别处有效的周期返回 422日内宏观品种不接受 30m,周线只存在于 K 线和指标中。
不是错误的空响应在稳定币上请求期货指标:unavailable 键会说明适用三种原因中的哪一种。(期权和 ETF 接口只提供 BTC 和 ETH:其他资产返回 422 invalid_asset,并列出可用值。)
看似无害的参数却返回 422每个路由都会拒绝未声明的参数和重复传入的参数;快照对未知键也同样处理。响应会建议最接近的名称:拼错的参数绝不会被悄悄忽略。
看似正确的 since_ms 却返回 422since_ms 与 until_ms 的单位为毫秒。以秒、微秒或纳秒表示的时间戳会在执行前被拒绝,负数、颠倒或早于 2009-01-03 的边界也一样——since_ms=0 除外,它表示数据的起点。

#指标

校验按固定顺序进行(timeframe、limit、交易对、解析指标、上限规则、读取 K 线),以第一个失败为准。因此修正后的请求体可能暴露第二个错误。

情况状态码
周期无效、limit 不在 1–1000 之间、交易对未知422
indicators 列表为空,或某个条目不是对象422
缺少 id 或 type 键,id 无效,或请求体字段未知422
不支持的类型422
该类型的未知参数(例如带 period 的 obv)422
参数类型错误,或低于最小值422
macd 或 adosc 的 fast 大于或等于 slow422
sar 的 acceleration 大于 maximum422
标识符重复422
正文格式错误、超过 50 个实例、字段过长422
limit 加预热超过 1000422
该周期数据不足,或成交量历史太短,不足以计算成交量类指标422

#WebSocket 数据流

每个无法满足的请求都会收到 op: error 消息,说明期望的内容:有效交易对列表、频道列表、depth 的范围。有三种情况不会产生错误,而是关闭连接:

代码原因
4003 · 上限已达到方案的同时连接数上限。原因中会给出上限。断开连接会立即释放名额。
4005 · 客户端过慢发送队列已溢出十次。请加快消费速度,或减少频道数量。原因会区分这两种情况。
4001实际上不再发送:密钥在握手时校验(401),在已打开的会话上发送 auth 帧会返回 authenticated。
4002会话在五秒内始终未认证。由于密钥已在握手时校验,这种情况很少见。

密钥在握手时(连接打开前)校验:缺少密钥返回 401 missing_api_key,密钥未知或已吊销返回 401 invalid_api_key(带 WWW-Authenticate),不含数据流的方案(Free)返回 403 plan_websocket——每次都是 X-Deny-Reason 的值。此时的 429 表示打开连接过于频繁,503 表示数据流服务已达容量上限(所有账户合计):请稍后重试。连接后,若频道所属市场数据族不在方案内,会收到带 error.code: plan_family 的 op: error,整个订阅被拒绝。参见使用限制。

#MCP 服务器

错误遵循同一种格式 Error (HTTP NNN): message [code: …],失败的工具调用会被标记为 MCP 错误(isError),同一错误也放在 structuredContent.error 中:status, code, message,适用时还有 param, hint, retry_after_s。每次工具调用都按使用客户端密钥的 REST 请求来判断:方案外数据族的 403 或配额相关的 429 会原样返回,并附带其消息和 error.code。有两类错误是它特有的:

  • 请求无效:未知字段;缺少目标(symbol、asset、series),或提供了所请求字段都不需要的目标;所选路由不接受的参数;没有任何字段使用的 timeframe;对不支持日期窗口的字段指定窗口。所有问题在一条消息中列出,并且在任何网络调用之前返回。
  • 部分响应:在五个 MCP 数据工具(get_pair_data、get_options_data…)中,某个字段出错不会影响其他字段。它会列在 errors 下,响应带有 partial: true;只有所有字段都失败时,调用本身才会失败。

只有在上游没有响应时(502、503、504 或网络故障)才会重试:500 不会重放,因为每个请求都计入客户端配额。超时会在三十秒后返回 Error (HTTP 504)。

#重试策略

并非所有请求都可以重放。重放错误的请求只会得到完全相同的响应,白白消耗配额。

Python
import httpx  # pip install httpx


def should_retry(response: httpx.Response) -> bool:
    """What is transient, and what never will be (the official SDKs do the same)."""
    # A spent monthly quota only resets on the 1st of the month: fail fast.
    if response.status_code == 429 and response.headers.get("X-Deny-Reason") == "quota_exceeded":
        return False
    # 429 (rate) and 503: the server says when, in Retry-After. 502 and 504:
    # a gateway hiccup or a slow query. Retry with an increasing delay.
    if response.status_code in (429, 502, 503, 504):
        return True
    # 500: a fault on the service side, retry once.
    if response.status_code == 500:
        return True
    # 401, 403, 404, 405, 422: the request is at fault. Replaying it as is
    # produces exactly the same response.
    return False
  • 遵守 Retry-After,不要自行设定延迟:服务器知道自己何时就绪。
  • 限制重试次数。三到四次就够了:再多说明问题不是暂时的。
  • 不要重放 4xx(429 除外)。请修正请求。
  • 在数据流上,请以递增的延迟重连,并查看关闭代码:4003 表示已达方案上限,需先关闭账户的另一个连接;4005(client too slow)表示客户端过载,不改变消费方式而重连会再次被断开。握手时的 503 只需等待。