alltools.one
API
2025-06-05
7 min
alltools.one Team
APIRESTJSONResponse FormatBest Practices

APIレスポンスフォーマット:一貫性のあるAPIのベストプラクティス

一貫性のないAPIレスポンスは、フロントエンド開発者から最も多い不満の一つです。すべてのエンドポイントが異なる形式でデータを返すと、クライアントコードは特殊なケースだらけになります。一貫したレスポンスフォーマットは開発者体験を向上させ、バグを減らし、APIを自己文書化するものにします。

レスポンスエンベロープ

すべてのレスポンスを一貫した構造でラップします:

成功(単一リソース)

{
  "data": {
    "id": "user_123",
    "name": "Alice",
    "email": "alice@example.com",
    "createdAt": "2024-01-15T10:30:00Z"
  },
  "meta": {
    "requestId": "req_abc123"
  }
}

成功(コレクション)

{
  "data": [
    { "id": "user_123", "name": "Alice" },
    { "id": "user_456", "name": "Bob" }
  ],
  "meta": {
    "total": 142,
    "page": 1,
    "perPage": 20,
    "requestId": "req_def456"
  }
}

エラー

{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Request validation failed",
    "details": [
      { "field": "email", "message": "Invalid email format" }
    ]
  },
  "meta": {
    "requestId": "req_ghi789"
  }
}

重要な原則:クライアントは常にトップレベルで data または error を確認します。成功データとエラー情報を同じレスポンスに混在させてはいけません。

レスポンスフォーマットの検証にはJSONバリデーターをお使いください。

HTTPステータスコード

ステータスコードを正しく使いましょう — クライアントが最初に確認するものです:

成功コード

コード使用場面
200 OKGETの成功、PUT/PATCHの成功
201 Createdリソースを作成したPOST
204 No ContentDELETEの成功(ボディなし)

クライアントエラーコード

コード使用場面
400 Bad Request不正なリクエスト構文
401 Unauthorized認証の欠落または無効
403 Forbidden認証済みだが権限なし
404 Not Foundリソースが存在しない
409 Conflictリソース状態の競合(重複)
422 Unprocessable構文は正しいがセマンティックエラー
429 Too Many Requestsレート制限超過

サーバーエラーコード

コード使用場面
500 Internal Server Error予期しないサーバー障害
502 Bad Gateway上流サービスの障害
503 Service Unavailable一時的な過負荷またはメンテナンス

エラーレスポンスの設計

良いエラーレスポンスは開発者が素早くデバッグするのに役立ちます:

{
  "error": {
    "code": "RESOURCE_NOT_FOUND",
    "message": "User with ID 'user_999' not found",
    "details": [],
    "documentationUrl": "https://api.example.com/docs/errors#RESOURCE_NOT_FOUND"
  },
  "meta": {
    "requestId": "req_xyz789",
    "timestamp": "2024-01-15T10:30:00Z"
  }
}

ルール

  • code は機械可読(定数文字列、HTTPステータスではない)
  • message は人間可読(クライアントを壊さずに変更可能)
  • details はバリデーション失敗時のフィールドレベルエラーを提供
  • requestId はサポートチームがログでリクエストを追跡可能にする

ページネーションパターン

オフセットベース

シンプルで任意のページへのジャンプをサポート:

{
  "data": ["..."],
  "meta": {
    "page": 2,
    "perPage": 20,
    "total": 142,
    "totalPages": 8
  },
  "links": {
    "first": "/api/users?page=1&per_page=20",
    "prev": "/api/users?page=1&per_page=20",
    "next": "/api/users?page=3&per_page=20",
    "last": "/api/users?page=8&per_page=20"
  }
}

カーソルベース

リアルタイムデータや大規模データセットに適しています:

{
  "data": ["..."],
  "meta": {
    "hasNext": true,
    "hasPrev": true
  },
  "links": {
    "next": "/api/users?cursor=eyJpZCI6MTQzfQ&limit=20",
    "prev": "/api/users?cursor=eyJpZCI6MTIzfQ&limit=20&direction=prev"
  }
}

日時

常にISO 8601形式でタイムゾーン情報を含めてください:

{
  "createdAt": "2024-01-15T10:30:00Z",
  "updatedAt": "2024-01-15T14:22:33+00:00",
  "expiresAt": "2024-12-31T23:59:59Z"
}

以下は使用しないでください:

  • Unixタイムスタンプ(曖昧:秒かミリ秒か?)
  • タイムゾーンなしのローカル日付
  • MM/DD/YYYYなどのカスタムフォーマット

タイムスタンプの処理について詳しくはUnixタイムスタンプガイドをご覧ください。

Null vs 存在しないフィールド

2つの一般的なアプローチ:

nullを含める(明示的):

{ "name": "Alice", "avatar": null, "bio": null }

存在しないフィールドを省略(疎):

{ "name": "Alice" }

推奨事項:API内で一貫性を保ちましょう。明示的なnullは型付き言語に適しています(クライアントがフィールドの存在を知ることができます)。疎な方法は帯域幅が制限された環境に適しています。

レスポンスのバージョニング

レスポンスフォーマットが変更される場合、APIをバージョニングします:

GET /api/v2/users/123

バージョニングが必要な破壊的変更:

  • フィールドの削除
  • フィールドの型変更
  • フィールドの名前変更
  • レスポンスエンベロープ構造の変更

バージョニング不要の非破壊的変更:

  • 新しいフィールドの追加
  • 新しいエンドポイントの追加
  • 新しいenum値の追加

FAQ

成功レスポンスをdataキーでラップすべきか、リソースを直接返すべきか?

data ラッパーを使用すると、すべてのレスポンスに一貫した構造を提供し、データと並んでメタデータ、ページネーション、リンクのための余地を残せます。リソースを直接返す方が単一リソースのエンドポイントではシンプルです。ほとんどの最新のAPIは一貫性のためにラッパーアプローチを使用しています。

バッチ操作で部分的な失敗をどう処理すべきか?

成功と失敗の両方をdataオブジェクトに含む200レスポンスを返します。207 Multi-Status(WebDAV)を使用することもできますが、REST APIではあまり一般的ではありません。

関連リソース

Published on 2025-06-05
API Response Formats: Best Practices for Consistent APIs | alltools.one