CrestRate
登入註冊

快速入門

從零到第一次成功呼叫,通常不到兩分鐘。

基礎位址: https://api.crestrate.com/v1

取得 API key

註冊後在控制台建立。免費方案每月 1,000 次,無需信用卡。 明文只顯示一次,請當場存進您的密鑰管理工具。

查詢匯率

base 是商品標價幣別,quote 是客戶支付幣別。回傳的 rate 就是「1 單位 base 換多少 quote」,可直接用來計算金額。

所有 /v1 請求都必須透過 X-API-Key 或 Authorization: Bearer 附上 key,否則回傳 401 api_key_required。

curl -H "X-API-Key: $CR_API_KEY" \
  "https://api.crestrate.com/v1/rate?base=JPY&quote=HKD"
所有匯率和金額都是字串,不是 JSON number。 JSON 的 number 是 IEEE 754 雙精度,0.05117904 這類值解析後會失去精度、金額算錯。請用 Decimal / BigDecimal / decimal.js / bcmath 解析。

下單時鎖定價格

客戶從看到價格到實際付款之間有時間差,匯率會變動。用 POST /v1/quotes 鎖定報價,取得的 payable 在有效期限內不變,對帳才不會亂。

curl -X POST "https://api.crestrate.com/v1/quotes" \
  -H "X-API-Key: $CR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"base":"JPY","quote":"HKD","amount":"10000","reference":"ORDER-8823"}'

# → {"quote_id":"4ac0…","payable":"524.15","rate":"0.05241460",
#    "expires_at":"2026-09-14T12:53:01Z","ttl_seconds":900, …}

處理速率限制與配額

每個回應都帶 6 個標頭,用戶端應據此退避,而不是硬重試。

回應標頭含義
X-RateLimit-Limit權杖桶容量(瞬間突發上限)
X-RateLimit-Remaining目前剩餘權杖
X-RateLimit-Reset下一枚權杖到達的時刻(epoch 秒),依此安排下次呼叫
X-Quota-Limit本月配額
X-Quota-Used本月已用
X-Quota-Remaining本月剩餘

429 quota_exceeded 是硬性阻斷,要到下個自然月(UTC)或升級後才恢復,重試沒有用;只有 429 rate_limited 值得依 Retry-After 等待後重試。

async function getRate(base, quote, attempt = 0) {
  const res = await fetch(
    `https://api.crestrate.com/v1/rate?base=${base}&quote=${quote}`,
    { headers: { "X-API-Key": process.env.CR_API_KEY } }
  );

  if (res.status === 429) {
    const body = await res.json();

    // quota_exceeded is a hard stop: retrying won't help, upgrade or wait for next month
    if (body.error === "quota_exceeded") {
      throw new Error(`Monthly quota exhausted: ${body.used}/${body.quota}`);
    }

    // only rate_limited is worth retrying, after Retry-After
    if (attempt < 3) {
      const wait = Number(res.headers.get("Retry-After") || 1);
      await new Promise(r => setTimeout(r, wait * 1000));
      return getRate(base, quote, attempt + 1);
    }
    throw new Error("rate limited");
  }

  // 503 no_rate: not enough valid sources. We return no price rather than a doubtful one.
  // Fall back to your own rate; never treat it as 0.
  if (res.status === 503) throw new Error("no reliable rate available");
  if (!res.ok) throw new Error(`HTTP ${res.status}`);
  return res.json();
}
別把 503 當成 0。 有效資料來源不足時,API 回傳 503 no_rate 而不是硬湊一個價格——這是刻意設計。呼叫方應退回自己的備援匯率或暫停下單,絕不能當成匯率為 0。

下一步