クイックスタート

ゼロから最初の呼び出し成功まで、通常 2 分もかかりません。

ベース URL: https://api.crestrate.com/v1

API キーを取得する

登録後、ダッシュボードでキーを作成します。無料プランは月 1,000 リクエストまで、クレジットカードは不要です。 キーの全文は一度しか表示されません。すぐにシークレット管理ツールに保存してください。

レートを照会する

base は商品の価格通貨、quote はお客様の支払通貨です。返される rate は「base 1 単位が quote でいくらか」を表し、そのまま金額計算に使えます。

/v1 へのリクエストにはすべて X-API-Key または Authorization: Bearer でキーが必要です。キーがない場合は 401 api_key_required が返ります。

curl -H "X-API-Key: $CR_API_KEY" \
  "https://api.crestrate.com/v1/rate?base=JPY&quote=HKD"
レートと金額は JSON の数値ではなく文字列です。 JSON の数値は 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次のトークンが補充される時刻(エポック秒)。次の呼び出しはこれに合わせてください
X-Quota-Limit月間クォータ
X-Quota-Used今月の使用量
X-Quota-Remaining今月の残り

429 quota_exceeded は翌暦月(UTC)かアップグレードまで解除されないため、再試行しても意味がありません。再試行すべきなのは Retry-After 後の 429 rate_limited だけです。

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 をゼロとして扱わないでください。 有効なソースが足りないとき、API は無理にレートを作らず 503 no_rate を返します。これは意図的な設計です。自前のフォールバックレートを使うか注文を一時停止し、決してレート 0 として扱わないでください。

次のステップ