HTTPステータスコードは仕様書では番号と短い説明しか書かれていませんが、実際のAPI設計では「200でいいのか201を返すべきか」「400と422はどう違うのか」「401と403はいつ使い分けるのか」といった迷いが頻繁に生じます。この記事では、REST APIを設計・実装する上でよく使う10個のステータスコードを、実際のユースケースと判断基準とともに解説します。
2xx:成功系コードの使い分け
`200 OK` はGET・PUT・PATCHなど汎用的な成功レスポンスです。`201 Created` はPOSTでリソースが新規作成されたときに使い、`Location` ヘッダーに作成されたリソースのURLを付けるのがベストプラクティスです。`204 No Content` はDELETE成功時やPATCHでレスポンスボディが不要な場合に使います。204を返す場合はボディを空にする必要があり、ボディを付けると仕様違反になるため注意が必要です。`202 Accepted` はリクエストを受け付けたが処理が非同期で行われる場合に使います。バックグラウンドジョブのキューイングやメール送信などで有効で、`Location` ヘッダーに処理状況を確認できるエンドポイントを示すと親切です。
400 vs 422:バリデーションエラーの適切な使い分け
`400 Bad Request` と `422 Unprocessable Content` はどちらもクライアントのエラーですが、意味が異なります。400はリクエスト自体が不正な場合(JSONの構文エラー、必須パラメータの欠落、型の根本的な誤り)に使います。422はリクエストの構文は正しいが、内容が処理できない場合(メールアドレスの形式エラー、年齢が負の値、存在しないカテゴリIDの指定)に使います。シンプルなAPIでは400に統一するケースも多いですが、GraphQLや複雑なフォームバリデーションでは422を使うとフィールドごとのエラー詳細を返しやすくなります。
401 vs 403:認証と認可の違いを正確に返す
`401 Unauthorized` は認証情報がない・または無効な場合に使います。名前は「Unauthorized(権限なし)」ですが、実態は「Unauthenticated(未認証)」です。Bearerトークンが期限切れ、またはトークンがリクエストに含まれていない場合が典型です。`403 Forbidden` は認証済みだがアクセス権限がない場合に使います。ログイン済みの一般ユーザーが管理者専用エンドポイントにアクセスしようとした場合などです。セキュリティ上の理由から、403と404を使い分けるべきかどうかは慎重に判断する必要があります。リソースの存在自体を秘匿したい場合は403ではなく404を返すことが推奨されます。
404 vs 410:リソースの消失を正確に伝える
`404 Not Found` は現在リソースが存在しない場合に使いますが、将来的に存在する可能性も否定しません。`410 Gone` は以前存在したが恒久的に削除されたリソースに対して使います。SEOの観点では、削除したページに410を返すとGoogleが素早くインデックスから除外してくれるため、ページ削除後は410を返すのがベストプラクティスです。ただし多くのAPIでは404と410を区別せず404で統一するケースも多く、クライアントが10xを正しくハンドリングできるかどうかも判断基準になります。
409 Conflict と 429 Too Many Requests
`409 Conflict` は操作がリソースの現在の状態と競合する場合に使います。典型的なユースケースは一意制約違反(同じメールアドレスでの重複登録)、楽観的ロックの競合(同じリソースを複数ユーザーが同時に更新しようとした場合)です。`429 Too Many Requests` はレート制限を超えた場合に使います。`Retry-After` ヘッダーで次にリクエストできるまでの待機秒数をクライアントに伝えると、適切なバックオフ処理を実装しやすくなります。APIゲートウェイやCloudflareなどのインフラレイヤーでも自動的に返されることが多いため、バックエンド側でも意識して設計することが大切です。
まとめ
ステータスコードの適切な使い分けは、APIを消費するクライアント開発者の体験を大きく左右します。仕様書を暗記する必要はありませんが、2xx・4xx・5xxそれぞれの意味を正確に理解し、「このエラーはクライアントの問題か、サーバーの問題か」「認証の問題か、認可の問題か」という判断軸を持つことが重要です。HTTP Status Referenceツールを手元に置いて、設計時の迷いを素早く解消しましょう。