エラーハンドリング
エラーレスポンス形式
すべてのAPIエラーは、適切なHTTPステータスコードと一貫したJSON構造に従います:
{
"error": {
"code": "ERROR_CODE",
"message": "Human-readable description of what went wrong"
}
}code フィールドは安定したマシンリーダブルな識別子で、エラーハンドリングロジックで使用できます。message フィールドは追加のコンテキストを提供し、同じエラーコードでも発生ごとに異なる場合があります。
エラーカテゴリ
認証エラー (401)
リクエストを認証できない場合に返されます。
| コード | 説明 |
|---|---|
UNAUTHORIZED | Authorization ヘッダーが欠落、不正、または無効なトークンを含んでいます。 |
KEY_EXPIRED | APIキーは有効でしたが、有効期限を過ぎています。続行するには新しいキーを作成してください。 |
{
"error": {
"code": "UNAUTHORIZED",
"message": "Missing or invalid Authorization header"
}
}認可エラー (403)
認証済みユーザーがリクエストされたリソースにアクセスする権限を持っていない場合に返されます。
| コード | 説明 |
|---|---|
FORBIDDEN | 別のユーザーに属するリソースにアクセスまたは変更しようとしています(例:他のユーザーのAPIキーの無効化)。 |
未検出エラー (404)
リクエストされたリソースが存在しない場合に返されます。
| コード | 説明 |
|---|---|
NOT_FOUND | URL内で識別されたリソース(抽出、APIキーなど)が存在しないか、削除されています。 |
バリデーションエラー (400)
リクエストボディまたはパラメータが無効な場合に返されます。
| コード | 説明 |
|---|---|
VALIDATION_ERROR | リクエストボディがスキーマバリデーションに失敗しました。message フィールドにどのフィールドが無効かが記述されます。 |
MAX_KEYS_REACHED | アクティブなAPIキーの上限10個に達しました。新しいキーを作成する前に、既存のキーを無効化してください。 |
{
"error": {
"code": "MAX_KEYS_REACHED",
"message": "Maximum of 10 active API keys allowed"
}
}レート制限エラー (429)
使用量制限を超過した場合に返されます。
| コード | 説明 |
|---|---|
USAGE_LIMIT_EXCEEDED | 月間抽出制限に達しました。プランをアップグレードするか、次の請求期間まで待ってください。 |
{
"error": {
"code": "USAGE_LIMIT_EXCEEDED",
"message": "Monthly extraction limit reached (25/25). Upgrade your plan for more extractions."
}
}サーバーエラー (500)
サーバー側で予期しない問題が発生した場合に返されます。
| コード | 説明 |
|---|---|
INTERNAL_ERROR | 予期しないサーバーエラーが発生しました。これらは自動的にログに記録され、調査されます。 |
EXTRACTION_FAILED | ドキュメントからデータを抽出する際にAI処理パイプラインでエラーが発生しました。ドキュメントが破損しているか、読み取れないか、サポートされていない形式の可能性があります。 |
リトライ可能なエラー
すべてのエラーがリトライすべきとは限りません。以下に分類を示します:
| コード | リトライ可能 | アクション |
|---|---|---|
INTERNAL_ERROR | はい | 指数バックオフでリトライ |
EXTRACTION_FAILED | はい | リトライ -- AIが異なる結果を生成する場合があります。持続する場合はドキュメントの品質を確認 |
USAGE_LIMIT_EXCEEDED | いいえ | プランをアップグレードするか、次の請求期間まで待つ |
UNAUTHORIZED | いいえ | 認証情報を修正 |
KEY_EXPIRED | いいえ | 新しいAPIキーを作成 |
FORBIDDEN | いいえ | 所有していないリソースにアクセスしている |
NOT_FOUND | いいえ | リソースが存在しない -- IDを確認 |
VALIDATION_ERROR | いいえ | リクエストボディを期待されるスキーマに合わせて修正 |
MAX_KEYS_REACHED | いいえ | 新しいキーを作成する前に既存のキーを無効化 |
リトライ戦略
リトライ可能なエラーの場合、サーバーへの過負荷を避けるために指数バックオフを使用します。以下は再利用可能な実装です:
interface ApiResponse<T> {
data?: T;
error?: { code: string; message: string };
}
async function fetchWithRetry<T>(
url: string,
options: RequestInit,
maxRetries = 3,
): Promise<ApiResponse<T>> {
let lastError: Error | null = null;
for (let attempt = 0; attempt <= maxRetries; attempt++) {
try {
const response = await fetch(url, options);
const body = await response.json();
if (response.ok) {
return body as ApiResponse<T>;
}
const errorCode = body?.error?.code;
// サーバーエラーのみリトライ
if (
(errorCode === "INTERNAL_ERROR" || errorCode === "EXTRACTION_FAILED") &&
attempt < maxRetries
) {
const delayMs = 1000 * Math.pow(2, attempt); // 1s, 2s, 4s
console.log(`Retrying in ${delayMs}ms (attempt ${attempt + 1}/${maxRetries})...`);
await new Promise((resolve) => setTimeout(resolve, delayMs));
continue;
}
// リトライ不可能なエラー -- 即座に返す
return body as ApiResponse<T>;
} catch (err) {
lastError = err as Error;
if (attempt < maxRetries) {
const delayMs = 1000 * Math.pow(2, attempt);
await new Promise((resolve) => setTimeout(resolve, delayMs));
continue;
}
}
}
throw lastError ?? new Error("Max retries exceeded");
}使用方法:
const result = await fetchWithRetry<ExtractionResult>(
"https://api.docmap.io/v1/extractions/run",
{
method: "POST",
headers: {
Authorization: `Bearer ${apiKey}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
templateId: "tmpl_abc123",
fileName: "invoice.pdf",
pdfBase64: encodedPdf,
mimeType: "application/pdf",
}),
},
);
if (result.error) {
console.error(`Extraction failed: [${result.error.code}] ${result.error.message}`);
} else {
console.log("Extracted data:", result.data);
}ベストプラクティス
まずHTTPステータスコードを確認する。
2xxステータスは成功を意味し、それ以外はエラーです。ステータスを確認せずにレスポンスボディにdataフィールドがあると想定しないでください。codeフィールドでエラーボディを解析する。 制御フローではmessageではなくcodeを使用してください。エラーメッセージは時間とともに変わる可能性がありますが、エラーコードは安定しています。特定のエラーコードを処理する。
USAGE_LIMIT_EXCEEDEDやKEY_EXPIREDなどの既知のコードに分岐して、ユーザーへのターゲットメッセージの表示や特定のワークフローのトリガーを行います。不明なエラーをログに記録する。 明示的に処理していないエラーコードに遭遇した場合、デバッグのために完全なレスポンス(ステータスコード、エラーコード、メッセージ)をログに記録してください。
4xxエラーをリトライしない。 認証、認可、バリデーション、未検出エラーは自然に解決されません。リトライする前に根本的な問題を修正してください。
リトライ回数に制限を設ける。 無限にリトライしないでください。指数バックオフ(1秒、2秒、4秒)での3回のリトライは、サーバーエラーに対する妥当なデフォルトです。
