跳到主要内容

Binance 的公共 WebSocket API (2024-10-17)

API 基本信息

  • 本篇所列出的 wss 接口的 base URL:wss://ws-api.binance.com:443/ws-api/v3
    • 如果使用标准443端口时遇到问题,可以使用替代端口9443。
    • 现货测试网的 base URL 是 wss://testnet.binance.vision/ws-api/v3
  • 每个到 base URL 的链接有效期不超过24小时,请妥善处理断线重连。
  • Websocket 服务器每3分钟发送Ping消息。
    • 如果Websocket服务器在10分钟之内没有收到Pong消息应答,连接会被断开。
    • 当客户收到ping消息,必需尽快回复pong消息,同时payload需要和ping消息一致。
    • 未经请求的pong消息是被允许的,但是不会保证连接不断开。对于这些pong消息,建议payload为空
  • 响应中如有数组,数组元素以时间时间顺序排列,越早的数据越提前。
  • 除非另有说明,所有与时间戳相关的字段均以UTC的毫秒为单位。
  • 除非另有说明,所有字段名称和值都大小写敏感

请求格式

请求必须在 text 帧 中以 JSON 格式发送,每帧一个请求。

请求示例:

{
"id": "e2a85d9f-07a5-4f94-8d5f-789dc3deb097",
"method": "order.place",
"params": {
"symbol": "BTCUSDT",
"side": "BUY",
"type": "LIMIT",
"price": "0.1",
"quantity": "10",
"timeInForce": "GTC",
"timestamp": 1655716096498,
"apiKey": "T59MTDLWlpRW16JVeZ2Nju5A5C98WkMm8CSzWC4oqynUlTm1zXOxyauT8LmwXEv9",
"signature": "5942ad337e6779f2f4c62cd1c26dba71c91514400a24990a3e7f5edec9323f90"
}
}

请求字段:

名称类型是否必需描述
idINT / STRING / nullYES任意的 ID 用于匹配对请求的响应
methodSTRINGYES请求函数名称
paramsOBJECTNO请求参数。如果没有参数可以省略
  • 请求 id 是任意的。可以使用 UUID、顺次 ID、当前时间戳等。 服务器不会以任何方式解释 id,只是在响应中回显它。

    可以在一个会话中自由重复使用 ID,不过请注意不要一次发送多个具有相同 ID 的请求,因为否则可能无法区分响应。

  • 请求函数名称可以以显式版本为前缀,例如:"v3/order.place"

  • params 的顺序不重要。

响应格式

响应在 text 帧 中以 JSON 格式返回,每帧一个响应。

成功响应示例:

{
"id": "e2a85d9f-07a5-4f94-8d5f-789dc3deb097",
"status": 200,
"result": {
"symbol": "BTCUSDT",
"orderId": 12510053279,
"orderListId": -1,
"clientOrderId": "a097fe6304b20a7e4fc436",
"transactTime": 1655716096505,
"price": "0.10000000",
"origQty": "10.00000000",
"executedQty": "0.00000000",
"cummulativeQuoteQty": "0.00000000",
"status": "NEW",
"timeInForce": "GTC",
"type": "LIMIT",
"side": "BUY",
"workingTime": 1655716096505,
"selfTradePreventionMode": "NONE"
},
"rateLimits": [
{
"rateLimitType": "ORDERS",
"interval": "SECOND",
"intervalNum": 10,
"limit": 50,
"count": 12
},
{
"rateLimitType": "ORDERS",
"interval": "DAY",
"intervalNum": 1,
"limit": 160000,
"count": 4043
},
{
"rateLimitType": "REQUEST_WEIGHT",
"interval": "MINUTE",
"intervalNum": 1,
"limit": 6000,
"count": 321
}
]
}

失败响应示例:

{
"id": "e2a85d9f-07a5-4f94-8d5f-789dc3deb097",
"status": 400,
"error": {
"code": -2010,
"msg": "Account has insufficient balance for requested action."
},
"rateLimits": [
{
"rateLimitType": "ORDERS",
"interval": "SECOND",
"intervalNum": 10,
"limit": 50,
"count": 13
},
{
"rateLimitType": "ORDERS",
"interval": "DAY",
"intervalNum": 1,
"limit": 160000,
"count": 4044
},
{
"rateLimitType": "REQUEST_WEIGHT",
"interval": "MINUTE",
"intervalNum": 1,
"limit": 6000,
"count": 322
}
]
}

响应字段:

名称 类型 是否必需 描述
id INT / STRING / null YES 与原来请求的ID一样
status INT YES 响应状态。请看 状态代码
result OBJECT / ARRAY YES 响应内容。请求成功则显示
error OBJECT 错误描述。请求失败则显示
rateLimits ARRAY NO 速率限制状态。请看 速率限制

状态代码

status 字段的状态代码与HTTP的状态代码相同。

一些常见状态代码:

  • 200 代码指示成功响应。
  • 4XX 错误码用于指示错误的请求内容、行为、格式。问题在于请求者。
    • 400 – 错误码表示请求失败,请参阅 error 了解原因。
    • 403 – 错误码表示违反 WAF 限制(Web应用程序防火墙)。
    • 409 – 错误码表示请求有一部分成功,一部分失败。请参阅 error 了解更多详细。
    • 418 – 表示收到 429 后继续访问,于是被封了。
    • 429 – 错误码表示警告访问频次超限,即将被封IP。
  • 5XX 错误码用于指示Binance服务侧的问题。
    • 重要:如果响应包含 5xx 状态码,并不一定意思请求失败。 执行状态为 unknown,请求可能实际成功。 请使用 query 函数确认状态。 建议建立一个新 WebSocket 连接用于确认状态。

有关错误代码和消息的列表,请参阅 Binance 的错误代码

速率限制

连接数量限制

每IP地址、每5分钟最多可以发送300次连接请求。

速率限制基本信息

  • exchangeInfo 有包含与速率限制相关的信息。
  • 根据不同的间隔,有多种频率限制类型。
  • 从响应中的可选 rateLimits 字段,能看到当前的频率限制状态。
  • 当您超出未成交订单计数或者请求速率限制时,请求会失败并返回 HTTP 状态代码 429。

如何咨询频率限制

频率限制状态的响应可能如下所示:

{
"id": "7069b743-f477-4ae3-81db-db9b8df085d2",
"status": 200,
"result": {
"serverTime": 1656400526260
},
"rateLimits": [
{
"rateLimitType": "REQUEST_WEIGHT",
"interval": "MINUTE",
"intervalNum": 1,
"limit": 6000,
"count": 70
}
]
}

rate Limits 数组描述了受请求影响的所有当前的速率限制。

名称类型是否必须描述
rateLimitTypeENUMYES频率限制类型: REQUEST_WEIGHT, ORDERS
intervalENUMYES频率限制间隔: SECOND, MINUTE, HOUR, DAY
intervalNumINTYES频率限制间隔乘数
limitINTYES每个间隔的请求限制
countINTYES每个间隔的当前使用情况

频率限制按间隔计算。

例如,1 MINUTE 间隔表示每分钟开始。 在 00:01:23.456 提交的请求计入 00:01:00 分钟的限制。 一旦 00:02:00 分钟开始,计数将再次重置为零。

其他间隔的行为方式类似。 例如,1 DAY 频率限制是在每天 00:00 UTC 重置,并且 10 SECOND 间隔重置为每分钟的 00、10、20...秒。

API 有多种频率限制间隔。 如果您用完了较短的间隔但较长的间隔仍然允许请求,您将不得不等待较短的间隔到期并重置。 如果你用完了更长的间隔,你将不得不等待那个间隔重置,即使较短的频率限制计数为零。

如何显示/隐藏频率限制信息

默认情况下,每个响应都包含 rateLimits 字段。

但是,频率限制信息可能非常大。 如果您对每个请求的详细频率限制状态不感兴趣,可以从响应中省略 rateLimits 字段。

  • 请求中的可选 returnRateLimits boolean 参数。

    使用 returnRateLimits 参数控制是否包含 rateLimits 字段以响应单个请求。

    默认请求和响应:

    {"id":1,"method":"time"}
    {"id":1,"status":200,"result":{"serverTime":1656400526260},"rateLimits":[{"rateLimitType":"REQUEST_WEIGHT","interval":"MINUTE","intervalNum":1,"limit":6000,"count":70}]}

    没有频率限制状态的请求和响应:

    {"id":2,"method":"time","params":{"returnRateLimits":false}}
    {"id":2,"status":200,"result":{"serverTime":1656400527891}}
  • 连接 URL 中可选的 returnRateLimits boolean 参数。

    如果您希望在默认情况下从所有响应中省略 rateLimits,可以在 query string 中使用 returnRateLimits 参数:

    wss://ws-api.binance.com:443/ws-api/v3?returnRateLimits=false

    这将使通过此连接发出的所有请求的行为就像您已传了 "returnRateLimits":false 一样。

    如果您_想_查看特定请求的频率限制,您需要特定传 "returnRateLimits":true 参数。

注意: 如果您在响应中隐藏 rateLimits 字段,您的请求仍然还是会受到频率限制的。

IP 访问限制

  • 每个请求都有一个特定的 权重,它会添加到您的访问限制中。
    • 越消耗资源的接口, 比如查询多个交易对, 权重就会越大。
    • 连接到 WebSocket API 会用到2个权重。
  • 当前权重使用由 REQUEST_WEIGHT 频率限制类型指示。
  • 请使用exchangeInfo请求来跟踪当前的重量限制。
  • 权重是基于每个 IP 地址累积的,并由来自该地址的所有连接共享。
  • 如果超多限制,客服端会收到 429
    • 这错误代码表示您有责任停止发送请求,不得滥用API。
    • 响应会包含一个 retryAfter 字段,指示在什么时候您能重试。
  • 屡次违反速率限制或者在收到429后未能退缩将导致自动 IP 封禁和断开连接。
    • 被禁止 IP 地址的请求失败,状态为 418
    • retryAfter 字段表示解除禁令的timestamp。
  • 频繁违反限制的封禁时间会逐渐延长从最短2分钟到最长3天

表示在1分钟内使用了(1200权重限制中的)70权重的成功响应:

{
"id": "7069b743-f477-4ae3-81db-db9b8df085d2",
"status": 200,
"result": [],
"rateLimits": [
{
"rateLimitType": "REQUEST_WEIGHT",
"interval": "MINUTE",
"intervalNum": 1,
"limit": 6000,
"count": 70
}
]
}

表示已被封禁且封禁将在 epoch 1659146400000 解锁的失败响应:

{
"id": "fc93a61a-a192-4cf4-bb2a-a8f0f0c51e06",
"status": 418,
"error": {
"code": -1003,
"msg": "Way too much request weight used; IP banned until 1659146400000. Please use WebSocket Streams for live updates to avoid bans.",
"data": {
"serverTime": 1659142907531,
"retryAfter": 1659146400000
}
},
"rateLimits": [
{
"rateLimitType": "REQUEST_WEIGHT",
"interval": "MINUTE",
"intervalNum": 1,
"limit": 6000,
"count": 2411
}
]
}

未成交订单计数

  • 成功下单将更新 订单 速率限制类型。
  • 被拒绝或不成功的订单可能会也可能不会更新 订单 速率限制类型。
  • 请注意,如果您的订单一直顺利完成交易,您可以通过 API 持续下订单。更多信息,请参见 现货未成交订单计数规则
  • 使用 account.rateLimits.orders 请求来跟踪您在此时间间隔内下了多少订单。
  • 如果超过此值,请求将失败,状态为 429
    • 此状态代码表示您应退出并停止向 API 滥发信息。
    • 状态为 429 的响应会包含 retryAfter 字段,用以指示何时可以重试请求。
  • 这是按 每一个账户 维护的,并由该账户的所有 API 密钥共享。

表示在10秒内下了12个订单和在24小时内下了4043个订单的成功响应:

{
"id": "e2a85d9f-07a5-4f94-8d5f-789dc3deb097",
"status": 200,
"result": {
"symbol": "BTCUSDT",
"orderId": 12510053279,
"orderListId": -1,
"clientOrderId": "a097fe6304b20a7e4fc436",
"transactTime": 1655716096505,
"price": "0.10000000",
"origQty": "10.00000000",
"executedQty": "0.00000000",
"cummulativeQuoteQty": "0.00000000",
"status": "NEW",
"timeInForce": "GTC",
"type": "LIMIT",
"side": "BUY",
"workingTime": 1655716096505,
"selfTradePreventionMode": "NONE"
},
"rateLimits": [
{
"rateLimitType": "ORDERS",
"interval": "SECOND",
"intervalNum": 10,
"limit": 50,
"count": 12
},
{
"rateLimitType": "ORDERS",
"interval": "DAY",
"intervalNum": 1,
"limit": 160000,
"count": 4043
},
{
"rateLimitType": "REQUEST_WEIGHT",
"interval": "MINUTE",
"intervalNum": 1,
"limit": 6000,
"count": 321
}
]
}

请求鉴权类型

  • 每个函数都有自己的鉴权类型,鉴权类型决定了访问时应当进行何种鉴权。
    • 鉴权类型会在本文档中各个函数名称旁声明。比如 下新的订单 (TRADE)
    • 如果没有特殊声明即默认为 NONE
鉴权类型API key签名描述
NONE公开市场数据
TRADErequiredrequired在交易所交易,下单和取消订单
USER_DATArequiredrequired私人账户信息,例如订单状态和交易历史
USER_STREAMrequired管理用户数据流订阅
MARKET_DATArequired历史市场数据访问
  • 函数鉴权需要指定和验证有效的 API key。
    • API key 可以在币安账户的 API 管理 页面创建。
    • API key和密钥都是大小写敏感的。 切勿与任何人共享它们。 如果您发现您的账户有异常活动,请立即撤销所有keys并联系币安客服。
  • API key 可以配置为仅允许访问某些类型的函数鉴权。
    • 例如,可以拥有一个 API key 有 TRADE 的权限进行交易,同时使用另一个 API key 有 USER_DATA 的权限来监控您的订单状态。
    • 默认情况下,API key 不能 交易。您需要先在 API 管理中开通交易权限。
  • TRADEUSER_DATA 请求也称为 SIGNED 请求。

SIGNED (TRADE 和 USER_DATA) 请求鉴权

时间同步安全

  • SIGNED 请求也必须发 timestamp 参数,其值应当是请求发送时刻的 unix 时间戳(毫秒)。

  • 还可以发送一个可选参数 recvWindow,指定请求保持有效的时间。

    • 如果 recvWindow 未发送,默认为5000毫秒
    • 最大 recvWindow 为60000毫秒。
  • 请求处理逻辑:

    if (timestamp < (serverTime + 1000) && (serverTime - timestamp) <= recvWindow) {
    // 处理请求
    } else {
    // 拒绝请求
    }

关于交易时效性 互联网状况并不完全稳定可靠,因此你的程序本地到币安服务器的时延会有抖动, 这是我们设置 recvWindow 的目所在。如果你从事高频交易,对交易时效性有较高的要求,可以灵活设置 recvWindow 以达到你的要求。

建议使用5000毫秒以下的 recvWindow

SIGNED 请求示例 (HMAC)

这是有关如何用 HMAC secret key 签署请求的分步指南。

示例 API key 和 secret key:

KeyValue
apiKeyvmPUZE6mv9SD5VNHk4HlWFsOr6aKE2zvsw0MuIgwCIPy6utIco14y7Ju91duEh8A
secretKeyNhqPtmdSJYdKjVHjA7PZj4Mge3R5YNiP1e3UZjInClVN65XAbvqqM6A7H5fATj0j

警告:请勿与任何人共享您的私钥。

示例密钥仅供参考。

请求示例:

{
"id": "4885f793-e5ad-4c3b-8f6c-55d891472b71",
"method": "order.place",
"params": {
"symbol": "BTCUSDT",
"side": "SELL",
"type": "LIMIT",
"timeInForce": "GTC",
"quantity": "0.01000000",
"price": "52000.00",
"newOrderRespType": "ACK",
"recvWindow": 100,
"timestamp": 1645423376532,
"apiKey": "vmPUZE6mv9SD5VNHk4HlWFsOr6aKE2zvsw0MuIgwCIPy6utIco14y7Ju91duEh8A",
"signature": "------ 未填写 ------"
}
}

如您所见,目前缺少 signature 参数。

第一步:创建签名内容

除了 signature 之外,获取所有请求 params,然后按名称按字母顺序进行排序:

参数取值
apiKeyvmPUZE6mv9SD5VNHk4HlWFsOr6aKE2zvsw0MuIgwCIPy6utIco14y7Ju91duEh8A
newOrderRespTypeACK
price52000.00
quantity0.01000000
recvWindow100
sideSELL
symbolBTCUSDT
timeInForceGTC
timestamp1645423376532
typeLIMIT

将参数格式化为 参数=取值 对并用 & 分隔每个参数:

签名效载荷示例:

apiKey=vmPUZE6mv9SD5VNHk4HlWFsOr6aKE2zvsw0MuIgwCIPy6utIco14y7Ju91duEh8A&newOrderRespType=ACK&price=52000.00&quantity=0.01000000&recvWindow=100&side=SELL&symbol=BTCUSDT&timeInForce=GTC&timestamp=1645423376532&type=LIMIT

第二步:计算签名

  1. secretKey 解释为 ASCII 数据,将其用作 HMAC-SHA-256 的 key。
  2. 将签名有效负载签名为 ASCII 数据。
  3. 将 HMAC-SHA-256 输出编码为 hex string。

请注意,apiKeysecretKey 和有效负载是大小写敏感的。 生成的签名值是不区分大小写的。

可以使用 OpenSSL 交叉检查您的签名算法实现:

$ echo -n 'apiKey=vmPUZE6mv9SD5VNHk4HlWFsOr6aKE2zvsw0MuIgwCIPy6utIco14y7Ju91duEh8A&newOrderRespType=ACK&price=52000.00&quantity=0.01000000&recvWindow=100&side=SELL&symbol=BTCUSDT&timeInForce=GTC&timestamp=1645423376532&type=LIMIT' \
| openssl dgst -hex -sha256 -hmac 'NhqPtmdSJYdKjVHjA7PZj4Mge3R5YNiP1e3UZjInClVN65XAbvqqM6A7H5fATj0j'

cc15477742bd704c29492d96c7ead9414dfd8e0ec4a00f947bb5bb454ddbd08a

第三步:添加 signatureparams

最后,使用生成的签名完成请求:

{
"id": "4885f793-e5ad-4c3b-8f6c-55d891472b71",
"method": "order.place",
"params": {
"symbol": "BTCUSDT",
"side": "SELL",
"type": "LIMIT",
"timeInForce": "GTC",
"quantity": "0.01000000",
"price": "52000.00",
"newOrderRespType": "ACK",
"recvWindow": 100,
"timestamp": 1645423376532,
"apiKey": "vmPUZE6mv9SD5VNHk4HlWFsOr6aKE2zvsw0MuIgwCIPy6utIco14y7Ju91duEh8A",
"signature": "cc15477742bd704c29492d96c7ead9414dfd8e0ec4a00f947bb5bb454ddbd08a"
}
}

SIGNED 请求示例 (RSA)

KeyValue
apiKeyCAvIjXy3F44yW6Pou5k8Dy1swsYDWJZLeoK2r8G4cFDnE9nosRppc2eKc1T8TRTQ

对于这个例子,Private Key 将被引用为 test-prv-key.pem

警告:请勿与任何人共享您的私钥。 示例密钥仅供参考。

请求例子:

{
"id": "4885f793-e5ad-4c3b-8f6c-55d891472b71",
"method": "order.place",
"params": {
"symbol": "BTCUSDT",
"side": "SELL",
"type": "LIMIT",
"timeInForce": "GTC",
"quantity": "0.01000000",
"price": "52000.00",
"newOrderRespType": "ACK",
"recvWindow": 100,
"timestamp": 1645423376532,
"apiKey": "CAvIjXy3F44yW6Pou5k8Dy1swsYDWJZLeoK2r8G4cFDnE9nosRppc2eKc1T8TRTQ",
"signature": "------ FILL ME ------"
}
}

第一步:计算 Payload

除了 signature,获取请求的所有其它 params,然后按名称字母顺序对它们进行排序:

参数取值
apiKeyCAvIjXy3F44yW6Pou5k8Dy1swsYDWJZLeoK2r8G4cFDnE9nosRppc2eKc1T8TRTQ
newOrderRespTypeACK
price52000.00
quantity0.01000000
recvWindow100
sideSELL
symbolBTCUSDT
timeInForceGTC
timestamp1645423376532
typeLIMIT

将参数格式化为 参数=取值 对并用 & 分隔每个参数:

apiKey=CAvIjXy3F44yW6Pou5k8Dy1swsYDWJZLeoK2r8G4cFDnE9nosRppc2eKc1T8TRTQ&newOrderRespType=ACK&price=52000.00&quantity=0.01000000&recvWindow=100&side=SELL&symbol=BTCUSDT&timeInForce=GTC&timestamp=1645423376532&type=LIMIT

第二步:计算签名

  1. 将签名有效负载编码为 ASCII 数据。
  2. 使用带有 SHA-256 hash 函数的 RSASSA-PKCS1-v1_5 算法对 payload 进行签名。
  3. 将输出编码为 base64 string。

请注意,apiKey, payload 和生成的签名值都是大小写敏感的。

您可以使用 OpenSSL 交叉检查您的签名算法:

$ echo -n 'apiKey=CAvIjXy3F44yW6Pou5k8Dy1swsYDWJZLeoK2r8G4cFDnE9nosRppc2eKc1T8TRTQ&newOrderRespType=ACK&price=52000.00&quantity=0.01000000&recvWindow=100&side=SELL&symbol=BTCUSDT&timeInForce=GTC&timestamp=1645423376532&type=LIMIT' \
| openssl dgst -sha256 -sign test-prv-key.pem \
| openssl enc -base64 -A

OJJaf8C/3VGrU4ATTR4GiUDqL2FboSE1Qw7UnnoYNfXTXHubIl1iaePGuGyfct4NPu5oVEZCH4Q6ZStfB1w4ssgu0uiB/Bg+fBrRFfVgVaLKBdYHMvT+ljUJzqVaeoThG9oXlduiw8PbS9U8DYAbDvWN3jqZLo4Z2YJbyovyDAvDTr/oC0+vssLqP7NmlNb3fF3Bj7StmOwJvQJTbRAtzxK5PP7OQe+0mbW+D7RqVkUiSswR8qJFWTeSe4nXXNIdZdueYhF/Xf25L+KitJS5IHdIHcKfEw3MQzHFb2ZsGWkjDQwxkwr7Noi0Zaa+gFtxCuatGFm9dFIyx217pmSHtA==

第三步:在请求的 params 参数添加签名值

最后,使用生成的签名完成请求:

{
"id": "4885f793-e5ad-4c3b-8f6c-55d891472b71",
"method": "order.place",
"params": {
"symbol": "BTCUSDT",
"side": "SELL",
"type": "LIMIT",
"timeInForce": "GTC",
"quantity": "0.01000000",
"price": "52000.00",
"newOrderRespType": "ACK",
"recvWindow": 100,
"timestamp": 1645423376532,
"apiKey": "CAvIjXy3F44yW6Pou5k8Dy1swsYDWJZLeoK2r8G4cFDnE9nosRppc2eKc1T8TRTQ",
"signature": "OJJaf8C/3VGrU4ATTR4GiUDqL2FboSE1Qw7UnnoYNfXTXHubIl1iaePGuGyfct4NPu5oVEZCH4Q6ZStfB1w4ssgu0uiB/Bg+fBrRFfVgVaLKBdYHMvT+ljUJzqVaeoThG9oXlduiw8PbS9U8DYAbDvWN3jqZLo4Z2YJbyovyDAvDTr/oC0+vssLqP7NmlNb3fF3Bj7StmOwJvQJTbRAtzxK5PP7OQe+0mbW+D7RqVkUiSswR8qJFWTeSe4nXXNIdZdueYhF/Xf25L+KitJS5IHdIHcKfEw3MQzHFb2ZsGWkjDQwxkwr7Noi0Zaa+gFtxCuatGFm9dFIyx217pmSHtA=="
}
}

SIGNED 请求示例 (Ed25519)

我们建议使用 Ed25519 API keys,因为它在所有受支持的 API key 类型中提供最佳性能和安全性。

参数取值
symbolBTCUSDT
sideSELL
typeLIMIT
timeInForceGTC
quantity1
price0.2
timestamp1668481559918

下面的 Python 示例代码能说明如何使用 Ed25519 key 对 payload 进行签名。

#!/usr/bin/env python3
import base64
import time
import json
from cryptography.hazmat.primitives.serialization import load_pem_private_key
from websocket import create_connection

# 设置身份验证:
API_KEY='替换成您的 API Key'
PRIVATE_KEY_PATH='test-prv-key.pem'
# 加载 private key。
# 在这个例子中,private key 没有加密,但我们建议使用强密码以提高安全性。
with open(PRIVATE_KEY_PATH, 'rb') as f:
private_key = load_pem_private_key(data=f.read(), password=None)
# 设置请求参数:
params = {
'apiKey': API_KEY,
'symbol': 'BTCUSDT',
'side': 'SELL',
'type': 'LIMIT',
'timeInForce': 'GTC',
'quantity': '1.0000000',
'price': '0.20'
}
# 参数中加时间戳:
timestamp = int(time.time() * 1000) # 以毫秒为单位的 UNIX 时间戳
params['timestamp'] = timestamp
# 参数中加签名:
payload = '&'.join([f'{param}={value}' for param, value in sorted(params.items())])
signature = base64.b64encode(private_key.sign(payload.encode('ASCII')))
params['signature'] = signature.decode('ASCII')
# 发送请求:
request = {
'id': 'my_new_order',
'method': 'order.place',
'params': params
}
ws = create_connection('wss://ws-api.binance.com:443/ws-api/v3')
ws.send(json.dumps(request))
result = ws.recv()
ws.close()
print(result)

会话身份验证

注意: 仅支持 Ed25519 密钥用于此功能。

如果你不想在每个单独的请求中指定apiKeysignature,你可以为有效的WebSocket会话进行API密钥身份验证。

一旦完成身份验证,你将不需在需要它们的请求中指定apiKeysignature。 这些请求将代表拥有已验证API密钥的帐户执行。

注意: 对于SIGNED请求,你仍需要指定timestamp参数。

连接后进行身份验证

你可以使用会话身份验证请求对已经建立的连接进行身份验证:

关于吊销API密钥:

如果在活动会话期间,由于 任何 原因(例如IP地址未被加入白名单、API密钥被删除、API密钥没有正确的权限等),在下一个请求后,会话将被吊销,并显示以下错误消息:

{
"id": null,
"status": 401,
"error": {
"code": -2015,
"msg": "Invalid API-key, IP, or permissions for action."
}
}

授权 临时 请求

WebSocket连接只能通过一个API密钥进行身份验证。 默认情况下,经过身份验证的API密钥将用于需要apiKey参数的请求。 但是,你始终可以为单个请求明确指定apiKeysignature,覆盖已认证的API密钥,以使用不同的API密钥授权特定请求。

例如,你可能希望用默认密钥来验证 USER_DATA,但在下单时使用TRADE密钥来签名。

数据源

  • API 系统是异步的。响应中一些延迟是正常和预期的。

  • 每种函数都会有一个数据源, 用来指示数据的来源,以及它的最新程度。

数据源延迟描述
撮合引擎最低表示撮合引擎直接产生响应
缓存表示数据来源于内部或者外部的缓存
数据库中度表示数据直接来源于数据库
  • 某些函数有多个数据源(例如,缓存 => 数据库)。

    这代表 API 将按该顺序查找最新数据:首先是缓存,然后是数据库。