0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

RESTAPIの命名とステータスコードについて

Posted at

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設計を心がけましょう。

参考リンク

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?