浏览全部文档

价格流参考文档

通过一个 WebSocket 连接获取商品现货价格和外汇汇率,接收每个订阅项的初始价格及价格变化时的更新

访问权限与限制

价格流适用于 Basic 和 Pro 套餐。 使用 Free 套餐密钥时会收到 plan_upgrade_required,随后连接关闭。

价格、事件和预测流共用并发连接数上限:Free 为 1 个,Basic 为 2 个,Pro 为 10 个。每个连接消耗一次月度调用额度。

连接

将 API 密钥放入 Authorization: Bearer 请求头,连接到 wss://api.narwhalapi.com/v1/prices/stream。

浏览器无法在 WebSocket 连接中设置该请求头。请从服务器发送 POST /v1/prices/stream-ticket,然后通过 ?ticket= 携带返回的票据建立连接。票据只能使用一次,30 秒后过期,且要求来源已获允许。 预测流遵循相同的票据规则。

订阅

服务器发送 {"type":"ready"}。请在 5 秒内发送一条订阅消息:

订阅消息
{
  "action": "subscribe",
  "commodities": [
    {
      "commodity": "XAU",
      "currency": "USD"
    }
  ],
  "fx": [
    {
      "base": "USD",
      "currencies": [
        "EUR",
        "JPY"
      ]
    }
  ]
}
  • commodities:最多指定 20 个受 GET /v1/commodities/spot/{commodity}/{currency} 支持的商品与货币组合。
  • fx:最多指定 5 种基准货币。currencies 为可选项:省略时接收该基准货币支持的所有货币,也可以列出最多 64 种货币。

服务器回复 {"type":"subscribed"},并将每个已订阅价格发送一次。此后,仅在价格变化时发送。价格约每秒检查一次。

要更改订阅,请重新连接。发送第二条订阅消息会导致连接以 resubscribe_required 关闭。

消息

价格消息的正文与 REST 端点的响应正文相同,包括小数位数、回退值和数据过期标志。

消息内容或频率
ready连接建立时发送。请在 5 秒内订阅。
subscribed订阅已接受。
commodityspot 包含 GET /v1/commodities/spot/{commodity}/{currency} 的响应正文。
fxrate 包含 GET /v1/fx/rates/{base} 的 rates 中的一个条目,以及 base 和 market_session。
heartbeat每 30 秒发送一次,包含 as_of。
pong对 {"action":"ping"} 的回复。
error包含错误 code;随后连接关闭。
商品价格消息
{
  "type": "commodity",
  "spot": {
    "symbol": "XAU-USD",
    "price": "4195.86",
    "currency": "USD",
    "unit": "troy_ounce",
    "timestamp": "2026-10-11T06:25:00Z",
    "stale": false
  }
}
外汇汇率消息
{
  "type": "fx",
  "base": "USD",
  "market_session": "open",
  "rate": {
    "currency": "EUR",
    "rate": "0.8924",
    "timestamp": "2026-10-09T00:00:00Z",
    "stale": false
  }
}

现货价格参考文档 · 外汇汇率参考文档

保持连接

发送 {"action":"ping"} 可收到 {"type":"pong"}。服务器还会每 30 秒发送一次 heartbeat。请及时读取消息:客户端若连续 5 秒不读取消息,连接将以 slow_consumer 关闭。

每个连接最多可发送 30 个帧。重新连接后,所有已订阅价格都会再次发送;错过的价格变化不会重放。

错误

错误以 {"type":"error","code":"..."} 的形式送达,随后连接关闭。

代码含义
unauthorizedAPI 密钥或票据缺失或无效。
plan_upgrade_required使用该流需要 Basic 或 Pro 套餐。
stream_limit已达到套餐的流并发连接数上限。
quota_unavailable月度额度已用尽或无法检查。
subscribe_required发送就绪消息后 5 秒内未收到订阅消息。
resubscribe_required发送了第二条订阅消息。请重新连接以更改订阅。
invalid_command该消息不是订阅或 ping 操作。
invalid_frame该消息不是有效的 JSON,或超出了订阅限制。
commodity_not_supported订阅消息中的某种商品未提供。
currency_not_supported订阅消息中的某种货币未提供。
revokedAPI 密钥已被撤销,或其连接租约已失效。
slow_consumer客户端连续 5 秒未读取消息。
command_limit客户端在一个连接上发送了超过 30 个帧。
unavailable该流暂时不可用。请稍后重新连接。