Claudeに90%書いてもらいつつ、シンプルにした好みのREST API ガイドライン
マークダウンが反映されなくてつらいけど面倒だからそのまま貼る。
———
# REST API設計規約
## 1. 基本原則
### 1.1 RESTの基本原則に従う
- リソース指向設計
- ステートレス通信
- 統一インターフェース
- 自己記述型メッセージ
### 1.2 シンプルさを重視する
- 複雑な設計よりもシンプルな設計を優先する
- 直感的で理解しやすいAPIを設計する
## 2. リソース設計
### 2.1 リソース名
- 名詞を使用し、複数形で表現する(例: `/users`, `/products`)
- リソース名は小文字のみ使用し、ハイフン(-)で単語を区切る
- 特殊文字やスペースは使用しない
### 2.2 リソースの階層
- 親子関係がある場合は階層構造で表現する(例: `/users/{userId}/orders`)
- 階層は最大で3〜4レベルまでに制限する
### 2.3 リソースの識別
- リソースIDはURIパスで指定する(例: `/users/{userId}`)
- IDはシステム内で一意であること
## 3. HTTP動詞の利用
### 3.1 標準的なHTTP動詞の使用
| 動詞 | 用途 | 例 |
|———|———|———|
| GET | リソースの取得 | `GET /users/{userId}` |
| POST | リソースの作成 | `POST /users` |
| PUT | リソースの完全更新 | `PUT /users/{userId}` |
| PATCH | リソースの部分更新 | `PATCH /users/{userId}` |
| DELETE | リソースの削除 | `DELETE /users/{userId}` |
#### PUTとPATCHの違い
- **PUT**: リソース全体を置き換える完全更新。クライアントはリソースの全フィールドを送信する必要がある。送信されなかったフィールドは初期値または null にリセットされる。
- **PATCH**: リソースの一部のみを更新する部分更新。クライアントは変更したいフィールドのみを送信すればよい。送信されなかったフィールドは変更されない。
- 例: ユーザーの名前だけを更新する場合
- PUT: すべての属性を送信する必要がある(`{“name”: “新しい名前”, “email”: “既存のメール”, ...}`)
- PATCH: 変更する属性のみ送信(`{“name”: “新しい名前”}`)
### 3.2 動詞の安全性と冪等性
- GETは安全であり冪等である(何度実行しても同じ結果、副作用なし)
- PUTとDELETEは冪等である(何度実行しても同じ状態になる)
- POSTは安全でも冪等でもない
## 4. クエリパラメータ
### 4.1 フィルタリング
- フィルタリングはクエリパラメータで行う(例: `/users?status=active`)
- 複数の条件はアンパサンド(&)で連結する(例: `/users?status=active&role=admin`)
### 4.2 ソート
- ソートはsortパラメータで指定する(例: `/users?sort=lastName`)
- 昇順/降順はプレフィックス+/-で指定する(例: `/users?sort=-createdAt`)
### 4.3 ページネーション
- トークンベースのページネーションを使用する
- 例: `/users?limit=20&page_token=eyJvZmZzZXQiOjQwfQ==`
- 次ページのトークンはレスポンスに含める
- デフォルト値と最大値を設定する
### 4.4 フィールド選択
- 取得するフィールドをfieldsパラメータで指定できる(例: `/users?fields=id,name,email`)
- フィールド選択はオプション機能であり、実装は必須ではない
## 5. レスポンス設計
### 5.1 ステータスコード
| コード | 説明 | 使用例 |
|————|———|————|
| 200 | OK | リクエスト成功(GET, PUT, PATCH) |
| 201 | Created | リソース作成成功(POST) |
| 204 | No Content | リクエスト成功、返すコンテンツなし(DELETE) |
| 400 | Bad Request | リクエスト形式が不正 |
| 401 | Unauthorized | 認証が必要 |
| 403 | Forbidden | 認証済みだが権限がない |
| 404 | Not Found | リソースが存在しない |
| 429 | Too Many Requests | レート制限超過 |
| 500 | Internal Server Error | サーバー内部エラー |
### 5.2 エラーレスポンス形式
```json
{
“error”: {
"code": "RESOURCE_NOT_FOUND",
"message": "指定されたユーザーは存在しません"
}
}
```
### 5.3 成功レスポンス形式
- 単一リソース
```json
{
“id”: “user123”,
“name”: “山田太郎”,
“email”: “yamada@example.com”,
“createdAt”: “2023-01-15T12:00:00Z”
}
```
- リソースコレクション
```json
{
“items”: [
{
"id": "user123",
"name": "山田太郎"
},
{
"id": "user456",
"name": "佐藤次郎"
}
],
“metadata”: {
"totalCount": 2500,
"returnedCount": 2,
"limit": 2,
"nextPageToken": "eyJvZmZzZXQiOjJ9"
}
}
```
### 5.4 POSTメソッドのレスポンス規則
- リソース作成(Create)の場合:
- ステータスコード: 201 Created
- レスポンスボディ: 作成されたリソースを返す(少なくともidを含める)
- 例: `POST /users` → 新しいユーザーオブジェクト(idを含む)
```json
{
“id”: “user789”,
“name”: “鈴木花子”,
“email”: “suzuki@example.com”,
“createdAt”: “2023-01-15T12:00:00Z”
}
```
- アクション実行の場合:
- ステータスコード: 200 OK または 204 No Content
- レスポンスボディ: アクションの結果または空(204の場合)
- 例: `POST /users/{userId}:reset-password` → 空のレスポンスまたは結果オブジェクト
## 6. バージョニング
### 6.1 バージョニング方式
- URIパスでバージョンを指定する(例: `/v1/users`)
- メジャーバージョンのみをURIに含める
### 6.2 後方互換性
- 既存のAPIに対する破壊的変更はしない
- 機能追加は後方互換性を保持する
- 破壊的変更が必要な場合は新しいバージョンを作成する
## 7. セキュリティ
### 7.1 認証・認可
- APIキーまたはOAuth 2.0を使用する
- 認証情報はHTTP Authorizationヘッダで送信する
- すべてのエンドポイントでTLSを使用する
### 7.2 レート制限
- APIアクセスにレート制限を設けることはオプションである
- レート制限を実装する場合、制限状態を以下のヘッダで通知する
- X-RateLimit-Limit: 時間枠あたりの最大リクエスト数
- X-RateLimit-Remaining: 現在の時間枠での残りリクエスト数
- X-RateLimit-Reset: レート制限のリセット時間(Unix時間)
### 7.3 入力バリデーション
- すべてのユーザー入力を検証する
- 入力検証エラーは400 Bad Requestで返す
- 詳細なエラーメッセージを提供する
## 8. パフォーマンスとキャッシング
### 8.1 キャッシュ制御
- Cache-Controlヘッダを適切に設定する
- ETagを利用して条件付きリクエストをサポートする
### 8.2 圧縮
- 大きなレスポンスはgzipで圧縮する
- Accept-Encodingヘッダで対応する圧縮形式を確認する
## 9. 日付と時刻
### 9.1 形式
- 日付と時刻はISO 8601形式を使用する(例: `2023-04-01T13:45:30Z`)
- タイムゾーンはUTCを使用し、末尾に「Z」を付ける
## 10. ドキュメント
### 10.1 API仕様
- OpenAPI(Swagger)仕様に従ってAPIをドキュメント化する
- 各エンドポイントの説明、パラメータ、レスポンスを詳細に記述する
## 12. 複雑な操作
### 12.1 一括操作
- 一括作成/更新はコレクションに対するPOST/PUTで行う
- レスポンスには各項目の処理結果を含める
### 12.2 非RESTful操作
- リソース指向で表現できない操作はカスタムアクションとして実装する
- コロン構文を使用する: `{リソース}:{Action}`
- 例: `/users/{userId}:reset-password`(POST)