CrestRate
登录注册
本页目录

CrestRate API 接口文档

多源聚合的汇率接口,为跨币种收款和付款的企业而做。你决定汇率站在哪一边,点差按 API key 配置,报价单同时锁定汇率和点差。

  • 基地址 — https://api.crestrate.com。汇率接口都在 /v1 下,例如 https://api.crestrate.com/v1/rate
  • 第一次接入 — 先看快速开始,四段可复制的代码带你跑通第一次调用
  • 机器可读规范 — OpenAPI 3.1
  • 套餐、配额与限速 — 定价
  • 服务状态 — https://crestrate.com/zh/status

适用场景

用一种货币标价、用另一种货币结算,就用得上。我们不按行业划分客户,常见用法如下:

  • 跨境电商 — 商品标价换算成客户的货币
  • SaaS 与订阅制 — 按客户本地货币出账单
  • 访日游客消费 — 酒店、零售、免税店、收银系统以日元定价,游客用港币、人民币、美元、欧元付款
  • B2B 进出口贸易 — 按买方货币开发票,报价有效期内用报价单锁价
  • 平台与市场 — 向买家收款用 strategy=max,给卖家结算用 strategy=min
  • 旅游、留学、签证等中介 — 按客户的货币报价
  • 游戏与数字商品 — 按地区定价

支持的币种

以下币种提供实时数据,base 与 quote 可任意组合:

币种 代码 金额最小单位
美元 USD 0.01
日元 JPY 1
欧元 EUR 0.01
港币 HKD 0.01
人民币 CNY 0.01

暂时无法提供实时数据: TWD、SGD、GBP、AUD、KRW、MYR、THB,稳定后开放。

在此之前,请求中使用这些代码会返回 HTTP 422 currency_not_available,supported 字段列出当前可用的币种。完全无法识别的代码返回 HTTP 400 unsupported_currency。请求中的币种代码不区分大小写,响应中一律大写。

汇率是怎么选出来的

每次请求都会把当前健康的全部数据源一起纳入计算,而不是只问一家:

  1. 各源的汇率表统一归一化到同一基准,你要的货币对按交叉汇率算出来
  2. 数据过期的源、不覆盖该货币对的源,先剔除
  3. 从最新鲜的那一档源(实时 → 小时级 → 每日)取中位数作为基准。 这是对「当前市场价」最可靠的估计
  4. 与基准偏离超过故障阈值的源被判定为数据损坏,剔除
  5. 按 strategy 在幸存的源里选价:max 取最高、min 取最低、median 取最接近中位数的那个。 再做双向钳制:高于封顶线 cap_rate 就压回封顶线,低于保底线 floor_rate 就抬回保底线
  6. 按收付方向叠加点差:收款方往上加,付款方往下减

返回里始终写明最终汇率来自哪个源、其他源各报了多少、以及任何被剔除的源和机器可读的剔除原因(excluded_code)。数据源用稳定的匿名代号标识,如 source_a。 有效源不足时返回 HTTP 503 no_rate,而不是给出一个我们无法担保的数字。

你决定汇率站在哪一边

同一个货币对,收钱时汇率越高越好,付钱时越低越好。用 strategy 告诉我们你在哪一边,返回里的 side 会写明本次按哪一边算。

strategy side 对谁有利 典型用途
max(默认) charge 收款方:选最高汇率,同样的标价收到更多 电商、SaaS、酒店、B2B 开票
min pay 付款方:选最低汇率,同样的应付额付出更少 平台给卖家结算、给海外供应商付款
median charge 中立:选最接近各源中位数的汇率 会计记账、对内报表

strategy 不区分大小写,其他取值返回 HTTP 400 bad_request。side 同时决定点差方向和金额取整方向:

项目 charge(收款方) pay(付款方)
点差 汇率往上,客户多付 汇率往下,你少付
payable 取整 向上取整到最小货币单位 向下取整到最小货币单位
gain_vs_mid payable - mid_payable(多收的) mid_payable - payable(少付的)

两个方向都有保护。 选出的汇率会与新鲜度基准 anchor_rate 比较:高于封顶线 cap_rate 就压回(capped: true),低于保底线 floor_rate 就抬回(floored: true)。收款时不会明显高于实时市场,付款时不会明显低于实时市场 —— 对方拿公开汇率核对也站得住。点差是你主动配置的,在钳制之后才叠加。

点差

点差是你在选出的汇率上额外加的幅度,单位基点(bps),100 基点 = 1%。

项目 说明
在哪设置 控制台的 API key 列表,每把 key 单独设置
默认点差 这把 key 在所有币种上使用的点差
按币种单独设置 按 quote 币种覆盖默认点差,例如 HKD 120 基点、JPY 200 基点。只能为提供实时数据的币种单独设置
取值范围 0 ~ 1000 基点(0% ~ 10%)。设为 0 表示明确不加点差
生效时间 保存后立即生效,下一次请求就用新值
报价单 点差在创建报价单时锁定。之后改点差,已发出的报价单不受影响

优先级从高到低,返回里的 markup_source 会写明本次用的是哪一个:

  1. 该 key 对此币种的单独设置 → key_currency
  2. 该 key 的默认点差 → key_default
  3. 平台默认 → platform

同币种对(如 USD → USD)没有发生兑换,不加点差,markup_source 为 none。

方向和取整都跟着 side 走,结果始终对你有利。 收款方:raw_rate × (1 + markup_bps/10000),金额向上取整;付款方:raw_rate × (1 - markup_bps/10000),金额向下取整。

算例(数字仅作示例,不是实时行情;为便于对比,假设两种情况选出的汇率都是 7.8000):一笔 1,000 美元的订单,用港币结算,点差 150 基点(1.5%)。

场景 不加点差 点差 150 基点 差额
你在收款(strategy=max) 汇率 7.8000,客户付 HK$7,800.00 汇率 7.9170,客户付 HK$7,917.00 多收 HK$117.00
你在付款(strategy=min) 汇率 7.8000,你付 HK$7,800.00 汇率 7.6830,你付 HK$7,683.00 少付 HK$117.00

先预览再保存。 在控制台设置点差时有效果预览:调数值时当场显示客户多付多少、你少付多少。

披露。 在对加价有披露要求的地区(例如欧盟面向消费者的支付),请向你的客户披露加价。

报价单锁价

报价单把你展示给客户的价格冻结到过期为止,展示和付款之间的汇率波动不会造成金额对不上。

  • POST /v1/quotes 在创建时锁定最终汇率 rate、当时生效的点差 markup_bps 和结算金额 payable
  • 之后在控制台修改这把 key 的点差,不会改变已发出的报价单
  • 报价单在 ttl_seconds 内有效(目前为 900 秒,即 15 分钟)。请从响应读取,不要写死
  • 保存 quote_id,客户付款时用 GET /v1/quotes/{quote_id} 取回;过了 expires_at 会返回 404,此时应重新创建报价单

网站演示

首页上的在线演示只用于体验,不是可以接入的接口:

  • 数据延迟 1 小时:用各数据源 1 小时前的最新快照计算,结果旁边标出数据时间
  • 每次请求都经过无感的人机验证(Cloudflare Turnstile)
  • 使用平台默认点差,按网段和全站限流,高峰期可能提示繁忙
  • 不接受 API key,不计量,不占用任何账号的配额

需要实时数据请在控制台免费创建 API key。

接口参考

鉴权

所有 /v1 接口都必须带 API key,没有匿名访问。

请求头 示例
X-API-Key X-API-Key: <你的 key>
Authorization Authorization: Bearer <你的 key>
  • 任选其一;两者都带时以 X-API-Key 为准
  • 在控制台创建和撤销 key。需先完成邮箱验证,每个账号最多同时持有 10 把有效 key。明文只显示一次
  • 撤销后的 key 立即失效(HTTP 401 invalid_api_key)
  • 请从你的服务端调用。/v1 响应不带 CORS 头;嵌在网页或手机 App 里的 key 任何人都能拿走
  • GET /health 与 GET /openapi.json 不需要 key

通用约定

约定 说明
汇率与金额一律是字符串 不是 JSON number。JSON 的 number 是 IEEE 754 双精度,0.05117904 这类值解析后会丢精度,金额算错。请用 Decimal(Python)/ BigDecimal(Java)/ decimal.js(JS)解析。汇率固定 8 位小数
时间 一律 ISO 8601 UTC 字符串,如 2026-09-14T10:38:01Z。需要做算术的地方额外给 *_unix(Unix 秒,浮点)
百分比 字符串,单位是 %(不是小数)。"0.1791" 表示 0.1791%,不是 17.91%
币种代码 ISO 4217。请求中不区分大小写,响应中一律大写。见上文「支持的币种」
base / quote base = 标价币种,quote = 结算币种(收款时是客户支付的币种,付款时是你付出的币种)。汇率含义恒为「1 单位 base 能换多少 quote」
缓存与 Cookie 汇率响应带 Cache-Control: no-store。接口从不设置 Cookie

限速与月配额

每个套餐有一个限速(稳定速率加短时突发)和一个月请求配额,公布在定价页。

  • 两者都按账号计算,不按 key。 同一账号下的所有 API key 共享同一个限速和同一份月配额,多建 key 不会提高任何一项。X-Quota-* 响应头显示的是整个账号的合计
  • 月配额在每个自然月开始时(UTC)重置
  • 通过鉴权和限额检查的请求,无论结果如何都计入配额 —— 包括 400、404、422、503。被 401、403、429 拒绝的请求不计入
  • 对 /v1 接口发出的 HEAD 请求与 GET 完全相同地处理(完整执行汇率计算),因此同样计入配额和限速
  • 不存在的路径返回 404 not_found,不计量

所有 /v1 响应(包括错误响应)都带以下响应头:

响应头 含义
X-RateLimit-Limit 最大突发量:可以连续发出多少个请求
X-RateLimit-Remaining 此刻不必等待还能发出多少个请求
X-RateLimit-Reset 下一个请求名额可用的 Unix 时间(秒)
X-Quota-Limit 账号的月配额。0 表示不限
X-Quota-Used 账号本月已用请求数,含本次
X-Quota-Remaining 本月剩余请求数。X-Quota-Limit 为 0(不限)时恒为 0,请先看上限
X-Request-Id 本次请求的 ID。联系支持时请附上
Retry-After 需等待的秒数。只随 429 rate_limited 返回

请求无法归属到某个账号时(缺少或无效的 key、账号停用或邮箱未验证、请求体超限、内部错误),限速与配额头给出的是与任何账号无关的中性默认值。

触发限额时

响应 含义 怎么办
429 rate_limited 短时间内请求过多 等待 Retry-After 秒(响应体也有 retry_after)后重试
429 quota_exceeded 账号本月配额已用完。硬性阻断:不做超额计费,不带 Retry-After 不要重试。升级套餐(upgrade_url 为定价页的绝对地址)或等下个月。响应体带 used 与 quota

请求处理顺序

请求按以下顺序检查,第一个不通过的检查决定响应:

  1. 请求体大小:超过 16 KiB → 413 payload_too_large
  2. 缺少 API key → 401 api_key_required;key 无效或已撤销 → 401 invalid_api_key
  3. 账号已停用 → 403 account_disabled;邮箱未验证 → 403 email_not_verified
  4. 限速 → 429 rate_limited;月配额 → 429 quota_exceeded
  5. 参数 → 400 bad_request / 400 unsupported_currency / 422 currency_not_available(此时已计入配额)
  6. 定价 → 有效源不足 503 no_rate;数据存储短暂不可达 503 storage_unavailable

GET /v1/rate

取单个货币对的最终汇率,并附全部数据源的明细。

查询参数

参数 必填 说明
base 是 标价币种。别名 from
quote 是 结算币种。别名 to
strategy 否 汇率站在哪一边:max(默认,收款)/ min(付款)/ median(中立)。不区分大小写

同币种对(如 base=USD&quote=USD)返回汇率 1.00000000,chosen_provider 与 anchor_tier 为 identity。

响应:顶层字段

字段 类型 说明
base string 标价币种
quote string 结算币种
rate string 最终汇率,算金额就用它。收款方(side=charge)为 raw_rate × (1 + markup_bps/10000),付款方(side=pay)为 raw_rate × (1 - markup_bps/10000)。markup_bps 为 0 时等于 raw_rate
raw_rate string 加点差前的汇率。按 strategy 在各源中选出;触及 cap_rate / floor_rate 时已被钳制
mid_rate string 有效源的中位数,约等于市场中间价。可用来衡量你比市场高出多少
low_rate string 有效源中的最低汇率。strategy=min 且未触及保底线时等于 raw_rate
high_rate string 有效源中的最高汇率。strategy=max 且未触及封顶线时等于 raw_rate
markup_bps int 本次实际使用的点差,单位基点(100 基点 = 1%)。同币种对恒为 0
markup_source string 点差来源:key_currency(该 key 对此币种的单独设置)/ key_default(该 key 的默认点差)/ platform(平台默认)/ none(同币种对,不加点差)
strategy string 本次使用的选价策略:max / median / min
side string 本次站在哪一边:charge(收款方;max 与 median)/ pay(付款方;min)。点差方向与取整方向跟随它
chosen_provider string 最终汇率来自哪个源,匿名代号,如 source_a。同币种对为 identity
source_count int 参与定价的有效源数量(不含被剔除的)
spread_vs_mid_pct string 最终汇率相对 mid_rate 的偏离,单位 %,4 位小数。收款时通常为正,付款时通常为负
anchor_rate string 新鲜度基准。剔除异常值与封顶/保底都以它为准;取最新鲜那一档的中位数
anchor_tier string 基准来自哪一档:realtime / hourly / daily / all / identity。退到 daily 或 all 说明新鲜源都暂不可用,报价可能偏离市场
anchor_notes string[] 更新鲜的档位为何没被采用为基准,英文说明。正常情况下为空数组
cap_rate string | null 封顶线:anchor_rate 加一个固定幅度。raw_rate 不会超过它。同币种对为 null
capped bool true 表示选出的汇率超过封顶线、被压了回来。说明市场在动而较慢的源还没跟上,值得告警
floor_rate string | null 保底线:anchor_rate 减去同样的幅度。raw_rate 不会低于它。同币种对为 null
floored bool true 表示选出的汇率低于保底线、被抬了回来。多见于 strategy=min
sources object[] 全部数据源明细,含被剔除的源。见下表
generated_at string 本次响应生成时间(ISO 8601 UTC)
generated_at_unix float 同上,Unix 秒

响应:sources[] 每一项

字段 类型 说明
provider string 稳定的匿名源代号,如 source_a
label string 展示名,如 Source A
data_freq string | null 该源自身数据的更新频率:realtime / hourly / daily
rate string | null 该源给出的 base→quote 汇率。null 表示该源不覆盖此货币对
vs_anchor_pct string | null 该源相对 anchor_rate 的偏离,单位 %(正数表示更高)
fetched_at string 我们抓取它的时间(ISO 8601 UTC)
age_seconds float 距那次抓取过了多少秒
source_time string | null 该源自称的数据时间。null 表示该源不提供
used bool 是否参与了本次定价
chosen bool 是否就是被选中的那个源
excluded_code string | null 机器可读的剔除原因;参与定价时为 null。监控请匹配它
excluded_reason string | null 给人看的英文剔除原因;参与定价时为 null。文案可能调整,不要解析

excluded_code 的取值

excluded_code excluded_reason 示例 含义 怎么办
missing_currency Source does not cover this currency pair 该源不覆盖此货币对 正常,其他源会补上
snapshot_stale Snapshot is stale (9000s > 7200s) 太久没从该源抓到新数据 其他源会补上;持续出现可看状态页
deviates_from_anchor Deviates 12.5% from the realtime tier anchor, beyond +/-5%; treated as a data fault 该源数值离基准太远 该源数据很可能损坏,你这边无需处理

GET /v1/rates

一次取多个货币对的汇率表。每行是 GET /v1/rate 的精简版,不含 sources 明细。

查询参数

参数 必填 说明
base 否 逗号分隔的标价币种,如 USD,EUR。空项与重复项会被忽略
quote 否 逗号分隔的结算币种,如 JPY,HKD

省略参数时使用服务的默认币种网格;如果你的集成依赖确切的行,请显式传入两个参数。 列表里有无法识别的代码时整个请求返回 400 unsupported_currency;有暂时无法提供实时数据的币种时返回 422 currency_not_available。先整体检查 base 列表,再检查 quote:同一列表内无法识别的代码优先于暂时无法提供实时数据的币种报错,但 base 的问题总是先报,因此 base 含暂时无法提供实时数据的币种、同时 quote=ZZZ 时返回 422。

各行使用平台默认点差,不使用你这把 key 的点差。 需要应用你自己的点差时,请用 GET /v1/rate 或 GET /v1/convert。

响应

字段 类型 说明
rows object[] 每个 base × quote 组合一行
generated_at / generated_at_unix string / float 生成时间

rows[] 每一项

字段 类型 说明
base / quote string 货币对
final_rate string 按平台默认点差计算的最终汇率
raw_rate string 加点差前
mid_rate string 各源中位数
chosen_provider string 被选中的源(匿名代号)
source_count int 有效源数量
markup_bps int 使用的点差(平台默认)
spread_pct string 相对中间价的溢价,单位 %,3 位小数
anchor_tier string 基准档位
capped bool 是否触及封顶线
error string | null 不为 null 时该行没有汇率:只有 base、quote、error 三个字段。典型原因是该货币对有效源不足。使用每一行之前务必判空

GET /v1/convert

把标价币种的金额换算成结算金额。金额取整到币种的最小单位(JPY 到 1;USD、EUR、HKD、CNY 到 0.01),取整方向跟随 side:收款向上、付款向下,零头始终对你有利。

查询参数

参数 必填 说明
base / quote 是 同 GET /v1/rate,含别名 from / to
amount 是 标价币种金额,十进制字符串,必须 > 0。换算结果(payable、mid_payable)按结算币种最小单位取整后,连同小数位最多 28 位,超出时返回 400 bad_request
strategy 否 同 GET /v1/rate

响应

字段 类型 说明
base / quote string 货币对
amount string 你传入的金额,十进制字符串
payable string 结算金额。收款方(side=charge)是客户应付金额,向上取整;付款方(side=pay)是你应付出的金额,向下取整
rate string 使用的最终汇率
mid_rate string 市场中间价
mid_payable string 按中间价计算的金额(四舍五入),用于对比
gain_vs_mid string 对你有利的差额,越大越好。收款方:payable - mid_payable(多收的);付款方:mid_payable - payable(少付的)
markup_bps int 使用的点差
markup_source string 点差来源,同 GET /v1/rate
side string charge / pay,同 GET /v1/rate
chosen_provider string 汇率来自哪个源(匿名代号)
source_count int 有效源数量
anchor_tier string 基准档位
capped bool 是否触及封顶线
floored bool 是否触及保底线

GET /v1/convert 只做换算,不锁价。真实下单请用 POST /v1/quotes。


POST /v1/quotes

创建锁价报价单:汇率、点差和 payable 在 ttl_seconds 内保持不变,结算以 payable 为准。

请求体(JSON 对象,Content-Type: application/json,不超过 16 KiB)

字段 必填 说明
base / quote 是 货币对。别名 from / to
amount 是 标价币种金额,必须 > 0。建议传十进制字符串,也接受 JSON number
reference 否 你自己的订单号(最多 128 个字符),原样保存并返回,便于对账
strategy 否 汇率站在哪一边,同 GET /v1/rate

请求体不是合法 JSON、不是 JSON 对象或字段类型不对时返回 400 bad_request。

响应(HTTP 201)

字段 类型 说明
quote_id string 报价单 ID(32 位小写十六进制)。请保存,用于后续查询与对账
reference string | null 原样返回你传入的订单号
base / quote string 货币对
amount string 标价币种金额
payable string 结算金额,即锁定的值。过期前不会变化。取整方向跟随 side
rate string 锁定的最终汇率
raw_rate string 加点差前的汇率
mid_rate string 下单时的市场中间价,便于对账
markup_bps int 创建时锁定的点差。之后在控制台修改点差不影响这张报价单
strategy string 选价策略
side string charge / pay,同 GET /v1/rate
chosen_provider string 汇率来自哪个源(匿名代号)—— 争议或对账时的凭据
source_count int 当时的有效源数量
created_at / created_at_unix string / float 创建时间
expires_at / expires_at_unix string / float 过期时间。过期后用该 ID 查询返回 404
ttl_seconds int 锁价时长(秒)

报价单无法保存时返回 503 storage_unavailable,此时报价单不存在,请重试。

GET /v1/quotes/{quote_id}

取回报价单。字段与创建时返回的完全相同,另多一个:

字段 类型 说明
expired bool 是否已过期。报价单一过期就会被删除,通常你会直接得到 404;只有在删除前的极短窗口内这个字段才可能为 true
  • quote_id 不是 32 位小写十六进制,或报价单不存在、已过期 → 404 not_found
  • 503 storage_unavailable 表示此刻无法查询,不代表报价单已过期。请重试

GET /v1/sources

当前为你提供汇率的数据源有哪些、各自有多新鲜。用来判断某个汇率可以信任到什么程度。

响应

字段 类型 说明
sources object[] 当前启用的数据源
source_count int 数据源数量
last_poll_at string | null 最近一次抓取时间(ISO 8601 UTC)

sources[] 每一项

字段 类型 说明
provider string 匿名源代号,与 GET /v1/rate 的 sources[].provider 对应
label string 数据源展示名
data_freq string 该源自身数据的更新频率:realtime / hourly / daily
last_fetch_at string | null 我们最近一次从该源抓取的时间
last_fetch_age float | null 距最近一次抓取过了多少秒
source_time string | null 该源自称的数据时间。null 表示该源不提供
source_age_seconds float | null 该源数据的年龄(秒)
currencies int 该源当前覆盖了多少个支持的币种

这两个时间含义完全不同。 last_fetch_at 是我们拉取数据的时间,所以总是很新; source_time 是数据源自己声称的数据时间。每日更新的源通常滞后 12–36 小时, 个别每日源在周末会超过 80 小时 —— 这是正常的。 只看 last_fetch_at 判断新鲜度会严重误判。


GET /health

服务健康检查,不需要 API key。供你的监控或负载均衡使用。

字段 类型 含义
status string ok / degraded。只反映「此刻能不能出价」
sources_healthy int 当前有新鲜可用数据的源数量
last_updated_at string | null 最近一次抓到源数据的时间(ISO 8601 UTC)

HTTP 状态:ok 时 200,degraded 时 503。

该接口刻意只返回一个健康信号,不透露内部抓取状态和上游错误细节。 需要逐个源的新鲜度请用 GET /v1/sources,或查看状态页。

GET /openapi.json

上述全部接口的 OpenAPI 3.1 文档,地址为 https://api.crestrate.com/openapi.json。不需要 API key,允许浏览器跨域读取,缓存 5 分钟。文档同时声明了两种鉴权方式(X-API-Key 与 Bearer),SDK 生成器可直接使用。

网站上的 https://crestrate.com/openapi.json 以 HTTP 302 重定向到上述地址。工具里请直接填写 API 地址。

错误响应

所有接口的错误格式一致:

字段 类型 说明
error string 机器可读的错误码。请按它匹配,不要按 message
message string 给人看的英文说明,文案可能调整
currency string 出错的币种代码(unsupported_currency、currency_not_available)
supported string[] 提供实时数据的币种(currency_not_available)
retry_after number 需等待的秒数(rate_limited)
used / quota int 本月已用请求数 / 月配额(quota_exceeded)
upgrade_url string 定价页的绝对地址(quota_exceeded)
HTTP error 含义 可以重试吗
400 bad_request 参数缺失或非法:缺 base/quote、缺 amount、amount ≤ 0、不是数字或过大、未知 strategy、请求体不是合法 JSON、reference 过长 否,先修正请求
400 unsupported_currency 无法识别的币种代码。带 currency 否
401 api_key_required 没有带 API key 否,请带 X-API-Key 或 Authorization: Bearer
401 invalid_api_key key 无效或已撤销 否
403 account_disabled 账号已被停用,请联系支持 否
403 email_not_verified 账号邮箱尚未验证 验证后可以
404 not_found 报价单不存在或已过期;路径不存在 否
413 payload_too_large 请求体超过 16 KiB 否
422 currency_not_available 该币种暂时无法提供实时数据。带 currency 与 supported 开放前不行
429 rate_limited 超过限速。带 Retry-After 头与 retry_after 字段 可以,等 Retry-After 之后
429 quota_exceeded 月配额已用完。带 used、quota、upgrade_url 否,升级或等下个月
500 internal_error 服务端意外错误 可以,退避重试;持续出现请附 X-Request-Id 联系支持
503 no_rate 有效源不足,无法给出可信的汇率。message 列出各源被剔除的原因(只含匿名代号) 可以,稍后重试;期间使用你自己的备用汇率
503 storage_unavailable 服务暂时不可用,未保存任何数据 可以,退避重试

示例:

{
  "error": "currency_not_available",
  "message": "Real-time data for GBP is temporarily unavailable. Supported: USD, JPY, EUR, HKD, CNY.",
  "currency": "GBP",
  "supported": ["USD", "JPY", "EUR", "HKD", "CNY"]
}

503 no_rate 是刻意的 —— 我们宁可不给价,也不给来源存疑的价。调用方应稍后重试,或回退到自己的兜底汇率。不要当成 0 处理。


最佳实践

用 strategy 选对边。 向客户收款用默认的 max,给卖家或供应商付款用 min,median 只用于记账。选错了,选价、点差和取整就都在替对方着想。

用十进制类型解析汇率,永远不要用浮点。 所有汇率和金额都是 JSON 字符串,正是为此。 按 IEEE-754 双精度解析,0.05117904 会丢精度,合计金额会慢慢漂移。 请用 Decimal / BigDecimal / decimal.js / bcmath。

收款前一定先锁价。 客户看到价格和实际付款之间有时间差,汇率在这段时间里会动。 POST /v1/quotes 把汇率、点差和金额冻结到 TTL 结束,并给你一个 quote_id 用于之后对账。 GET /v1/convert 只用于展示和估算 —— 不要用它下单。

rate_limited 值得重试,quota_exceeded 不值得。 前者是暂时的,按 Retry-After 退避后再试。 后者在本自然月内是硬性阻断,而且账号下所有 key 共同受限。请升级,或等下个月重置。

永远不要把 503 no_rate 当成 0。 它的意思是「有效源太少,我们不会给你一个站不住的价格」。 回退到你自己的兜底汇率,或暂停下单流程。不要乘以 0。

在你这边先校验币种。 使用暂时无法提供实时数据的币种的请求同样计入配额;调用前先对照支持列表检查。

在你这边做缓存。 汇率不会比我们最快的源变得更快。缓存 30–60 秒能大幅减少用量,精度几乎不受影响。

关注 capped、floored 和 anchor_tier。 capped: true 或 floored: true 表示市场在动而较慢的源还没跟上,我们把报价钳回了实时市场附近。 anchor_tier 退到 daily 或 all 表示最新鲜的源暂时不可用 —— 汇率仍然可用,只是不如平时新鲜。

监控按 error 与 excluded_code 匹配,不要按文案。 message 与 excluded_reason 是给人看的,措辞可能调整。

版本策略

当前为 v1,版本号是路径的一部分(/v1)。我们会新增字段而不另行通知,请做防御性解析,忽略不认识的键。

删除或改变现有字段的用途、修改字段类型、修改错误码的含义或 HTTP 状态,我们不会在少于 90 天通知期的情况下进行。 通知会发送到近期有调用的每位客户的账号邮箱。

支持

有疑问,或发现行为与文档不符?请发邮件至 [email protected],并附上该请求的 X-Request-Id。