跳到主要内容

REST行情与交易接口 (2024-10-17)

API 基本信息

HTTP 返回代码

  • HTTP 4XX 错误码用于指示错误的请求内容、行为、格式。问题在于请求者。
  • HTTP 403 错误码表示违反WAF限制(Web应用程序防火墙)。
  • HTTP 409 错误码表示重新下单(cancelReplace)的请求部分成功。(比如取消订单失败,但是下单成功了)
  • HTTP 429 错误码表示警告访问频次超限,即将被封IP。
  • HTTP 418 表示收到429后继续访问,于是被封了。
  • HTTP 5XX 错误码用于指示Binance服务侧的问题。

接口错误代码

  • 每个接口都有可能抛出异常,异常响应格式如下:
{
"code": -1121,
"msg": "Invalid symbol."
}

接口的基本信息

  • GET 方法的接口, 参数必须在 query string中发送。
  • POST, PUT, 和 DELETE 方法的接口,参数可以在内容形式为application/x-www-form-urlencodedquery string 中发送,也可以在 request body 中发送。 如果你喜欢,也可以混合这两种方式发送参数。
  • 对参数的顺序不做要求。
  • 但如果同一个参数名在query stringrequest body中都有,query string中的会被优先采用。

访问限制

访问限制基本信息

  • 以下是 intervalLetter 作为头部值:
    • SECOND => S
    • MINUTE => M
    • HOUR => H
    • DAY => D
  • /api/v3/exchangeInfo接口中rateLimits数组里包含有REST接口(不限于本篇的REST接口)的访问限制。包括带权重的访问频次限制、下单速率限制。参考 枚举定义 中有关有限制类型的进一步说明。
  • 当您超出请求速率限制时,请求会失败并返回 HTTP 状态代码 429。

IP 访问限制

  • 每个请求将包含一个X-MBX-USED-WEIGHT-(intervalNum)(intervalLetter)的头,其中包含当前IP所有请求的已使用权重。
  • 每一个接口均有一个相应的权重(weight),有的接口根据参数不同可能拥有不同的权重。越消耗资源的接口权重就会越大。
  • 收到429时,您有责任停止发送请求,不得滥用API。
  • 收到429后仍然继续违反访问限制,会被封禁IP,并收到418错误码
  • 频繁违反限制,封禁时间会逐渐延长,从最短2分钟到最长3天.
  • Retry-After的头会与带有418或429的响应发送,并且会给出以秒为单位的等待时长(如果是429)以防止禁令,或者如果是418,直到禁令结束。
  • 访问限制是基于IP的,而不是API Key

未成交订单计数

  • 每个成功的订单响应都将包含一个 X-MBX-ORDER-COUNT-(intervalNum)(intervalLetter) 报文头,用于标识您在该时间间隔内下了多少订单。

    如果您想要对此进行监控,请参阅 GET api/v3/rateLimit/order
  • 被拒绝/不成功的订单不保证在响应中有 X-MBX-ORDER-COUNT-** 报文头。
  • 如果超过此值,您将收到一个 429 错误,而且不带 Retry-After 报文头。
  • 请注意,如果您的订单一直顺利完成交易,您可以通过 API 持续下订单。更多信息,请参见现货未成交订单计数规则
  • 未成交订单数量是按照每个账户来统计的

数据来源

  • 因为API系统是异步的, 所以返回的数据有延时很正常, 也在预期之中。
  • 在每个接口中,都列出了其数据的来源,可以用于理解数据的时效性。

系统一共有3个数据来源,按照更新速度的先后排序。排在前面的数据最新,在后面就有可能存在延迟。

  • 撮合引擎 - 表示数据来源于撮合引擎
  • 缓存 - 表示数据来源于内部或者外部的缓存
  • 数据库 - 表示数据直接来源于数据库

有些接口有不止一个数据源, 比如 缓存 => 数据库, 这表示接口会先从第一个数据源检查,如果没有数据,则检查下一个数据源。

接口鉴权类型

  • 每个接口都有自己的鉴权类型,鉴权类型决定了访问时应当进行何种鉴权。
  • 鉴权类型会在本文档中各个接口名称旁声明,如果没有特殊声明即默认为 NONE
  • 如果需要 API-keys,应当在HTTP头中以 X-MBX-APIKEY字段传递。
  • API-keys 与 secret-keys 是大小写敏感的
  • API-keys可以被配置为只拥有访问一些接口的权限。
    例如, 一个 API-key 仅可用于发送交易指令, 而另一个 API-key 则可访问除交易指令外的所有路径。
  • 默认 API-keys 可访问所有鉴权路径.
鉴权类型描述
NONE不需要鉴权的接口
TRADE需要有效的API-KEY和签名
USER_DATA需要有效的API-KEY和签名
USER_STREAM需要有效的API-KEY
MARKET_DATA需要有效的API-KEY
  • TRADEUSER_DATA 接口是 签名(SIGNED)接口.

需要签名的接口 (TRADE 与 USER_DATA)

  • 调用SIGNED 接口时,除了接口本身所需的参数外,还需要在query stringrequest body中传递 signature, 即签名参数。
  • 签名 大小写不敏感.
  • 请参考下面 签名示例 以了解具体如何做计算签名。

时间同步安全

  • 签名接口均需要传递 timestamp参数,其值应当是请求发送时刻的unix时间戳(毫秒)。

  • 服务器收到请求时会判断请求中的时间戳,如果是5000毫秒之前发出的,则请求会被认为无效。这个时间空窗值可以通过发送可选参数 recvWindow来定义。

  • 逻辑伪代码:

    if (timestamp < (serverTime + 1000) && (serverTime - timestamp) <= recvWindow) {
    // process request
    } else {
    // reject request
    }

关于交易时效性 互联网状况并不100%可靠,不可完全依赖,因此你的程序本地到币安服务器的时延会有抖动. 这是我们设置recvWindow的目的所在,如果你从事高频交易,对交易时效性有较高的要求,可以灵活设置recvWindow以达到你的要求。 不推荐使用5秒以上的recvWindow。最大值不能超过60秒!

POST /api/v3/order 的示例

HMAC Keys

以下是在linux bash环境下使用 echo,opensslcurl工具实现的一个调用接口下单的示例 apikey、secret仅供示范

KeyValue
apiKeyvmPUZE6mv9SD5VNHk4HlWFsOr6aKE2zvsw0MuIgwCIPy6utIco14y7Ju91duEh8A
secretKeyNhqPtmdSJYdKjVHjA7PZj4Mge3R5YNiP1e3UZjInClVN65XAbvqqM6A7H5fATj0j
参数取值
symbolLTCBTC
sideBUY
typeLIMIT
timeInForceGTC
quantity1
price0.1
recvWindow5000
timestamp1499827319559

示例 1: 所有参数通过 query string 发送

  • queryString: symbol=LTCBTC&side=BUY&type=LIMIT&timeInForce=GTC&quantity=1&price=0.1&recvWindow=5000&timestamp=1499827319559

  • HMAC SHA256 签名:

    [linux]$ echo -n "symbol=LTCBTC&side=BUY&type=LIMIT&timeInForce=GTC&quantity=1&price=0.1&recvWindow=5000&timestamp=1499827319559" | openssl dgst -sha256 -hmac "NhqPtmdSJYdKjVHjA7PZj4Mge3R5YNiP1e3UZjInClVN65XAbvqqM6A7H5fATj0j"
    (stdin)= c8db56825ae71d6d79447849e617115f4a920fa2acdcab2b053c4b2838bd6b71
  • curl 调用:

    (HMAC SHA256)
    [linux]$ curl -H "X-MBX-APIKEY: vmPUZE6mv9SD5VNHk4HlWFsOr6aKE2zvsw0MuIgwCIPy6utIco14y7Ju91duEh8A" -X POST 'https://api.binance.com/api/v3/order?symbol=LTCBTC&side=BUY&type=LIMIT&timeInForce=GTC&quantity=1&price=0.1&recvWindow=5000&timestamp=1499827319559&signature=c8db56825ae71d6d79447849e617115f4a920fa2acdcab2b053c4b2838bd6b71'

示例 2: 所有参数通过 request body 发送

  • requestBody: symbol=LTCBTC&side=BUY&type=LIMIT&timeInForce=GTC&quantity=1&price=0.1&recvWindow=5000&timestamp=1499827319559

  • HMAC SHA256 签名:

    [linux]$ echo -n "symbol=LTCBTC&side=BUY&type=LIMIT&timeInForce=GTC&quantity=1&price=0.1&recvWindow=5000&timestamp=1499827319559" | openssl dgst -sha256 -hmac "NhqPtmdSJYdKjVHjA7PZj4Mge3R5YNiP1e3UZjInClVN65XAbvqqM6A7H5fATj0j"
    (stdin)= c8db56825ae71d6d79447849e617115f4a920fa2acdcab2b053c4b2838bd6b71
  • curl 调用:

    (HMAC SHA256)
    [linux]$ curl -H "X-MBX-APIKEY: vmPUZE6mv9SD5VNHk4HlWFsOr6aKE2zvsw0MuIgwCIPy6utIco14y7Ju91duEh8A" -X POST 'https://api.binance.com/api/v3/order' -d 'symbol=LTCBTC&side=BUY&type=LIMIT&timeInForce=GTC&quantity=1&price=0.1&recvWindow=5000&timestamp=1499827319559&signature=c8db56825ae71d6d79447849e617115f4a920fa2acdcab2b053c4b2838bd6b71'

示例 3: 混合使用 query string 与 request body

  • queryString: symbol=LTCBTC&side=BUY&type=LIMIT&timeInForce=GTC

  • requestBody: quantity=1&price=0.1&recvWindow=5000&timestamp=1499827319559

  • HMAC SHA256 签名:

    [linux]$ echo -n "symbol=LTCBTC&side=BUY&type=LIMIT&timeInForce=GTCquantity=1&price=0.1&recvWindow=5000&timestamp=1499827319559" | openssl dgst -sha256 -hmac "NhqPtmdSJYdKjVHjA7PZj4Mge3R5YNiP1e3UZjInClVN65XAbvqqM6A7H5fATj0j"
    (stdin)= 0fd168b8ddb4876a0358a8d14d0c9f3da0e9b20c5d52b2a00fcf7d1c602f9a77
  • curl 调用:

    (HMAC SHA256)
    [linux]$ curl -H "X-MBX-APIKEY: vmPUZE6mv9SD5VNHk4HlWFsOr6aKE2zvsw0MuIgwCIPy6utIco14y7Ju91duEh8A" -X POST 'https://api.binance.com/api/v3/order?symbol=LTCBTC&side=BUY&type=LIMIT&timeInForce=GTC' -d 'quantity=1&price=0.1&recvWindow=5000&timestamp=1499827319559&signature=0fd168b8ddb4876a0358a8d14d0c9f3da0e9b20c5d52b2a00fcf7d1c602f9a77'

Note that the signature is different in example 3. There is no & between "GTC" and "quantity=1".

RSA Keys

  • 这将逐步介绍如何通过有效的签名发送 payload。
  • 我们接受PKCS#8格式的RSA密钥。
  • 要获取 API Key,您需要在您的账户上上传您的 RSA Public Key。
  • 对于这个例子,Private Key 将被引用为 test-prv-key.pem
KeyValue
apiKeyCAvIjXy3F44yW6Pou5k8Dy1swsYDWJZLeoK2r8G4cFDnE9nosRppc2eKc1T8TRTQ
参数取值
symbolBTCUSDT
sideSELL
typeLIMIT
timeInForceGTC
quantity1
price0.2
timestamp1668481559918
recvWindow5000

第一步: Payload

将参数列表排列成一个 string。 用 & 分隔每个参数。对于上述参数,签名 payload 如下所示:

symbol=BTCUSDT&side=SELL&type=LIMIT&timeInForce=GTC&quantity=1&price=0.2&timestamp=1668481559918&recvWindow=5000

第二步: 计算签名

  1. 将签名有效负载编码为 ASCII 数据。
  2. 使用带有 SHA-256 hash 函数的 RSASSA-PKCS1-v1_5 算法对 payload 进行签名。
$ echo -n 'symbol=BTCUSDT&side=SELL&type=LIMIT&timeInForce=GTC&quantity=1&price=0.2&timestamp=1668481559918&recvWindow=5000' | openssl dgst -sha256 -sign ./test-prv-key.pem
  1. 将输出编码为 base64 string。
$ echo -n 'symbol=BTCUSDT&side=SELL&type=LIMIT&timeInForce=GTC&quantity=1&price=0.2&timestamp=1668481559918&recvWindow=5000' | openssl dgst -sha256 -sign ./test-prv-key.pem | openssl enc -base64 -A
HZ8HOjiJ1s/igS9JA+n7+7Ti/ihtkRF5BIWcPIEluJP6tlbFM/Bf44LfZka/iemtahZAZzcO9TnI5uaXh3++lrqtNonCwp6/245UFWkiW1elpgtVAmJPbogcAv6rSlokztAfWk296ZJXzRDYAtzGH0gq7CgSJKfH+XxaCmR0WcvlKjNQnp12/eKXJYO4tDap8UCBLuyxDnR7oJKLHQHJLP0r0EAVOOSIbrFang/1WOq+Jaq4Efc4XpnTgnwlBbWTmhWDR1pvS9iVEzcSYLHT/fNnMRxFc7u+j3qI//5yuGuu14KR0MuQKKCSpViieD+fIti46sxPTsjSemoUKp0oXA==
  1. 由于签名可能包含 /=,这可能会导致发送请求时出现问题。 所以签名必须是 URL 编码的。
HZ8HOjiJ1s%2FigS9JA%2Bn7%2B7Ti%2FihtkRF5BIWcPIEluJP6tlbFM%2FBf44LfZka%2FiemtahZAZzcO9TnI5uaXh3%2B%2BlrqtNonCwp6%2F245UFWkiW1elpgtVAmJPbogcAv6rSlokztAfWk296ZJXzRDYAtzGH0gq7CgSJKfH%2BXxaCmR0WcvlKjNQnp12%2FeKXJYO4tDap8UCBLuyxDnR7oJKLHQHJLP0r0EAVOOSIbrFang%2F1WOq%2BJaq4Efc4XpnTgnwlBbWTmhWDR1pvS9iVEzcSYLHT%2FfNnMRxFc7u%2Bj3qI%2F%2F5yuGuu14KR0MuQKKCSpViieD%2BfIti46sxPTsjSemoUKp0oXA%3D%3D
  1. curl 命令:
curl -H "X-MBX-APIKEY: CAvIjXy3F44yW6Pou5k8Dy1swsYDWJZLeoK2r8G4cFDnE9nosRppc2eKc1T8TRTQ" -X POST 'https://api.binance.com/api/v3/order?symbol=BTCUSDT&side=SELL&type=LIMIT&timeInForce=GTC&quantity=1&price=0.2&timestamp=1668481559918&recvWindow=5000&signature=HZ8HOjiJ1s%2FigS9JA%2Bn7%2B7Ti%2FihtkRF5BIWcPIEluJP6tlbFM%2FBf44LfZka%2FiemtahZAZzcO9TnI5uaXh3%2B%2BlrqtNonCwp6%2F245UFWkiW1elpgtVAmJPbogcAv6rSlokztAfWk296ZJXzRDYAtzGH0gq7CgSJKfH%2BXxaCmR0WcvlKjNQnp12%2FeKXJYO4tDap8UCBLuyxDnR7oJKLHQHJLP0r0EAVOOSIbrFang%2F1WOq%2BJaq4Efc4XpnTgnwlBbWTmhWDR1pvS9iVEzcSYLHT%2FfNnMRxFc7u%2Bj3qI%2F%2F5yuGuu14KR0MuQKKCSpViieD%2BfIti46sxPTsjSemoUKp0oXA%3D%3D'

下面的示例 Bash 脚本执行上述类似的步骤:

#!/usr/bin/env bash
# 设置身份验证:
API_KEY="替换成您的 API Key"
PRIVATE_KEY_PATH="test-prv-key.pem"
# 设置您的请求:
API_METHOD="POST"
API_CALL="api/v3/order"
API_PARAMS="symbol=BTCUSDT&side=SELL&type=LIMIT&timeInForce=GTC&quantity=1&price=0.2"
# 计算签名:
timestamp=$(date +%s000)
api_params_with_timestamp="$API_PARAMS&timestamp=$timestamp"
signature=$(echo -n "$api_params_with_timestamp" \
| openssl dgst -sha256 -sign "$PRIVATE_KEY_PATH" \
| openssl enc -base64 -A)
# 发送请求:
curl -H "X-MBX-APIKEY: $API_KEY" -X "$API_METHOD" \
"https://api.binance.com/$API_CALL?$api_params_with_timestamp" \
--data-urlencode "signature=$signature"

Ed25519 Keys

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

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

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

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

# 设置身份验证:
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 = {
'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 params.items()])
signature = base64.b64encode(private_key.sign(payload.encode('ASCII')))
params['signature'] = signature
# 发送请求:
headers = {
'X-MBX-APIKEY': API_KEY,
}
response = requests.post(
'https://api.binance.com/api/v3/order',
headers=headers,
data=params,
)
print(response.json())