REST API基础:HTTP请求方法、请求头与参数、状态码解读、限频机制
各位同学好,我是你们的讲师。今天咱们来聊聊REST API的基础。说实话,这部分内容看似简单,但我在对接几十家交易所的过程中,发现很多坑都埋在这些基础细节里。你想想看,如果连GET和POST都搞混了,那后面的策略跑起来可就要出大问题了。
一、HTTP请求方法:GET、POST、DELETE
交易所的REST API,说白了就是通过HTTP协议跟服务器打交道。常用的方法就三个:GET、POST、DELETE。我个人习惯把它们比作“查、改、删”。
1. GET请求:查数据
GET用于获取资源,比如查询行情、账户余额。它不会修改服务器上的任何数据。我在项目中遇到过,有人用GET请求去下单,结果服务器直接返回405错误——方法不被允许。
# 查询BTC/USDT的最新行情
GET https://api.exchange.com/v1/ticker?symbol=BTCUSDT
# 查询账户余额
GET https://api.exchange.com/v1/account/balance
注意:GET请求的参数都放在URL里,所以有长度限制。一般不超过2048个字符。如果你要传大量数据,那就得用POST了。
2. POST请求:改数据
POST用于创建或修改资源。下单、撤单、修改订单都用它。POST请求的参数通常放在请求体(body)里,而不是URL中。
# 提交一个限价买单
POST https://api.exchange.com/v1/order
Content-Type: application/json
{
"symbol": "BTCUSDT",
"side": "buy",
"type": "limit",
"price": "50000.00",
"quantity": "0.01"
}
嗯,这里要注意:POST请求的body格式,交易所一般支持JSON和表单两种。我个人建议统一用JSON,因为可读性好,而且嵌套结构也方便。
3. DELETE请求:删数据
DELETE用于删除资源。在交易所场景里,最常用的就是撤销订单。
# 撤销指定订单
DELETE https://api.exchange.com/v1/order/123456789
我曾经犯过一个低级错误:用GET请求去撤单,结果查了半天才发现方法用错了。所以大家一定要记住:GET查、POST改、DELETE删,这个口诀很管用。
二、请求头与参数
请求头(Headers)和参数(Parameters)是API调用的“身份证”和“说明书”。少了它们,服务器根本不知道你是谁、想干什么。
1. 常见的请求头
| 请求头 | 说明 | 示例 |
|---|---|---|
| Content-Type | 请求体的格式 | application/json |
| X-MBX-APIKEY | API密钥(币安风格) | abc123def456 |
| Authorization | 认证信息(Bearer Token) | Bearer eyJhbGciOiJIUzI1NiJ9... |
| User-Agent | 客户端标识 | MyTradingBot/1.0 |
我个人习惯在请求头里加上User-Agent,这样服务器出问题时,对方能快速定位到我的请求。避坑指南:千万不要把API密钥放在URL里,我曾经见过有人把密钥写在GET请求的参数中,结果日志一打印,密钥全暴露了。
2. 参数传递方式
参数分三种:路径参数、查询参数、请求体参数。
- 路径参数:直接写在URL路径里,比如
/order/123456中的123456就是订单ID。 - 查询参数:跟在URL问号后面,比如
?symbol=BTCUSDT&limit=10。 - 请求体参数:放在POST请求的body里,JSON格式最常用。
# 路径参数示例
GET https://api.exchange.com/v1/order/123456
# 查询参数示例
GET https://api.exchange.com/v1/kline?symbol=BTCUSDT&interval=1h&limit=100
# 请求体参数示例
POST https://api.exchange.com/v1/order
{
"symbol": "BTCUSDT",
"side": "sell",
"type": "market",
"quantity": "0.1"
}
三、状态码解读
状态码是服务器给你的“回执”。读懂它,你就能快速定位问题。我刚开始做量化时,看到4xx就慌,后来发现其实每个状态码都有明确的含义。
1. 常见的状态码
| 状态码 | 含义 | 常见场景 |
|---|---|---|
| 200 | 请求成功 | 查询行情、下单成功 |
| 201 | 创建成功 | 订单提交成功(部分交易所用) |
| 400 | 请求参数错误 | 缺少必填参数、参数格式不对 |
| 401 | 未授权 | API密钥无效或过期 |
| 403 | 禁止访问 | IP白名单限制、账户被冻结 |
| 404 | 资源不存在 | 查询不存在的订单ID |
| 429 | 请求过于频繁 | 触发了限频机制 |
| 5xx | 服务器错误 | 交易所内部故障 |
重点:状态码429是限频的标志。遇到它,你需要暂停请求,等待一段时间再重试。我见过有人不处理429,结果被交易所封了IP。
2. 如何处理状态码
写代码时,一定要对状态码做分类处理。我的做法是:
def handle_response(response):
if response.status_code == 200:
return response.json()
elif response.status_code == 429:
# 等待后重试
time.sleep(5)
return retry_request()
elif response.status_code in [400, 401, 403]:
# 记录日志,停止重试
log.error(f"请求失败: {response.status_code} - {response.text}")
raise APIError(response.status_code, response.text)
else:
# 5xx错误,可以重试
time.sleep(1)
return retry_request()
四、限频机制
限频(Rate Limit)是交易所保护自己的手段。说白了,就是防止你一个人把服务器打爆。每家交易所的限频规则都不一样,但核心逻辑是相通的。
1. 常见的限频方式
- 基于IP的限频:每个IP地址每分钟最多N次请求。
- 基于API Key的限频:每个API密钥每分钟最多M次请求。
- 基于端口的限频:不同接口有不同的限制,比如行情接口宽松,下单接口严格。
我记得有一次对接某交易所,它的限频规则特别复杂:每秒钟最多10次请求,每分钟最多600次,而且下单接口的权重是普通接口的5倍。如果不仔细看文档,很容易被限。
2. 如何应对限频
我的经验是:永远假设自己会被限频。在代码里做好重试和退避机制。
import time
import requests
class RateLimiter:
def __init__(self, max_calls=10, period=1.0):
self.max_calls = max_calls
self.period = period
self.calls = []
def wait_if_needed(self):
now = time.time()
# 移除过期的记录
self.calls = [t for t in self.calls if now - t < self.period]
if len(self.calls) >= self.max_calls:
sleep_time = self.calls[0] + self.period - now
if sleep_time > 0:
time.sleep(sleep_time)
self.calls.append(time.time())
# 使用示例
limiter = RateLimiter(max_calls=5, period=1.0)
for i in range(10):
limiter.wait_if_needed()
response = requests.get("https://api.exchange.com/v1/ticker?symbol=BTCUSDT")
print(f"请求 {i+1}: {response.status_code}")
小技巧:很多交易所会在响应头里返回限频信息,比如 X-MBX-USED-WEIGHT(已用权重)和 X-MBX-ORDER-COUNT(订单计数)。你可以读取这些值,动态调整请求频率。
五、知识体系总览
下面这张图,是我自己整理的REST API基础知识结构。你可以把它当作一个“地图”,随时回来查阅。
这张图把四个核心知识点串在了一起。你想想看,每次调用API,其实就是在跟这四个部分打交道:选对方法、带好参数、看懂状态码、控制频率。缺一个,你的程序就可能出问题。
避坑指南:我曾经在对接某交易所时,没有仔细看限频文档,结果用单线程每秒发了100次请求。不到10秒,IP就被封了24小时。后来我学乖了,每次对接新交易所,第一件事就是读限频文档,然后在代码里加上限频器。
好了,这一章的内容就到这里。记住:基础不牢,地动山摇。REST API的这些基础,是你后续学习WebSocket、FIX协议、以及多交易所适配的基石。多动手写代码,多踩坑,你才能真正掌握它们。