HTTPステータスコードは仕様書では番号と短い説明しか書かれていませんが、実際のAPI設計では「200でいいのか201を返すべきか」「400と422はどう違うのか」「401と403はいつ使い分けるのか」といった迷いが頻繁に生じます。この記事では、REST APIを設計・実装する上でよく使うステータスコードを、2xx・4xx・5xxの順に、実際のユースケースと判断基準とともに解説します。
2xx:成功系コードの使い分け
`200 OK` はGET・PUT・PATCHなど汎用的な成功レスポンスです。`201 Created` はPOSTでリソースが新規作成されたときに使い、`Location` ヘッダーに作成されたリソースのURLを付けるのがベストプラクティスです。`204 No Content` はDELETE成功時やPATCHでレスポンスボディが不要な場合に使います。204を返す場合はボディを空にする必要があり、ボディを付けると仕様違反になるため注意が必要です。`202 Accepted` はリクエストを受け付けたが処理が非同期で行われる場合に使います。バックグラウンドジョブのキューイングやメール送信などで有効で、`Location` ヘッダーに処理状況を確認できるエンドポイントを示すと親切です。
この手順で使うツール
HTTP Status Reference
HTTPステータスコードを番号/キーワードで検索 — 説明・用途・ヘッダー例を表示
400 vs 422:バリデーションエラーの適切な使い分け
`400 Bad Request` と `422 Unprocessable Content` はどちらもクライアントのエラーですが、意味が異なります。400はリクエスト自体が読めない場合(JSONの構文エラー、Content-Type と中身の食い違い、数値の欄に文字列が来たなど型の根本的な誤り)に使います。422はリクエストとしては読めるが、内容が処理できない場合(メールアドレスの形式エラー、年齢が負の値、存在しないカテゴリIDの指定)に使います。必須項目の欠落はどちらに入れるかがAPIによって分かれるので、自分のAPIの中でどちらかに揃えておくことが大切です。シンプルなAPIでは400に統一するケースも多いですが、422を分けておくと、クライアントが「送り方の誤り」と「入力内容の誤り」を区別でき、フォームでフィールドごとのエラーを表示しやすくなります。なお GraphQL は、エラーがあっても HTTP としては 200 を返し、本文の errors に詳細を入れるのが一般的で、この使い分けとは考え方が違います。
この手順で使うツール
HTTP Status Reference
HTTPステータスコードを番号/キーワードで検索 — 説明・用途・ヘッダー例を表示
401 vs 403:認証と認可の違いを正確に返す
`401 Unauthorized` は認証情報がない・または無効な場合に使います。名前は「Unauthorized(権限なし)」ですが、実態は「Unauthenticated(未認証)」です。Bearerトークンが期限切れ、またはトークンがリクエストに含まれていない場合が典型です。HTTPの仕様では、401 を返すときは WWW-Authenticate ヘッダーで認証の方式(たとえば Bearer)を示すことになっています。`403 Forbidden` は認証済みだがアクセス権限がない場合に使います。ログイン済みの一般ユーザーが管理者専用エンドポイントにアクセスしようとした場合などです。セキュリティ上の理由から、403と404を使い分けるべきかどうかは慎重に判断する必要があります。リソースの存在自体を秘匿したい場合は403ではなく404を返すことが推奨されます。
この手順で使うツール
HTTP Status Reference
HTTPステータスコードを番号/キーワードで検索 — 説明・用途・ヘッダー例を表示
404 vs 410:リソースの消失を正確に伝える
`404 Not Found` は現在リソースが存在しない場合に使いますが、将来的に存在する可能性も否定しません。`410 Gone` は以前存在したが恒久的に削除されたリソースに対して使います。Webページの場合、Google は 404 と 410 をほぼ同じように扱うと説明しており、410 のほうがわずかに早くインデックスから外れることがある程度の差です。恒久的に消したことが明確なら 410 を返すと意図が伝わります。多くのAPIでは404と410を区別せず404で統一していて、それで困ることは少ないので、クライアントが410を個別に扱う必要があるかで決めてください。
この手順で使うツール
HTTP Status Reference
HTTPステータスコードを番号/キーワードで検索 — 説明・用途・ヘッダー例を表示
409 Conflict と 429 Too Many Requests
`409 Conflict` は操作がリソースの現在の状態と競合する場合に使います。典型的なユースケースは一意制約違反(同じメールアドレスでの重複登録)、楽観的ロックの競合(同じリソースを複数ユーザーが同時に更新しようとした場合)です。`429 Too Many Requests` はレート制限を超えた場合に使います。`Retry-After` ヘッダーで次にリクエストしてよい時刻を伝えると、クライアントは適切に待ってから再試行できます。値は秒数(Retry-After: 30)か日時のどちらでも書けます。APIゲートウェイやCloudflareなどのインフラ側でも自動的に返されることが多いので、自分で返さないつもりでも、クライアントが 429 を受け取ったときの動きは決めておく必要があります。確かめるには、テストで 429 を返す偽のレスポンスを作ります。HTTP Response Mock でステータスを 429、ヘッダーに Retry-After: 30 を入れると、テストやモックサーバーで使える fetch の Response の形で出力されるので、クライアントが30秒待ってから再試行するかを確かめられます。
この手順で使うツール
HTTP Response Mock Builder
レスポンスを組み立てて curl / fetch / 生HTTP形式で出力
5xx:サーバー側の問題を区別して返す
`500 Internal Server Error` は、サーバー側で予期しないエラーが起きたときの総称です。クライアントにできることはないので、詳細な原因(スタックトレースなど)は本文に出さず、サーバーのログに残します。`503 Service Unavailable` は、メンテナンス中や過負荷で一時的に応答できない場合に使い、429 と同じく Retry-After で再開の目安を伝えられます。`502 Bad Gateway` と `504 Gateway Timeout` は、前段のプロキシやロードバランサーが、後ろのサーバーから正しい応答を受け取れなかった(502)、時間内に受け取れなかった(504)ことを表します。アプリ自身が返すことは少なく、インフラ側が返すものです。障害の調査では、500 ならアプリのログ、502・504 ならプロキシと後ろのサーバーの間、503 なら意図したメンテナンスか過負荷か、というように最初に見る場所が変わります。クライアント側では、500 は同じリクエストを繰り返しても直らないことが多いのに対し、502・503・504 は一時的なことが多く、間隔を空けた再試行が意味を持ちます。
この手順で使うツール
HTTP Status Reference
HTTPステータスコードを番号/キーワードで検索 — 説明・用途・ヘッダー例を表示
まとめ
ステータスコードの適切な使い分けは、APIを消費するクライアント開発者の体験を大きく左右します。仕様書を暗記する必要はありませんが、2xx・4xx・5xxそれぞれの意味を正確に理解し、「このエラーはクライアントの問題か、サーバーの問題か」「認証の問題か、認可の問題か」「再試行して意味があるか」という判断軸を持つことが重要です。HTTP Status Reference を手元に置いて、設計時の迷いを素早く解消しましょう。