REST APIを設計する際、最も重要なのは一貫性のある命名規則と適切なHTTPステータスコードの使用です。場当たり的な設計は、後のメンテナンスやチーム開発において大きな負債となります。この記事では、命名とステータスコードについて私が現場で学んだ知識をメモしておきたいと思います。
命名規則の基本原則
1. バージョン管理を含める
http://example.com/api/v1/
APIは進化します。後方互換性を保ちながら新機能を追加するため、URLにバージョン番号を含めることが推奨されます。
2. 拡張子を含めない
❌ http://example.com/api/v1/articles.json
✅ http://example.com/api/v1/articles
レスポンス形式はContent-Typeヘッダーで指定します。URLに拡張子を含めると、同じリソースに対して複数のURLが存在することになり、RESTの原則に反します。
3. 名詞を使用し、動詞を避ける
❌ http://example.com/api/v1/getArticles
❌ http://example.com/api/v1/createArticle
✅ http://example.com/api/v1/articles
HTTPメソッド(GET, POST, PUT, DELETE)が動詞の役割を果たすため、URLには名詞のみを使用します。これにより、CRUDごとにURLを増やす必要がなくなります。
4. 複数形を使用する
✅ http://example.com/api/v1/articles
✅ http://example.com/api/v1/users
一覧取得と単一リソース取得で一貫性を保つため、複数形の使用が推奨されます。
5. URLのみで意味が明確になるようにする
適切に設計されたURLは、ドキュメントを見なくても何を表しているか推測できるべきです。
実践的なエンドポイント設計
基本的なCRUD操作
GET /api/v1/articles # 記事一覧の取得
POST /api/v1/articles # 新規記事の作成
GET /api/v1/articles/123 # ID:123の記事取得
PUT /api/v1/articles/123 # ID:123の記事更新
DELETE /api/v1/articles/123 # ID:123の記事削除
Laravelなどのフレームワークでは、これらのエンドポイントをコマンド一つで生成できます。
ネストされたリソースの設計
複雑な関係性を持つリソースは、階層的にURLを構成します。
GET /api/v1/customers/100/orders
# 顧客ID:100の注文一覧
GET /api/v1/customers/100/orders/200
# 顧客ID:100の注文ID:200の詳細
GET /api/v1/customers/100/orders/200/comments/2
# 顧客ID:100の注文ID:200に対するコメントID:2
注意点: ネストは2〜3階層までに留めましょう。それ以上深くなると、URLが複雑になりすぎて可読性が低下します。
検索・フィルタリング
クエリパラメータを使用して、リソースの絞り込みを行います。
GET /api/v1/articles?category=tech&status=published
GET /api/v1/articles?page=2&limit=20
GET /api/v1/articles?sort=-created_at
HTTPステータスコードの適切な使用
ステータスコードは、APIレスポンスの結果を明確に伝える重要な要素です。
成功系(2xx)
200 OK
一般的なリクエスト成功時に使用します。
GET /api/v1/articles/123
Response: 200 OK
{
"id": 123,
"title": "REST API設計ガイド",
"content": "..."
}
201 Created
新しいリソースが作成された場合に使用します。Locationヘッダーに作成されたリソースのURLを含めることが推奨されます。
POST /api/v1/articles
Response: 201 Created
Location: /api/v1/articles/124
{
"id": 124,
"title": "新規記事",
"created_at": "2025-11-08T10:00:00Z"
}
200で代用することもありますが、RESTの原則に従うなら201を使用するべきです。
204 No Content
リクエストは成功したが、返すコンテンツがない場合に使用します。削除操作などで有用です。
DELETE /api/v1/articles/123
Response: 204 No Content
クライアントエラー(4xx)
400 Bad Request
リクエスト自体が無効な場合に使用します。JSONのパースエラーや、必須パラメータの欠落などが該当します。
POST /api/v1/articles
Request: { "invalid_json": }
Response: 400 Bad Request
{
"error": "Invalid JSON format"
}
401 Unauthorized
認証が必要、または認証に失敗した場合に使用します。ユーザーが誰であるかを確認できない状態です。
GET /api/v1/articles
Response: 401 Unauthorized
{
"error": "Authentication required",
"message": "Please provide a valid API token"
}
Basic認証やトークン認証が必要なAPIで、認証情報がない、または無効な場合に返されます。
403 Forbidden
認証は成功しているが、そのリソースへのアクセス権限がない場合に使用します。
DELETE /api/v1/articles/123
Response: 403 Forbidden
{
"error": "Permission denied",
"message": "You do not have permission to delete this article"
}
認証(401)と認可(403)の違い:
- 401 Unauthorized: 「あなたは誰ですか?」→ログインが必要
- 403 Forbidden: 「あなたが誰かは分かるが、これはできません」→権限不足
404 Not Found
指定されたリソースが存在しない場合に使用します。
GET /api/v1/articles/999
Response: 404 Not Found
{
"error": "Resource not found",
"message": "Article with ID 999 does not exist"
}
422 Unprocessable Entity
リクエストの形式は正しいが、セマンティック(意味的)エラーがある場合に使用します。バリデーションエラーで最も一般的に使われます。
POST /api/v1/articles
Request: {
"title": "",
"content": "本文のみ"
}
Response: 422 Unprocessable Entity
{
"error": "Validation failed",
"details": {
"title": ["The title field is required"]
}
}
400 vs 422の使い分け:
- 400: リクエスト自体が無効(JSONパースエラー、必須パラメータ欠落など)
- 422: リクエストは解釈できるが、ビジネスルールに違反(バリデーションエラー)
サーバーエラー(5xx)
500 Internal Server Error
サーバー側で予期しないエラーが発生した場合に使用します。
GET /api/v1/articles
Response: 500 Internal Server Error
{
"error": "Internal server error",
"message": "An unexpected error occurred"
}
本番環境では、詳細なエラー情報を返さないようセキュリティに配慮しましょう。
503 Service Unavailable
サーバーが一時的に利用できない場合(メンテナンス中など)に使用します。
Response: 503 Service Unavailable
Retry-After: 3600
実践的なTips
1. ページネーション
大量のデータを返す場合は、ページネーションを実装しましょう。
GET /api/v1/articles?page=2&per_page=20
Response:
{
"data": [...],
"meta": {
"current_page": 2,
"total_pages": 10,
"total_count": 200
},
"links": {
"first": "/api/v1/articles?page=1",
"prev": "/api/v1/articles?page=1",
"next": "/api/v1/articles?page=3",
"last": "/api/v1/articles?page=10"
}
}
2. レート制限の情報提供
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 999
X-RateLimit-Reset: 1699430400
3. 一貫性のあるエラーレスポンス
すべてのエラーレスポンスで同じ構造を使用します。
{
"error": "error_code",
"message": "Human readable error message",
"details": {}
}
まとめ
REST API設計において、一貫性が最も重要です。
- URLは名詞の複数形を使用し、HTTPメソッドで操作を表現
- バージョン管理を含め、将来の拡張に備える
- 適切なステータスコードで結果を明確に伝える
- 認証(401)と認可(403)を正しく使い分ける
- バリデーションエラーには422を使用
- ドキュメントなしでも直感的に理解できるAPI設計を目指す
これらの原則に従うことで、開発者にとって使いやすく、メンテナンスしやすいAPIを構築できます。チーム内でルールを統一し、一貫性のあるAPI設計を心がけましょう。