认证
一把密钥即可打开三个通道。它在每个通道中的传递方式不同(REST 和 MCP 用请求头,WebSocket 在握手时用 URL 参数),但值处处相同,且在每个通道上适用的都是你方案的权限。
#REST API
密钥放在 X-API-KEY 请求头中。不使用 URL 参数,也不使用 Authorization: Bearer:放在查询字符串中的密钥会出现在沿途每个中间节点的访问日志里。
curl -H "X-API-KEY: $BYTNODE_KEY" \
"https://api.bytnode.com/v1/basis?symbol=ETHUSDT"比较以恒定时间执行:错误的密钥与几乎正确的密钥被拒绝所需的时间完全相同。
#无需密钥的接口
只有一个接口无需认证即可访问:/v1/health,用于告知服务是否正常。紧接着会调用的两个接口(数据新鲜度和资产目录)与其他所有接口一样需要密钥。/v1/status 是探测接口:从不计入月度配额,但受方案的速率限制约束。/v1/symbols 属于价格与成交量数据族,在所有方案中开放,与其他调用一样计数。
GET/v1/health无需密钥
GET/v1/status
GET/v1/symbols
# The only route that answers without a key.
curl https://api.bytnode.com/v1/health
# The next two require the key. /v1/status is a probe: never counted
# against the monthly quota, but subject to the rate limit of the plan.
curl -H "X-API-KEY: $BYTNODE_KEY" https://api.bytnode.com/v1/status
curl -H "X-API-KEY: $BYTNODE_KEY" https://api.bytnode.com/v1/symbols#WebSocket 数据流
密钥以 ?api_key= 参数的形式放在 URL 中,并在握手时校验,早于连接建立。浏览器无法为 WebSocket 设置请求头:这是唯一在任何环境都可行的方式,也是示例中使用的方式。
import asyncio
import json
import os
import websockets
async def main() -> None:
# The key travels in the URL, at the handshake: the connection opens
# already authenticated. A missing or invalid key gets 403 before it opens.
url = f"wss://api.bytnode.com/ws?api_key={os.environ['BYTNODE_KEY']}"
async with websockets.connect(url) as ws:
await ws.send(json.dumps({
"op": "subscribe",
"channels": ["trades.futures.BTCUSDT"],
}))
print(await ws.recv()) # {"op": "subscribed", "channels": [...]}
asyncio.run(main())会话建立时即已认证:第一条消息就可以是订阅。密钥缺失、无效或已吊销,或方案不包含数据流时,握手阶段会返回 403,不会建立任何连接。方案的同时连接数上限适用于整个账户:超出的连接会以代码 4003 关闭。旧的 {"op": "auth", "api_key": "…"} 帧仍被接受并返回 ok,但它是可选的。
#MCP 服务器
MCP 服务器需要同一把密钥,放在同一个 X-API-KEY 请求头中,设置在 HTTP 连接上。没有密钥时不会暴露任何工具:服务器默认拒绝,而不是默认开放。
from fastmcp import Client
headers = {"X-API-KEY": "your_key"}
async with Client("https://mcp.bytnode.com", headers=headers) as client:
info = await client.call_tool("get_system_info", {})配置文件的具体格式取决于智能体;原则不变:一个 URL 和一个请求头。见 MCP 服务器。
#拒绝响应说明了什么
| 通道 | 响应 | 原因 |
|---|---|---|
| REST | 403, X-Deny-Reason: key | 请求头缺失,或密钥未知或已吊销。正文为 « Cle API absente, invalide ou revoquee »。 |
| REST | 403, X-Deny-Reason: family | 密钥有效,但该端点所属的数据族不在你的方案中。 |
| MCP | 401, header X-API-KEY requis | 连接上缺少请求头,或密钥被拒绝。校验发生在公布任何工具之前;之后,每次工具调用都会按密钥的权限判断。 |
| WebSocket | 握手时返回 403 | URL 中的密钥缺失或无效(key),或方案不含数据流(websocket)。连接不会建立。 |
| WebSocket | 关闭码 4003 | 已达到方案的同时连接数上限,按整个账户计算。原因中会给出上限。 |
#保护与轮换密钥
存放在哪里
- 放在环境变量或密钥管理器中,绝不放入代码仓库。
- 仅限服务器端。放在网页 JavaScript 中的密钥等同公开,无论如何混淆。
- 每个环境一把密钥:开发、预发布、生产。这样一旦泄露,可以只吊销它而不影响其他环境。
轮换
- 在控制台中创建新密钥。重叠期内两把密钥均有效。
- 将新密钥部署到所有地方,然后确认旧密钥上的流量已降为零。
- 吊销旧密钥。吊销立即生效。