银行汇率查询历史汇率:按月取还是按区间取
约 14 分钟 进阶银行汇率查询历史汇率牌价走势对账
# 银行汇率查询历史汇率:按月取还是按区间取
接口:银行汇率查询(apiCode=105)· 接入点:查询历史汇率(105-34)· 免费(L0 基础版 100 次/天、1 QPS)· 请求方式:POST / GET · 返回格式:JSON · 适用人群:需要做对账、走势分析的开发者 · 阅读时间:约 6 分钟 · 最后实测核对:2026-09-18
## 核心要点
- `month`(`yyyyMM`)与 `startDate` + `endDate`(`yyyyMMdd`)二选一,文档标注两者互斥。
- 货币参数 `code` 与 `name` 至少要传一个;一个都不传时业务级返回 `ret_code` 为 -1。
- 文档标注区间最大 90 天。实测超过 90 天并不报错,`list` 最多返回 90 条,因此判断实际取数区间要以 `list` 首尾的 `publish_time` 为准。
## 某天的牌价去哪查
对账、报销、季度分析这些工作经常要回溯「上个月某天美元是多少」。汇率查询接入点(105-30)只给当下,历史接入点补上时间维度:给它一个月份,或者给一段起止日期,它返回逐日牌价。
选哪种参数取决于你要的数据形状。查一个完整自然月就用 `month`,一次拿到整月;查跨月的连续区间、或者只想要其中几天,就用 `startDate` + `endDate`。
## 接口速览
| 项目 | 说明 |
|------|------|
| 接口地址 | `https://route.showapi.com/105-34?appKey={your_appKey}` |
| 货币参数 | `code`(货币编号)或 `name`(货币名称),至少传一个 |
| 时间参数 | `month`(`yyyyMM`),或 `startDate` + `endDate`(`yyyyMMdd`),二选一 |
| 区间上限 | 文档标注最大可查询区间为 90 天 |
| 数据范围 | 文档说明可查询自 2009 年 1 月起的记录,涵盖 20 多种常见货币 |
| 数据口径 | 100 外币兑人民币 |
| 返回字段 | `currency_code`、`currency_name`、`startDate`、`endDate`、`month`、`remark`、`list[]`、`ret_code` |
| 超时设置 | OpenAPI 文档标注 `x-read-timeout` 15 秒、`x-connect-timeout` 15 秒 |
## 按月查询的调用代码
下面三段代码查 2026 年 8 月的美元牌价。把 `YOUR_APPKEY` 换成自己的值即可运行。
Python(requests):
```python
import requests
url = "https://route.showapi.com/105-34"
params = {"appKey": "YOUR_APPKEY"}
data = {"code": "USD", "month": "202608"}
try:
js = requests.post(url, params=params, data=data, timeout=15).json()
if js.get("showapi_res_code") == 0 and js["showapi_res_body"].get("ret_code") == 0:
body = js["showapi_res_body"]
print(body["currency_name"], body["startDate"], "~", body["endDate"])
for row in body["list"]:
print(row["publish_time"], "中行折算价", row["middle_rate"])
else:
print("调用失败:", js["showapi_res_body"].get("remark"))
except requests.RequestException as exc:
print("请求异常:", exc)
```
cURL:
```bash
curl -X POST "https://route.showapi.com/105-34?appKey=YOUR_APPKEY" \
-H "content-type: application/x-www-form-urlencoded" \
-d "code=USD&month=202608"
```
Node.js(fetch):
```javascript
const url = "https://route.showapi.com/105-34?appKey=YOUR_APPKEY";
const body = new URLSearchParams({ code: "USD", month: "202608" });
const res = await fetch(url, {
method: "POST",
body,
headers: { "content-type": "application/x-www-form-urlencoded" },
signal: AbortSignal.timeout(15000)
});
const js = await res.json();
if (js.showapi_res_code === 0 && js.showapi_res_body.ret_code === 0) {
for (const row of js.showapi_res_body.list) {
console.log(row.publish_time, "中行折算价", row.middle_rate);
}
} else {
console.error("调用失败:", js.showapi_res_body.remark);
}
```
按区间查询只要把 `data` 换成 `{"code": "USD", "startDate": "20260601", "endDate": "20260830"}`,其余不变。
## 返回示例与解析
2026-09-18 实测 `code=USD&month=202608` 的真实返回(`list` 保留首尾两条):
```json
{
"showapi_res_code": 0,
"showapi_res_error": "",
"showapi_res_body": {
"currency_code": "USD",
"currency_name": "美元",
"startDate": "20260801",
"endDate": "20260901",
"month": "202608",
"remark": "查询成功!",
"ret_code": 0,
"list": [
{
"publish_time": "2026-08-31",
"middle_rate": "678.28",
"buying_rate": "670.78",
"selling_rate": "673.61",
"cash_buying_rate": "670.78",
"cash_selling_rate": "673.61"
},
{
"publish_time": "2026-08-01",
"middle_rate": "678.05",
"buying_rate": "670.55",
"selling_rate": "673.38",
"cash_buying_rate": "670.55",
"cash_selling_rate": "673.38"
}
]
}
}
```
| 字段 | 含义 |
|------|------|
| `currency_code` / `currency_name` | 货币编号 / 货币名称 |
| `startDate` / `endDate` | 本次实际查询的起止日期 |
| `month` | 按月查询时回显的查询年月 |
| `remark` | 提示信息,成功时为「查询成功!」 |
| `list[].publish_time` | 发布日期 |
| `list[].middle_rate` | 中行折算价 |
| `list[].buying_rate` | 现汇买入价 |
| `list[].selling_rate` | 现汇卖出价 |
| `list[].cash_buying_rate` | 现钞买入价 |
| `list[].cash_selling_rate` | 现钞卖出价 |
## 按月与按区间在实测中的三个行为
**`list` 按 `publish_time` 倒序排列。** 实测 `month=202608` 返回 31 条,第一条是 `2026-08-31`,最后一条是 `2026-08-01`。画走势线之前先按日期正序排一遍。
**按月查询时 `endDate` 回显为下月 1 日。** 实测 `month=202608` 的返回里,`startDate` 是 `20260801`,`endDate` 是 `20260901`。这个 `endDate` 是查询上界而不是最后一条数据的日期,判断数据范围要看 `list` 的首尾。
**区间超过 90 天时接口正常返回,记录数封顶在 90 条。** 实测两组:
| 请求区间 | 天数 | 返回结果 |
|----------|------|----------|
| `startDate=20260101&endDate=20260401` | 91 天 | `ret_code` 0,`list` 90 条,日期 2026-01-01 ~ 2026-03-31 |
| `startDate=20260101&endDate=20260901` | 244 天 | `ret_code` 0,`list` 90 条,日期 2026-02-13 ~ 2026-05-13 |
两组请求的 `startDate` / `endDate` 都按请求值原样回显,`remark` 都是「查询成功!」。第二组复测两次结果一致,返回的日期起始点与请求的 `startDate` 不同。因此长跨度取数时,请以 `list[].publish_time` 的首尾作为真实区间依据,并且按 90 天为单位自行分段请求。
## FAQ
**Q1:`month` 和 `startDate` + `endDate` 能同时传吗?**
不能。文档标注两者互斥,`month` 与 `startDate`、`endDate` 二选一。
**Q2:不传货币参数会返回什么?**
2026-09-18 实测:`showapi_res_code` 为 0,但 `showapi_res_body.ret_code` 为 -1,`remark` 为「货币编号或货币名称必须输入其中一个参数!」,同时 `showapi_fee_num` 为 0。所以 `code` 与 `name` 至少要传一个。
**Q3:最早能查到哪一天的数据?**
文档说明可查询自 2009 年 1 月起的记录,具体以接口实际返回为准。
**Q4:历史数据和实时数据的口径一样吗?**
不一样。「100 外币兑人民币」是历史接入点的口径,实时接入点(105-30)的字段名与口径都不同。跨接入点整合时先对齐口径再落库。
**Q5:返回是每 1 单位外币还是每 100 单位?**
历史接入点按「100 外币兑人民币」口径返回,`middle_rate` 这类字段的数值对应 100 单位外币。
## 下一步阅读
- [银行汇率查询返回字段全解(五大价位 / 两层状态码 / 空值情况)](https://www.showapi.com/guides/exchange-rate-fields-105):历史与实时两套字段名的完整对照。
- [银行汇率查询:企业汇率看板的落库与走势实现](https://www.showapi.com/guides/exchange-rate-finance-dashboard-105):把历史数据落库画走势线。
- [银行汇率查询:跨境电商与留学缴费的多币种牌价管理](https://www.showapi.com/guides/exchange-rate-crossborder-105):对账环节怎么用历史接入点留痕。
- **本系列共 13 篇**:查看[银行汇率查询指南总目录](https://www.showapi.com/guides/exchange-rate-guides-105)





