Binance Web3 API 所有 API 接口均受 API Key 鉴权保护。每个请求都必须使用您的 Secret
Key 进行签名,确保只有持有有效凭证的授权客户端才能访问平台。
第一步 — 获取 API 凭证
前往开发者平台创建项目,生成 API Key 和
Secret Key:
| 凭证 | 说明 |
|---|
API Key | 唯一标识您的应用(请求头 X-OC-APIKEY) |
Secret Key | 用于签名请求(HMAC-SHA256 模式),请妥善保管,切勿泄露 |
第二步 — 了解必填请求头
每个认证请求都必须携带以下三个请求头:
| 请求头 | 必填 | 说明 |
|---|
X-OC-APIKEY | 是 | 您的 API Key 字符串 |
X-OC-TIMESTAMP | 是 | 当前 UTC 时间,ISO 8601 格式(含毫秒),如 2026-05-11T10:08:57.715Z |
X-OC-SIGN | 是 | 请求签名(Base64 编码),详见第三步 |
X-OC-RECV-WINDOW | 否 | 允许的时间偏差(毫秒),默认 5000,最大 60000 |
X-OC-NONCE | 否 | 唯一请求标识符,用于防重放;若未填写则使用 X-OC-SIGN 值代替 |
Base URL 与必填的 /build 前缀
所有接口均由同一域名提供服务,并固定使用 /build 基础路径:
Base URL = https://web3.binance.com/build
这意味着 HTTP 线上传输的每个请求行都以 /build/api/v1/... 开头,并且参与签名的
requestPath(见第三步)也必须包含 /build 前缀 —— 与线上传输的路径完全一致。
关键提示 —— 40102 Invalid signature 的首要原因: 漏掉 /build
前缀。即使请求本身 能被正确路由,签名串里写成裸 /api/v1/...
也会导致签名校验失败。构造待签名字符串时,务必 在路径前显式带上 /build。
| 项目 | 取值 / 规则 |
|---|
| Base URL | https://web3.binance.com/build |
| 完整请求 URL | https://web3.binance.com/build + /api/v1/... |
参与签名的 requestPath | /build/api/v1/...(如有 query 再追加 ?query) |
Host 请求头 | web3.binance.com(不带路径) |
裸 https://web3.binance.com/api/v1/...(不带 /build)会在边缘层被重定向到 /build
前缀 —— 但不要依赖重定向来生成签名。请始终在请求 URL 和签名的 requestPath 中显式带上
/build。
第三步 — 生成签名
3.1 构造待签名字符串(preHash)
将以下四个部分直接拼接(无分隔符):
preHash = timestamp + method + requestPath + body
| 组成部分 | 规则 |
|---|
timestamp | X-OC-TIMESTAMP 请求头的值(ISO 8601,如 2026-05-11T10:08:57.715Z) |
method | HTTP 方法大写(如 GET、POST) |
requestPath | 完整 HTTP 路径,含 /build 基础路径前缀,加上查询字符串,以 原始 URL 编码形式表示,如 /build/api/v1/dex/market/price?chainId=1&symbol=ETH%20USDT。详见 Base URL。 |
body | POST/PUT/DELETE 请求的原始请求体字符串;GET/HEAD 请求使用空字符串 "" |
重要: requestPath 必须使用 HTTP 线上传输的原始编码形式 —— 不做 URL
解码、不对查询参数排序、不合并参数。它必须以 /build 前缀开头;漏掉前缀是
40102 Invalid signature 最常见的原因。
示例(GET 请求)
timestamp = "2026-05-11T10:08:57.715Z"
method = "GET"
requestPath = "/build/api/v1/dex/market/price?chainId=1&symbol=ETH%20USDT"
body = ""
preHash = "2026-05-11T10:08:57.715ZGET/build/api/v1/dex/market/price?chainId=1&symbol=ETH%20USDT"
示例(POST 请求)
timestamp = "2026-05-11T10:08:57.715Z"
method = "POST"
requestPath = "/build/api/v1/dex/swap"
body = '{"chainId":1,"fromToken":"0xEEEE...","toToken":"0xA0b8...","amount":"1000000000000000000"}'
preHash = "2026-05-11T10:08:57.715ZPOST/build/api/v1/dex/swap{\"chainId\":1,...}"
3.2 使用 HMAC-SHA256 签名(默认)
以 Secret Key 对 preHash 计算 HMAC-SHA256,再对结果进行 Base64 编码:
signature = Base64( HMAC-SHA256(preHash, secretKey) )
所有字符串均以 UTF-8 编码后参与运算。
JavaScript / Node.js
const crypto = require("crypto");
const timestamp = new Date().toISOString(); // 如 "2026-05-11T10:08:57.715Z"
const method = "GET";
// 注意:路径必须包含 /build 基础路径前缀 —— 它是参与签名的 requestPath 的一部分。
const pathWithQuery =
"/build/api/v1/dex/market/price?chainId=1&symbol=ETH%20USDT";
const body = ""; // GET 请求为空字符串
const preHash = timestamp + method + pathWithQuery + body;
const signature = crypto
.createHmac("sha256", secretKey)
.update(preHash, "utf8")
.digest("base64");
Python
import hmac, hashlib, base64
from datetime import datetime, timezone
now = datetime.now(timezone.utc)
timestamp = now.strftime("%Y-%m-%dT%H:%M:%S.") + f"{now.microsecond // 1000:03d}Z"
method = "GET"
# 注意:路径必须包含 /build 基础路径前缀 —— 它是参与签名的 requestPath 的一部分。
path_query = "/build/api/v1/dex/market/price?chainId=1&symbol=ETH%20USDT"
body = ""
pre_hash = timestamp + method + path_query + body
signature = base64.b64encode(
hmac.new(secret_key.encode("utf-8"), pre_hash.encode("utf-8"), hashlib.sha256).digest()
).decode("utf-8")
Java
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
// pathWithQuery 必须包含 /build 基础路径前缀 —— 它是参与签名的 requestPath 的一部分。
String pathWithQuery = "/build/api/v1/dex/market/price?chainId=1&symbol=ETH%20USDT";
String preHash = timestamp + method + pathWithQuery + body;
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(new SecretKeySpec(secretKey.getBytes("UTF-8"), "HmacSHA256"));
String signature = Base64.getEncoder().encodeToString(
mac.doFinal(preHash.getBytes("UTF-8"))
);
3.3 使用 Ed25519 签名(高级)
若您的 API Key 配置为 Ed25519 签名模式,请使用 Ed25519 私钥对 preHash 签名并 Base64 编码:
signature = Base64( Ed25519Sign(preHash, privateKey) )
创建 API Key 时需在开发者平台上传 Ed25519 公钥(Base64 编码,X.509 DER 格式)。
Java
import java.security.*;
import java.util.Base64;
Signature signer = Signature.getInstance("Ed25519");
signer.initSign(ed25519PrivateKey);
signer.update(preHash.getBytes("UTF-8"));
String signature = Base64.getEncoder().encodeToString(signer.sign());
第四步 — 发送请求
在每个认证请求中附加三个必填请求头:
GET /build/api/v1/dex/market/price?chainId=1&symbol=ETH%20USDT HTTP/1.1
Host: web3.binance.com
X-OC-APIKEY: your-api-key-here
X-OC-TIMESTAMP: 2026-05-11T10:08:57.715Z
X-OC-SIGN: k3Y2mNpQr...base64sig...==
完整 JavaScript 示例
const crypto = require("crypto");
const axios = require("axios");
const API_KEY = process.env.OC_API_KEY;
const SECRET_KEY = process.env.OC_SECRET_KEY;
// BASE_URL 已包含 /build 基础路径前缀。
// 传入的 path 用 /api/v1/... 形式,由下面的函数统一在 URL 和签名中补上 /build 前缀。
const BASE_URL = "https://web3.binance.com/build";
const BUILD_PREFIX = "/build";
async function get(path, params = {}) {
// 使用 encodeURIComponent 编码,空格转为 %20(而非 URLSearchParams 的 +),与 HTTP 线上传输一致
const queryStr = Object.entries(params)
.map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`)
.join("&");
const fullPath = queryStr ? `${path}?${queryStr}` : path;
const timestamp = new Date().toISOString();
// requestPath 即 HTTP 线上传输的完整路径 —— 必须包含 /build 前缀。
const requestPath = BUILD_PREFIX + fullPath;
const body = ""; // GET 请求 body 为空字符串
const preHash = timestamp + "GET" + requestPath + body;
const signature = crypto
.createHmac("sha256", SECRET_KEY)
.update(preHash, "utf8")
.digest("base64");
const resp = await axios.get(BASE_URL + fullPath, {
headers: {
"X-OC-APIKEY": API_KEY,
"X-OC-TIMESTAMP": timestamp,
"X-OC-SIGN": signature,
},
});
return resp.data;
}
// 使用示例 —— path 不带 /build,由函数统一在 URL 和签名中补上。
get("/api/v1/dex/aggregator/supported/chain", { binanceChainId: "56" }).then(
console.log,
);
无论您选择哪种风格 —— 显式传入 /build/... 路径,或由辅助函数统一补 /build
—— 核心要求都是: 签名的 requestPath 与 请求 URL 必须同时携带
/build 前缀。两者不一致(例如签名不带 /build 但请求带了)会产生 40102 Invalid signature。
时间戳与防重放
网关对每个认证请求都会校验 X-OC-TIMESTAMP:
- 格式:必须是合法的 ISO 8601 字符串(如
2026-05-11T10:08:57.715Z)。
- 时间窗口:请求时间戳与服务器时间的误差不得超过
recv_window 毫秒。默认 5 000
ms(5 秒),可通过 X-OC-RECV-WINDOW 配置(最大 60 000 ms / 60 秒)。
- 防重放:每个 nonce(
X-OC-NONCE 或签名本身)在 2 × recv_window
时间窗口内仅可使用一次。重放请求将被拒绝,返回错误码 40103。
请确保您的服务器时钟与 NTP 同步,避免因时钟偏差导致时间戳校验失败。
频率限制
认证请求同时受四个维度的频率限制约束:
| 维度 | 默认上限 | 时间窗口 | 响应头 |
|---|
| 单 IP | 1 200 次请求 | 60 秒 | X-OC-RateLimit-Limit |
| 单 API Key | 1 200 次请求 | 60 秒 | X-OC-RateLimit-Remaining |
| 单用户 | 6 000 次请求 | 60 秒 | X-OC-Used-Weight |
| 单接口 | 5 RPS(默认) | 1 秒 | X-OC-Used-Weight |
超过限制时,网关返回 HTTP 429,并在响应头中携带 Retry-After(单位:秒)。
错误码
| HTTP 状态码 | 错误码 | 说明 |
|---|
| 400 | 40001 | 请求参数无效 |
| 401 | 40101 | API Key 缺失、无效或已被禁用/冻结 |
| 401 | 40102 | 签名不匹配或缺失 |
| 401 | 40103 | 时间戳已过期或请求被重放 |
| 403 | 40104 | API Key 权限不足 |
| 429 | 42900 | 请求频率超限 |
| 500 | 50000 | 服务器内部错误 |
| 503 | 50001 | 服务暂时不可用 |
所有错误响应均遵循统一格式:
{
"code": 40102,
"msg": "Invalid signature",
"data": null,
"timestamp": 1715420937000
}
Postman 快速接入
在 Postman 集合的 Pre-request Script 中添加以下脚本,即可为所有请求自动签名。在集合中把 Base
URL 设为 https://web3.binance.com/build,每个请求的 path 配置为 /api/v1/...
—— 下方脚本会在构造签名时为路径补上 /build 前缀,使签名的 requestPath 与线上传输的路径一致。
// Binance Web3 API Gateway — 自动签名脚本
const apiKey = pm.variables.get("api_key");
const secretKey = pm.variables.get("secret_key");
if (!apiKey || !secretKey) {
throw new Error("请先在 Collection Variables 中设置 api_key 和 secret_key");
}
const timestamp = new Date().toISOString();
const method = pm.request.method.toUpperCase();
const url = pm.request.url;
const pathStr = "/" + (url.path || []).join("/");
const qParams = (url.query || []).filter((p) => !p.disabled && p.key);
const queryStr = qParams
.map(
(p) => encodeURIComponent(p.key) + "=" + encodeURIComponent(p.value || ""),
)
.join("&");
const pathWithQuery = queryStr ? pathStr + "?" + queryStr : pathStr;
// 参与签名的 requestPath 必须包含 /build 基础路径前缀。
// Postman 请求 path 配置为 /api/v1/...(不带 /build),这里统一补上。
const signedRequestPath = pathWithQuery.startsWith("/build")
? pathWithQuery
: "/build" + pathWithQuery;
const body =
method === "GET" || method === "HEAD"
? ""
: pm.request.body
? pm.request.body.toString()
: "";
const preHash = timestamp + method + signedRequestPath + body;
const signature = CryptoJS.enc.Base64.stringify(
CryptoJS.HmacSHA256(preHash, secretKey),
);
pm.request.headers.upsert({ key: "X-OC-APIKEY", value: apiKey });
pm.request.headers.upsert({ key: "X-OC-TIMESTAMP", value: timestamp });
pm.request.headers.upsert({ key: "X-OC-SIGN", value: signature });
在集合 → Variables 中设置 api_key 和 secret_key 后,每个请求将自动完成签名。
Last modified on