HTTP statusと対応
| Status | Meaning | Action |
|---|---|---|
| 400 | filter、field、sort、cursorなどが無効 | requestを修正。自動retryしない |
| 401 | API Keyが無効または不足 | 認証情報を確認。自動retryしない |
| 403 | Referer/IP/権限/利用範囲により拒否 | API Keyの制限と契約を確認 |
| 404 | routeまたはresourceが存在しない | pathを確認 |
| 405 | HTTP methodが不正 | GETへ修正 |
| 406 | 要求したresponse formatを返せない | Acceptを確認 |
| 429 | API Keyの利用上限を超過 | reset情報に従って待機 |
| 500 | 内部error | 上限付きbackoffで再試行 |
| 503 | 一時的に利用できない | 上限付きbackoffで再試行 |
検索結果が0件の場合
条件に一致するデータがない場合もrequestは成功です。404ではなく、HTTP 200と空のdataが返ります。
{
"data": [],
"size": 0,
"limit": 10,
"hasNext": false,
"hasPrev": false,
"version": "dataset-version"
}Application error schema
{
"httpStatusCode": 400,
"code": "invalidParameter",
"message": "...",
"validationErrors": [
{
"message": "...",
"paramName": "filter",
"invalidValue": "..."
}
]
}401、403、429のbodyは、このapplication error schemaと同じとは限りません。clientはまずHTTP statusを判定してください。human-readable messageの完全一致に依存しないでください。
Rate limit headers
利用できるwindowはAPI Keyのplan設定により異なります。header名はcase-insensitiveです。
| Header | Meaning | Unit |
|---|---|---|
RateLimit-Limit | 最も制約の強いwindowの上限 | request count |
RateLimit-Remaining | 同windowの残数 | request count |
RateLimit-Reset | 同windowがresetするまで | seconds |
Retry-After | 429後、再試行まで待つ時間 | seconds |
X-RateLimit-Limit-Second | 1秒windowの上限(設定時) | request count |
X-RateLimit-Remaining-Second | 1秒windowの残数(設定時) | request count |
X-RateLimit-Limit-Day | 1日windowの上限(設定時) | request count |
X-RateLimit-Remaining-Day | 1日windowの残数(設定時) | request count |
429では連続送信しない
429を受けたらrequestを止め、返されたreset情報に従ってから再試行してください。
Bounded retry
429と一時的な5xxだけを対象に、試行回数に上限を設けたexponential backoffとjitterを使用します。400、401、403はrequestまたは設定を修正するまでretryしません。
async function requestWithBackoff(request, maxAttempts = 3) {
for (let attempt = 0; attempt < maxAttempts; attempt += 1) {
const response = await request();
if (response.ok) return response;
const retryable = response.status === 429 || response.status >= 500;
if (!retryable || attempt === maxAttempts - 1) return response;
const retryAfter = Number(response.headers.get("Retry-After"));
const baseMs = Number.isFinite(retryAfter)
? retryAfter * 1000
: Math.min(1000 * 2 ** attempt, 30000);
const jitterMs = Math.random() * 250;
await new Promise((resolve) => setTimeout(resolve, baseMs + jitterMs));
}
}