价格流参考文档
通过一个 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 | 订阅已接受。 |
commodity | spot 包含 GET /v1/commodities/spot/{commodity}/{currency} 的响应正文。 |
fx | rate 包含 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":"..."} 的形式送达,随后连接关闭。
| 代码 | 含义 |
|---|---|
unauthorized | API 密钥或票据缺失或无效。 |
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 | 订阅消息中的某种货币未提供。 |
revoked | API 密钥已被撤销,或其连接租约已失效。 |
slow_consumer | 客户端连续 5 秒未读取消息。 |
command_limit | 客户端在一个连接上发送了超过 30 个帧。 |
unavailable | 该流暂时不可用。请稍后重新连接。 |
文档