エラーとレート制限
すべてのエンドポイントは、機械可読なコードとリクエストIDを含む共通の形式で失敗を報告します。
エラーレスポンス
呼び出しが失敗するとsuccess: falseが返されます。codeは変更されない安定した値でプログラム向け、errorは人が読むための短い英語メッセージ、request_idは当社のログ上でその呼び出しを特定するIDです。入力に問題がある場合は、paramに該当するパラメータ名が入ります。
実際の例
以下は、このページのレンダリング時にAPIから取得したライブのレスポンスです。
{
"success": false,
"error": "coin required",
"code": "INVALID_PARAM",
"request_id": "cb-mwefrn7e-f4d85d519d"
}{
"success": false,
"code": "NOT_FOUND",
"error": "unknown endpoint: GET /api/this-endpoint-does-not-exist",
"request_id": "cb-mwefrn7e-de3e82c2fc"
}エラーコード
| コード | HTTP | 意味 | 対処方法 |
|---|---|---|---|
| INVALID_PARAM | 400 | 必須パラメータが不足しているか、値が受け付けられません。該当するパラメータが特定できる場合は、`param`にその名前が入ります。 | そのまま再試行せず、リクエストを修正してください。 |
| UNAUTHORIZED | 401 | `CB-API-KEY`ヘッダーが送信されましたが、キーが不明か失効済みです。公開データにキーは不要です。ヘッダーを外すか、有効なキーを使用してください。 | そのまま再試行しないでください。 |
| FORBIDDEN | 403 | このルートは公開APIに含まれません(内部用またはアカウント専用)。 | 再試行しないでください。 |
| NOT_FOUND | 404 | 不明なルートであるか、リクエストされた銘柄 / 取引所 / ファンドが存在しません。 | 再試行せず、パスと識別子をカタログと照合してください。 |
| RATE_LIMITED | 429 | リクエスト数が1分あたりの上限を超えました。`Retry-After`に待機すべき秒数が示されます。 | `Retry-After`で示された時間だけ待ってから、バックオフ付きで再試行してください。 |
| INTERNAL | 500 | 予期しないサーバーエラーです。メッセージは意図的に汎用的な内容にしています。報告の際は`request_id`を引用してください。 | 数秒後に1回だけ再試行してください。解消しない場合は、リクエストIDを添えて報告してください。 |
| UPSTREAM_FAILED | 503 | このエンドポイントの背後にあるデータソースが時間内に応答しませんでした。鮮度切れの数値や代替の数値を代わりに返すことはありません。 | バックオフ付きで再試行し、ステータスページを確認してください。 |
| UNAVAILABLE | 501 / 503 | データセットが一時的に準備できていない(キャッシュのウォームアップ中)か、このエンドポイントに適法な公開ソースがまだありません。 | 時間をおいて再試行してください。仕様上利用できないエンドポイントは、カタログに明示されています。 |
| REQUEST_FAILED | 200 | 一部の古いエンドポイントは、HTTP 200で`success: false`を返します。HTTPステータスだけでなく、必ず`success`を確認してください。 | メッセージによって異なります。失敗したリクエストとして扱ってください。 |
リクエストID
各レスポンスにはX-Request-Idヘッダーが付与されます。失敗レスポンスでは、同じ値がボディのrequest_idにも含まれます。短時間のエッジキャッシュから返されたレスポンスは、そのレスポンスを生成したリクエストのIDをそのまま返します。そのため、連続する呼び出しでIDが同一であれば、キャッシュされたコピーを受け取ったことを意味します。
レート制限
制限は1分単位で適用され、匿名の呼び出しではIPアドレスごと、有効なCB-API-KEYヘッダーを送信した場合はキーごとにカウントされます。上限は毎分1200リクエストです。/api/coin-icon配下のアイコンリクエストはカウントされません。
レート制限ヘッダー
| 名前 | 説明 |
|---|---|
| X-Request-Id | このリクエストの識別子。バグ報告の際に引用してください。 |
| X-RateLimit-Limit | 現在の1分間ウィンドウで許可されるリクエスト数。 |
| X-RateLimit-Remaining | 現在のウィンドウで残っているリクエスト数。 |
| X-RateLimit-Reset | ウィンドウがリセットされるUnix時刻(秒)。 |
| Retry-After | HTTP 429とともに送信されます。再試行までに待機する秒数です。 |
| X-Cache | サーバー側レスポンスキャッシュの状態。HIT、STALE、MISSのいずれかです。 |
制限を超えた場合
APIはHTTP 429とコードRATE_LIMITEDを返します。Retry-Afterで示された秒数だけ待ってから再試行してください。エンドポイントのキャッシュTTLより短い間隔でポーリングしても、同じキャッシュ済みレスポンスが返されます。ポーリング間隔は、各リファレンスページに記載のTTLに合わせてください。
バックオフ付きの再試行
async function getJson(url, tries = 4) {
for (let i = 0; i < tries; i++) {
const res = await fetch(url);
if (res.status === 429 || res.status >= 500) {
const wait = Number(res.headers.get("Retry-After")) || 2 ** i;
await new Promise((r) => setTimeout(r, wait * 1000));
continue;
}
const body = await res.json();
if (body.success === false) {
throw new Error(body.code + ": " + body.error + " (" + body.request_id + ")");
}
return body;
}
throw new Error("gave up after " + tries + " attempts");
}データがないことはエラーではない
パラメータは有効でも、そのデータに適法な公開ソースがない場合、呼び出しはHTTP 200で成功します。値のフィールドはnull、meta.qualityはUNAVAILABLEとなり、coverage.unavailableに理由が示されます。ダッシュとして表示し、0には変換しないでください。
鮮度切れのデータ
コレクターに遅れが生じた場合、エンドポイントは最後に保存された値をmeta.is_stale: true付きで返し続けます。利用可能ウィンドウを過ぎると、その値は集計値から除外され、coverage.stale_excludedに記載されます。