エラーとレスポンス
すべてのパブリックAPIエンドポイントは予測可能なレスポンス形式を返します。エラーはボディ内に安定した機械可読コードを運ぶため、英語を解析することなく分岐できます。
レスポンスエンベロープ
成功レスポンスはリソース (またはリソースのリスト) を直接返します。トップレベルのラッパーはありません — クライアントは型付きモデルに直接デシリアライズできます:
GET /api/public/v1/org
{
"id": "e188fc87-…",
"name": "Acme Corp",
"plan": "growth",
…
}失敗レスポンスは、errorコードを唯一の必須フィールドとする小さな統一形式を使用します。オプションフィールドは呼び出しを修正するのに役立つコンテキストを提供します:
{
"error": "insufficient_scope",
"required": "assignments:write",
"present": ["assignments:read", "users:read"]
}ステータスコードリファレンス
| ステータス | 発生する場面 | 対処方法 |
|---|---|---|
200 | リクエストが成功しました。ボディにはリソースまたは確認メッセージが含まれます。 | ボディを処理します。 |
400 | 不正なリクエスト: 必須フィールドの欠落、無効なenum値、ボディが大きすぎる、解析不能なJSON。 | クライアントリクエストを修正してください — 同じペイロードで再試行しないでください。 |
401 | トークンが欠落、不正、取り消し済み、または期限切れです。 | Authorizationヘッダーを確認してください。トークンが取り消されている場合はローテーションしてください。 |
403 | トークンは有効ですが、必要なスコープが不足しています。 | 管理UIでスコープを追加してください。レスポンスには正確なスコープ名が含まれます。 |
404 | リソースが存在しないか、別の組織に属しています。 | 親コレクションを再取得してください。組織をまたいで古いIDをたどらないでください。 |
409 | 競合 — 例: メールアドレスがすでに使用されています。 | 操作が冪等であれば成功として扱ってください。 |
413 | リクエストボディがエンドポイントごとの上限を超えました。ハードオーバーフロー時にKestrelによって返されます。SARIFエンドポイントは、宣言されたContent-Lengthが10 MBを超える場合にこれを400 body_too_largeとしても返します。 | ペイロードをトリムしてください。SARIFの場合、ツール1つずつ検出結果を増分取り込みしてください。 |
429 | このAPIキーでレート制限に達しました。 | Retry-Afterに従ってください。レート制限を参照してください。 |
5xx | サーバー側の問題。 | 指数関数的バックオフで再試行してください。レスポンスX-Request-Idヘッダーを取得し、サポートチケットで引用してください。 |
エラーコード
errorフィールドはバージョン間で安定しています — 同じステータスが異なるコードを運ぶ可能性があるため、HTTPステータスではなくこれをクライアントコードで分岐してください:
| コード | ステータス | 意味 |
|---|---|---|
unauthorized | 401 | リクエストに使用可能なベアラートークンがありません。 |
insufficient_scope | 403 | トークンは問題ありませんが、スコープが欠落しています。レスポンスにはrequiredとpresentが含まれます。 |
rate_limited | 429 | 上限を超過しました。Retry-Afterヘッダーを参照してください。 |
user_not_found | 404 | ユーザーIDが存在しないか、あなたの組織にありません。 |
team_not_found | 404 | チームIDが存在しないか、あなたの組織にありません。 |
assignment_not_found | 404 | 課題IDが存在しないか、あなたの組織にありません。 |
empty_body | 400 | ボディが必要な場所でPOSTまたはPATCHがボディなしで送信されました。 |
body_too_large | 400 / 413 | リクエストボディがエンドポイント上限を超えました。SARIFは宣言されたContent-Lengthが大きすぎる場合、ボディにmaxBytesを含めて400として発行します。Kestrelは実際にボディがオーバーランしたときに素の413を発行します。 |
リクエストID
すべてのレスポンスはX-Request-Idヘッダー (UUID v4) を運びます。クライアント側でキャプチャし、サポートリクエストに含めてください — 失敗した呼び出しの正確なサーバー側トレースを引き出すことができます。5xxレスポンスの場合、リクエストIDは診断への最速の道です。
検証エラー
POSTとPATCHボディの検証失敗は、最初の失敗ルールを記述する平坦なerrorとともに400を返します。複数フィールドの検証表面化はv1の一部ではありません — 最初に報告されたフィールドを修正して再試行してください。将来のバージョンではフィールドごとの詳細が追加される可能性がありますが、トップレベルのerrorコントラクトは維持されます。
エラーでの分岐 — 例
const res = await fetch(url, { headers });
if (res.ok) return res.json();
const body = await res.json().catch(() => ({}));
switch (body.error) {
case 'rate_limited':
return retryWithBackoff(url);
case 'insufficient_scope':
throw new Error(`API key missing scope: ${body.required}`);
case 'unauthorized':
throw new Error('API key revoked or invalid — rotate the secret');
default:
throw new Error(`API error ${res.status}: ${body.error || 'unknown'}`);
}