四个只读路由,无需密钥和 cookie,使用 聚合器(CoinGecko、CoinMarketCap)和市场库(CCXT)期望的字段名。这些接口供程序自动读取,可用于构建仪表盘、为指数提供数据或核对价格。此 API 中没有下单路由——这里的任何内容都不会移动资金,也不需要账户。
一切挂在 https://offcode.pro/api/public/ 之下,只接受 GET,返回 application/json。ticker_id 形如 BASE_TARGET(BTC_USDT):下划线前为基础币,后为计价币,大写字母和数字,每侧 2 到 15 个字符。符号不符合该格式的交易对不予发布。
每个数字都以 十进制字符串 传输,绝不用浮点数——八位小数的币经过 float 会丢失小数。时刻为自 Unix 纪元起的毫秒数。
| 路由 | 返回内容 | 参数 |
|---|---|---|
GET /pairs | 此数据源覆盖的每个交易对,各自带有价格来源 | — |
GET /tickers | 现货交易对的价格、24 小时成交量、最高价、最低价和买卖双边 | — |
GET /orderbook | 单个交易对的订单簿 | ticker_id · depth |
GET /trades | 单个交易对的最近成交,最新在前 | ticker_id · type · limit |
GET /historical_trades | 与 /trades 相同——两个名字,同一实现 | 相同 |
此数据源覆盖内容的完整列表,也是其他路由的门户:不在这里的 ticker_id 在订单簿和成交上都返回 404。kind 区分平台的现货市场(spot)与永续(perp);同一名称同时服务两者时,归现货。price_source 在条目本身说明数字来自哪里。
每个 spot 交易对的价格、24 小时成交量、最高价、最低价和买卖双边。perp 交易对不包含在内:这是聚合器标准所描述的切片。
ticker_id | 交易对,形如 BASE_TARGET。 |
base_currency · target_currency | 分别列出交易对的基础币和计价币。 |
last_price | 永续合约上的最新成交价。 |
base_volume | 以基础货币计的 24 小时成交量,取交易场所发布时的测量值。只有在其缺失时,路由才用 target_volume 除以 last_price 并向下截断到 8 位小数——这是明确声明的计算值,不是交易所给出的数字。 |
target_volume | 以计价货币计的 24 小时成交量,来源原始值。 |
bid · ask | 两者相等,且都等于永续合约的中间价,并非订单簿中的买一价和卖一价。见 数据来自哪里。 |
high · low | 最近 24 小时的最高价和最低价。 |
timestamp | 读取时刻,自 Unix 纪元起的毫秒数。 |
单个交易对的订单簿。bids 和 asks 是 [price, size] 数对,均为十进制字符串,最优价在前。timestamp 是来源的时钟,不是我们的:用本地时钟会让过期的订单簿冒充新鲜的。
depth 可选,每侧最多 100 档。省略时返回上限:100。更大的请求不会被拒绝——而是截断到 100。
单个交易对的最近成交记录,最新在前。两个路由是同一实现、同一缓存:聚合器标准要求 historical_trades,CCXT 通常请求 trades,这样就绝不会有一天二者答案不同。
type 可选(buy 或 sell,按主动方),limit 最多 100,同样是截断而非拒绝。省略 type 返回双边,省略 limit 返回上限:100。trade_id 是派生的——时刻、方向、价格和数量——同一笔成交在两次读取间保持稳定,它不是交易场所自己的成交标识。
此数据源中的价格、订单簿、成交和 24 小时成交量都来自 永续市场——包括标记为 spot 的交易对。OFFCODE 的现货没有自己的订单簿:它报的是同名永续合约的 中间价。这就是为什么每个 /pairs 条目都带有 price_source:使用数据源的人在数据源本身读取来源,而不是从标签去推断——推断错误。
ask − bid 为零。真实订单簿不可能存在零买卖价差,请勿将这两个字段视为同一订单簿的买一价和卖一价。base_volume 是 永续合约 以基础货币计的 24 小时成交量,取交易场所发布时的测量值。只有在其缺失时,路由才用 target_volume 除以 last_price 并向下截断到 8 位小数——这是明确声明的计算值,不是交易所给出的数字。
只有存在同名可交易市场时,交易对才会发布:发布就是承诺服务,从 /pairs 出来的 ticker_id 必须紧接着在订单簿和成交上能给出答复。没有可交易对的托管币种不进入数据源,在交易场所名称带乘数因子的交易对也不进入——1000PEPE_USDT 永续按原样发布,绝不会作为 PEPE_USDT。
每个 IP 每分钟 600 次请求,每条路由各自计算。超出则返回 429。
2xx 响应带 Cache-Control: public, max-age=5;非 2xx 的响应带 no-store,因为一个被缓存五秒的 404 会比刚上市的交易对活得更久,而一个被缓存的 502 会在交易场所已经恢复之后仍报告它宕机。
底层上,订单簿每个交易对和深度最多每 350 毫秒 重读一次,成交每个交易对每 1 秒 一次:对交易场所的调用上限由缓存决定,而不是由请求人数决定。失败的读取绝不缓存。
Access-Control-Allow-Origin: *,不带凭据——没有 cookie、密钥或认证头,响应中没有任何个性化内容。
| 状态码 | 触发情形 | 响应体 |
|---|---|---|
| 400 | ticker_id 不符合格式、type 既非 buy 也非 sell、depth 或 limit 不是整数 | {"code": "VALIDATION_ERROR", "message": "…"} |
| 404 | 格式正确但不在 /pairs 中的 ticker_id | {"error": "UNKNOWN_TICKER"} |
| 429 | 超过该 IP 的请求限制 | {"statusCode": 429, "code": "RATE_LIMITED", "message": "…"} |
| 502 | 交易场所未响应,或返回了失败 | {"code": "UPSTREAM_UNAVAILABLE", "message": "…"} |
用 502 而不是 500,是有意的:交易场所的故障不是我们的故障,外部读取者需要这个区别来判断是否值得重试。
域名位于 Cloudflare 之后。浏览器可以通过;不带 cookie 的命令行调用可能收到验证挑战而不是 JSON——这不是路由在拒绝,而是边缘在询问来者是谁。如果你的机器人需要持续抓取此数据源,请在开启爬虫前申请许可:说明 user-agent、出站 IP 段和预期频率,发送至 联系我们。