REST API設計のベストプラクティスは、記事ごとに項目数も粒度もばらつきます。設計レビューで使うなら、覚える知識ではなく「この形なら通す・この形なら差し戻す」と言い切れる判定基準にしておきたいところ。この記事では、URIの命名、HTTPメソッドと冪等性、ステータスコードとエラー本文、表現の一貫性とキャッシュ制御、バージョニングの5領域を、RFCの一次情報を根拠に並べます。あわせて、規約を薄くしてよい条件と、すでに動いているAPIを壊さず直す順序も扱いました。
まとめ:REST API設計で守る5つの規約とレビューの通し方
REST API設計で差し戻し対象になるのは、ほぼ5つの領域に集約されます。URIに動詞が入っている、POSTの再送で二重登録が起きる、エラー本文の形式がエンドポイントごとに違う、フィールド命名や日時形式が混在している、破壊的変更を版を上げずに入れている。この5点を見れば、設計書のレビューは30分で回せます。
優先順位は「公開後に変えるとクライアント改修を強制するか」で決めます。URIの構造とエラー本文の形式は、後から直すと利用側の全面改修になる。ページネーションの上限値やキャッシュの有効期限は運用しながら調整できる領域です。前者は着手前に決め切り、後者は暫定値で走らせて構いません。
なお、これらの規約はすべてを満たすことが目的ではありません。社内システム間の連携で、呼び出し側が1チーム・寿命が2年以内なら、HATEOASや条件付きリクエストは見送って差し支えない。線引きは記事の後半で条件付きに示します。工程全体の進め方はAPI設計とは?リソース定義からURI・スキーマ・エラー・版管理までの実装手順に分けたので、着手前の段取りはそちらを参照してください。
URI設計の規約:名詞の複数形・動詞排除・ネスト2階層で統一する
URIはクライアントが最初に触れる面であり、公開後の変更コストが最も高い部分です。ここは規則を機械的に当てはめます。
コレクションと単一リソースの命名を複数形へ機械的に揃える規則
コレクションは複数形の名詞、単一リソースはその配下に識別子を置く。/orders がコレクション、/orders/1024 が単一リソースという対応で、API全体を通します。単数形と複数形を「1件だから単数」と使い分けると、クライアント側がエンドポイントごとに正しい綴りを覚える必要が生じます。
単語の区切りはハイフン、文字は小文字のみ、拡張子は付けない。/shippingInstructions ではなく /shipping-instructions に固定します。URLのパス部分は大文字と小文字が区別されるため、表記ゆれがそのまま404の原因になる点も理由の1つ。この規則は正規表現の検査に落とせるので、目視で確認する対象から外せます。
動詞をURIから排除し、操作の意味をHTTPメソッドへ寄せる判定
/create-order、/getUserList のように動詞が入ったURIは差し戻します。操作の種別はHTTPメソッドが担うため、パスに動詞を置くと同じ意味が2か所に書かれた状態になるから。判定はパスの各セグメントが名詞かどうかを見るだけです。
問題になるのは「注文を確定する」のようにCRUDへ収まらない操作です。取り得る形は2つ。状態をサブリソースへ切り出し /orders/1024/status を PUT で置き換える形と、コロン区切りのカスタムメソッドとして /orders/1024:confirm を許す形。前者は状態遷移の履歴を後からリソースとして取り出せるため、社内APIでは扱いやすい面があります。1つのAPI内で両方式を混ぜないでください。
絞り込み・並び替え・件数指定をクエリ文字列側へ寄せる書き分け
「未出荷の注文だけ欲しい」を /orders/unshipped というパスで表すと、条件が増えるたびにエンドポイントが増殖します。条件はクエリ文字列へ寄せ、/orders?status=unshipped の形に統一してください。パスは「何のリソースか」、クエリは「そのうちどれか」という役割分担です。
並び替えは sort、返却件数は limit、開始位置は offset か cursor と、パラメータ名もAPI全体で1組に固定します。件数指定には必ず上限を設けてください。上限のないAPIに limit=1000000 が飛ぶと、そのまま可用性の問題になる。方式の選び分けはページネーション設計とは?オフセットとカーソルの選び分けと実装で扱っています。
HTTPメソッドの割り当てと冪等性の担保:再送で壊れない設計にする
メソッド選択は好みの問題ではなく、リトライ設計に直結します。判定の根拠はRFC 9110(HTTP Semantics・2022年6月発行)が定義する安全性と冪等性です。
RFC 9110が定める安全性・冪等性の判定表とリトライ可否
安全なメソッドはサーバの状態を変えず、冪等なメソッドは何回送っても結果が同じになります。RFC 9110での位置づけは次のとおり。
| メソッド | 安全 | 冪等 | 無条件の再送 |
|---|---|---|---|
| GET | はい | はい | 可 |
| HEAD | はい | はい | 可 |
| PUT | いいえ | はい | 可 |
| DELETE | いいえ | はい | 可 |
| POST | いいえ | いいえ | 不可 |
| PATCH | いいえ | いいえ | 不可 |
この表の使いどころは、タイムアウトでレスポンスを受け取れなかった場面です。冪等な列が「はい」のメソッドなら、同じリクエストをそのまま再送できます。PUTを「更新用」ではなく「リソース全体の置換」として設計すれば、この性質が保たれる。PUTの中で採番やカウンタ加算を行うと冪等性が崩れ、リトライで数値がずれます。
POST再送による二重登録を一意キーのヘッダで抑止する実装手順
POSTは冪等ではないため、決済や受注のように二重実行が損害になる操作では別途の担保が要ります。定石は、クライアントがリクエストごとに一意なキーを生成してヘッダで送り、サーバがそのキーと処理結果を保存しておく方式。同じキーで再送が来たら処理を実行せず、保存済みの結果を返します。
ヘッダ名としては Idempotency-Key が広く使われますが、2026年9月時点でIETFの標準化は完了していません。該当のInternet-Draft(draft-ietf-httpapi-idempotency-key-header)は2025年10月15日改訂の第7版が最終で、以後は期限切れの扱い。規格準拠を根拠にはできないため、自社APIの規約として振る舞いを明文化します。保存期間、キー重複時に本文が異なる場合の応答、キー未指定時の扱いの3点を仕様書に書き切ってください。
PATCHの2方式:JSON PatchとJSON Merge Patchの選び分け
部分更新のPATCHは、リクエスト本文の形式が仕様で決まっていません。実務で選ぶのは2方式です。JSON Merge Patch(RFC 7396・2014年10月)は元のJSONと同じ構造で変更したいフィールドだけを送る形式で、記述が直感的。JSON Patch(RFC 6902・2013年4月)は add・remove・replace・test の操作配列で変更を表し、適用順序と事前条件を指定できます。
| 観点 | Merge Patch | JSON Patch |
|---|---|---|
| 記述量 | 少ない | 多い |
| null値の削除 | 削除の意味に固定 | 操作で区別できる |
| 配列の一部更新 | 不可(全置換) | 可能 |
| 更新前の値検査 | 不可 | test操作で可能 |
選定基準は、明示的な null を値として持つフィールドがあるかどうか。Merge Patchでは null が「そのフィールドを削除せよ」の意味に固定されるため、null 自体を値として保存したいスキーマでは表現できません。配列の1要素だけを差し替える要件がある場合もJSON Patchを選び、それ以外は記述量の少ないMerge Patchで足ります。どちらを採るかはメディアタイプで宣言してください。
ステータスコードの選択とRFC 9457で統一するエラー本文の設計
ステータスコードとエラー本文は、クライアントの分岐ロジックが直接依存する部分です。ここが揺れると、利用側は本文の文字列を正規表現で判定する実装に追い込まれます。
2xxの選び分け:201・202・204で意味が変わる場面の判定
成功時に200を返せば動くのは事実ですが、クライアントの後続処理が変わる場面では区別します。作成が完了して新しいURIが決まったなら201を返し、Locationヘッダに位置を入れる。クライアントは本文を解析せずに次の参照先を得られます。
処理を受け付けただけで完了していないなら202です。帳票生成や一括取り込みは同期で待たせず、202と進捗確認用のURIを返す形へ寄せてください。完了後にリソースが生まれる場合は、進捗確認のエンドポイントが303で新しいリソースへ誘導する流れが素直。返す本文がない削除成功などは204を使います。
4xxの選び分け:400・404・409・422・429を分ける判定基準
4xxの粒度が粗いと、クライアント側でリトライ可否の判断ができません。判定は次の順で行います。
| コード | 使う場面 |
|---|---|
| 400 | 本文の構文が壊れている |
| 401 | 認証情報がない・無効 |
| 403 | 認証済みだが権限がない |
| 404 | 指定のリソースが存在しない |
| 409 | 現在の状態と矛盾する要求 |
| 422 | 構文は正しいが値が不正 |
| 429 | レート制限の超過 |
400と422の境目は、パースできたかどうかに置きます。JSONとして壊れていれば400、パースはできたが必須項目の欠落や値域外なら422。RFC 9110は422を「Unprocessable Content」として定義し、内容面の不備を表す用途に置いています。409は在庫切れや二重確定のように、現在の状態と衝突する要求へ限定してください。429はRFC 6585(2012年4月)が定義するコードで、Retry-Afterヘッダに再試行までの秒数を添えると、クライアント側のバックオフ実装が単純になります。
Problem Detailsの項目設計とクライアントが分岐に使う値
エラー本文の形式は、RFC 9457(Problem Details for HTTP APIs・2023年7月発行)に寄せます。RFC 7807を廃止した改訂版で、メディアタイプは application/problem+json。定義されるメンバーは type・title・status・detail・instance の5つです。拡張メンバへ載せるアプリケーションエラーコードの付番規則や再試行可否の示し方は、APIエラーレスポンス設計とは?コード体系・リトライ判断・漏洩防止の実装手順にまとめています。
実装で決め手になるのは type の運用です。type にはエラー種別を識別するURIを入れ、その値を変えないと約束しておく。クライアントは title や detail の日本語文言ではなく type で分岐でき、文言の改善が破壊的変更になりません。detail は人間が読むための説明として扱い、そこに機械判定させないでください。
バリデーションエラーのように複数件を返す場合は、拡張メンバーを足して配列で持たせます。RFC 9457は独自メンバーの追加を許容するため、errors のようなキーにフィールド名と理由を並べる形で構いません。この型をOpenAPIの共通スキーマとして1か所に定義し、全エンドポイントから参照する運用はスキーマファーストとは?OpenAPI起点の並行開発と破壊的変更検知で扱う手順と噛み合います。
表現の一貫性とキャッシュ制御:命名規則・日時形式・ETagの規約
個々のエンドポイントが正しくても、API全体で表記が揺れると利用側に変換層が生まれます。ここは規約を1本に固定する話です。
フィールド命名と日時形式をAPI全体で1つの規則へ固定する手順
フィールド名の記法はキャメルケースかスネークケースのどちらかに決め、混在させません。どちらが優れているという話ではなく、1つのAPI内で userId と user_id が併存する状態を避けることが目的。実装言語の慣習に引きずられてサービスごとに変わるのがよくある崩れ方なので、規約はチーム横断のドキュメントに置きます。
日時はISO 8601形式でタイムゾーンを明示し、UTCに揃えるのが扱いやすい。2026-09-02T14:30:00Z のように送れば、クライアント側は自国の時刻へ変換するだけで済みます。日付のみと日時を同じキー名で使い分ける設計は境界の解釈が割れるため、分けてください。真偽値に 0 と 1 を入れる、金額を文字列で返すといった型の揺れも同じ理由で潰します。
ETagとIf-Matchによる楽観ロックで更新衝突を検知する
複数クライアントが同じリソースを更新するAPIでは、最後に書いた内容が黙って他方を上書きします。これを防ぐのが条件付きリクエストで、RFC 9110が規定する仕組み。サーバはGETの応答にETagヘッダでリソースの版を示す文字列を返し、クライアントは更新時にその値をIf-Matchヘッダへ載せて送ります。
サーバ側は、If-Matchの値が現在のETagと一致した場合だけ更新を実行し、一致しなければ412を返す。クライアントは412を受けて再取得し、差分を確認してから再送します。楽観ロックを本文の updatedAt で自前実装したAPIをよく見かけますが、HTTPの標準機構に寄せたほうがクライアントライブラリの支援を受けられます。
同じETagはキャッシュ検証にも効きます。クライアントがIf-None-Matchを付けて再取得し、変化がなければ304を返す形で、本文の転送を省ける仕組み。Cache-Controlのmax-ageと組み合わせる設計は、参照系の負荷が読めない外部公開APIで先に入れておく価値があります。
APIバージョニング方式の選定と後方互換を壊さない変更手順の決め方
版管理は「どの方式を選ぶか」より「いつ版を上げるか」の基準を先に決めるほうが効きます。方式の違いはその後の話です。
URIパス版・ヘッダ版・メディアタイプ版の比較と選定の判断基準
実務で使われる方式は3つ。URIパスに /v1/ を入れる方式、独自ヘッダやAcceptヘッダのパラメータで指定する方式、メディアタイプ自体に版を埋め込む方式です。
| 方式 | 利点 | 難点 |
|---|---|---|
| URIパス | 確認が容易・キャッシュ可 | 同一リソースが別URIに |
| ヘッダ指定 | URIが版で変わらない | ブラウザから試しにくい |
| メディアタイプ | HTTPの意味論に忠実 | 実装と周知の負担が大きい |
外部公開APIならURIパス方式を推します。利用者がドキュメントを見ずに現在の版を判別でき、ログやキャッシュの分離も効くためです。純粋なREST観点ではURIが版で変わる点が批判されますが、運用上の可読性がその不利を上回る場面が多い。社内APIで利用側が数チームなら、ヘッダ方式で呼び出し先を1つに保つ選択も成り立ちます。理論面の背景はRESTとは?REST APIの仕組みと6原則・SOAP/GraphQLとの違いで整理しました。
破壊的変更にあたる修正5種の判定と、版を上げずに機能を足す手順
版を上げるのは破壊的変更を入れるときだけです。該当するのは、レスポンスからのキー削除、キー名や型の変更、既存項目の意味変更、必須リクエスト項目の追加、エラーコードの意味の付け替えの5種。逆に、レスポンスへのキー追加、任意パラメータの追加、新規エンドポイントの追加は非破壊として同じ版に載せられます。
キー追加を非破壊として扱うには、クライアント側が未知のフィールドを無視する前提を先に宣言しておく必要があります。この一文が仕様書にないと、厳格なパーサを書いた利用者が追加のたびに壊れる。逆に言えば、この宣言を最初に入れておくだけで、その後の機能追加のかなりの部分を版を上げずに通せます。
やむを得ず破壊的変更を入れるなら、新旧を一定期間併存させ、旧版の応答に廃止予定日を示すヘッダを添えてから停止する順序を採ってください。告知から停止まで最低3か月といった期限を規約に書いておくと、個別交渉が発生しません。
規約を適用しない条件と、既存REST APIを壊さず是正する順序
ここまでの規約は、すべてのAPIに同じ密度で当てるものではありません。密度を下げる条件と、すでに動いているAPIの直し方を分けて示します。
規約の密度を薄くしてよい社内API3条件と外部公開との線引き
密度を下げてよいのは、呼び出し側が1チームに閉じている、想定寿命が2年以内、クライアントとサーバを同じチームが同時にデプロイできる、の3条件がそろう場合。HATEOAS、条件付きリクエスト、メディアタイプ版管理を見送り、URI命名とエラー形式の統一だけ守れば実務が回ります。壊れたら双方を同時に直せるためです。
逆に、1つでも外れたら密度を戻してください。特に「呼び出し側が2チーム以上」に該当した時点で、破壊的変更の判定基準とエラー形式の固定は外せない要件になります。ハイパーメディア採用の判断材料はHATEOASとは?RESTレベル3の仕組みとHAL・JSON:APIの実装判断にまとめました。
設計の密度は、APIの公開範囲と寿命で決まります。パートナー企業へ提供する、あるいはSaaSとして課金対象にする段階では、規約に加えてサポート期限の告知手段まで先に用意することになります。
既存APIを壊さず是正する順序:新旧併存から旧経路の停止まで
すでに稼働しているAPIの規約違反は、一斉に直すと利用側が全滅します。順序は「利用側に影響しない領域から」。まずエラー本文の形式をProblem Detailsへ寄せます。エラー時の本文構造は、正常系を触らずに差し替えられる場合が多いためです。次にレスポンスへのキー追加で情報を補い、旧キーは残したまま並走させます。
URIの命名違反とメソッドの誤用は最後です。新しいパスを追加して両方が同じ処理へ届くようにし、旧パスの応答にDeprecationの告知ヘッダを付け、アクセスログで旧パスの利用が消えたことを確認してから停止する。この確認を省いて期日で切ると、月次バッチのように低頻度で呼ぶ利用者を落とします。呼び出し元の識別が難しいなら、認証キー単位で利用状況を集計できるようにしてから着手してください。
既存APIの棚卸しから是正計画の作成までを外部と進める場合は、設計規約そのものを成果物として先に固定し、そのうえで是正順序を引く進め方が手戻りを抑えます。API開発・システム連携では、設計規約の策定から既存APIの是正・実装までを含めて対応しています。
よくある質問
RESTfulなAPIとREST APIは違うものですか?
実務では同義として扱って差し支えありません。厳密にはRESTの6制約をすべて満たすものがREST APIで、HATEOASのないAPIはRESTfulと呼べないという整理もあります。ただし公開APIの多くはRichardson成熟度モデルのレベル2で止まり、その状態をREST APIと呼ぶ用法が定着している状況。設計レビューでこの区別を争う実益は薄いと考えてください。
URIに動詞を入れてはいけないのは、なぜですか?
操作の種別をHTTPメソッドが既に表しているため、パスに動詞を置くと同じ情報が2か所に分かれるからです。/orders/1024/delete にGETが飛んだ場合の振る舞いが決まらない、といった矛盾も生じる。動詞を許すと命名が自由になり、delete・remove・destroy が同一API内に混在します。名詞へ固定すれば、この揺れが構造的に起きません。
PUTとPATCHは、どう使い分ければよいですか?
リソース全体を送るならPUT、変更部分だけを送るならPATCHです。PUTは送られてこなかったフィールドを未設定として扱う置換操作なので、一部だけ送ると他が消えます。フォーム全体を保持する更新画面ならPUT、項目単位で更新する呼び出し元にはPATCHが噛み合う。両方を実装するなら、PUTが置換である旨を仕様書に明記してください。
ステータスコードは常に200で返し、本文にエラーを入れる設計はどうですか?
避けてください。HTTPクライアントライブラリ、APIゲートウェイ、監視ツールはいずれもステータスコードで成否を判定します。200で返すとエラー率のメトリクスに何も現れず、障害の検知が遅れる。プロキシやCDNが誤ってエラー応答をキャッシュする問題も起こり得ます。既存APIがこの形なら、新しいパスを追加して段階的に移す方法を採ります。
ベストプラクティスに全部従うと、開発工数はどれくらい増えますか?
着手時点で規約を決めておく場合、増分は設計工程の数日程度に収まります。増えるのは後付けの場合で、稼働中のAPIへ条件付きリクエストや版管理を足すと、利用側の改修調整を含めて数か月単位になることも。工数の議論は「今入れる費用」と「後から入れる費用」の比較で行い、外部公開の予定を分岐の条件に置いてください。
関連記事
- API設計とは?リソース定義からURI・スキーマ・エラー・版管理までの実装手順:本記事の前提となる設計工程全体の進め方を扱っています。
- RESTとは?REST APIの仕組みと6原則・SOAP/GraphQLとの違いを実装目線で解説:REST原則そのものと他方式との比較を解説しています。
- HATEOASとは?RESTレベル3の仕組みとHAL・JSON:APIの実装判断を解説:ハイパーメディア採用の可否を判断する材料をまとめています。
- ページネーション設計とは?オフセットとカーソルの選び分けと実装を解説:一覧取得の方式選定を詳しく扱っています。
- スキーマファーストとは?OpenAPI起点の並行開発と破壊的変更検知を解説:規約をOpenAPI定義へ落として運用する手順を扱っています。
- API開発・システム連携:設計規約の策定から既存APIの是正・実装までの支援内容です。