REST 成熟度モデル

Leonard Richardson が定義した REST API の成熟度を 4 段階で評価するモデル

API設計

REST 成熟度モデルとは

REST 成熟度モデル (Richardson Maturity Model) は、REST API の設計を 4 段階 (レベル 0〜3) に分けて捉える考え方である。出所は Leonard Richardson が 2008 年 11 月 20 日の QCon 講演で示したもので、講演では第 3 部の題が「成熟度のヒューリスティック」となっており、本人は厳密な規格ではなく経験則として提示している。これを Martin Fowler が 2010 年 3 月 18 日の記事でレベルとして整理し、設計品質を議論する共通語になった。

段階付けを読むときの前提が 1 つある。Fowler は同じ記事で「これは REST の水準の定義ではない」と断り、Roy Fielding がレベル 3 を REST の前提条件だと明確にしていることも併記している。つまり、以下で「レベル 2 で十分」とするのは実務上の折り合いであって、Fielding の定義に照らせばレベル 2 は REST ではない。この食い違いを踏まえずに「REST 準拠」と名乗ると、議論が空回りする。

4 つのレベル

レベル 0 - The Swamp of POX

単一のエンドポイントに全操作を集約する。HTTP は単なるトランスポートとして使い、操作の種別はリクエストボディで指定する。

POST /api
{ "action": "getUser", "userId": "123" }

POST /api
{ "action": "createOrder", "items": [...] }

XML-RPC や SOAP がこのレベルに該当する。URL も HTTP メソッドも意味を持たない。

レベル 1 - Resources

操作対象をリソースとして URL で識別する。ただし HTTP メソッドは POST のみ。

POST /users/123
{ "action": "get" }

POST /orders
{ "action": "create", "items": [...] }

リソースの概念が導入されたが、HTTP メソッドの意味を活用していない。

レベル 2 - HTTP Verbs

HTTP メソッド (GET, POST, PUT, DELETE) をリソースへの操作に対応させる。ステータスコードも適切に使い分ける。実務で REST API と呼ばれる設計は、多くがこの段を指している。

この段の値打ちは、HTTP 側に既にある仕組みをそのまま借りられることにある。GET なら中間のキャッシュが効き、PUT や DELETE なら応答を受け取れなかったときに再送してよいと判断でき、ステータスコードだけでクライアントが分岐できる。レベル 0 や 1 では、これらを自前の取り決めとして作り直すことになる。

GET    /users/123          → 200 OK
POST   /orders             → 201 Created
PUT    /orders/456         → 200 OK
DELETE /orders/456         → 204 No Content
GET    /users/999          → 404 Not Found
POST   /orders (不正データ) → 400 Bad Request

レベル 3 - Hypermedia Controls (HATEOAS)

レスポンスにリンクを含め、クライアントが次に取れるアクションを動的に発見できる (HATEOAS)。

{
  "orderId": "456",
  "status": "pending",
  "_links": {
    "self": { "href": "/orders/456" },
    "cancel": { "href": "/orders/456/cancel", "method": "POST" },
    "payment": { "href": "/orders/456/payment", "method": "POST" }
  }
}

リンクの書き方は 1 つに定まっていない。上の例は HAL (JSON Hypertext Application Language) に近い形だが、method を添えるのは HAL には無い独自の拡張である。ほかに JSON:API 形式や、本文ではなく Link ヘッダーで示す方法 (RFC 8288 Web Linking) もある。表現を選ぶ時点で、クライアントとの間に独自の取り決めが 1 つ増えることは避けられない。

実務ではどのレベルを目指すべきか

2026 年 8 月時点でも、狙いどころはレベル 2 である。レベル 3 が広がらない理由は思想ではなく実装側にあり、クライアントが応答内のリンクを読んで次の操作を決める作りにしないと恩恵が出ない。URL を決め打ちする方が単純で、スキーマから通信コードを生成する運用とも噛み合いやすい。サーバー側がリンクを返していても、クライアントが無視して URL を組み立てているなら、実質はレベル 2 のままである。

レベル主に見られる場面推奨度
レベル 0既存の RPC 型システム新規開発では避ける
レベル 1一部の内部 API不十分
レベル 2実務の REST API の主流推奨 (標準)
レベル 3一部の公開 API部分的に採用

レベル 2 を確実に実装した上で、ページネーションのリンクや状態遷移のリンクなど、レベル 3 の要素を部分的に取り入れるのが現実的なアプローチだ。

レベル 2 でよくある設計ミス

GET で副作用を起こす

//GET でデータを削除
GET /users/123/delete

//DELETE メソッドを使う
DELETE /users/123

GET に求められるのは、べき等よりも強い「安全」(RFC 9110 の safe) である。安全とは意味の上で読み取り専用ということで、状態を変える操作を GET に載せてはいけない。中間のキャッシュやブラウザーのプリフェッチ、クローラーは安全であることを前提に勝手に GET を投げるため、削除が意図せず実行される。

ステータスコードの誤用 (200 で失敗を返す)

// ❌ エラーでも常に 200 を返す
HTTP 200 OK
{ "success": false, "error": "User not found" }

// ✅ 適切なステータスコードを返す
HTTP 404 Not Found
{ "error": "User not found", "code": "USER_NOT_FOUND" }

URL に動詞を含める

// ❌ URL に動詞
POST /users/123/activate
POST /orders/456/sendEmail

// ✅ リソースの状態変更として表現
PATCH /users/123 { "status": "active" }
POST /orders/456/notifications  (通知をリソースとして扱う)

ただし、CRUD に収まらない操作 (パスワードリセット、バッチ処理の開始など) は動詞を含む URL が許容される場合もある。判断の目安は、その行為自体を後から一覧・参照したいかどうかである。実行履歴を残したいならリソース (/password-reset-requests) として作る価値があり、単発で記録も要らないなら動詞のまま置く方が読みやすい。

API Gateway での実装

API Gateway + Lambda の構成では、レベル 2 の実装が自然に行える。SAM テンプレートでリソースとメソッドを定義する。

Events:
  GetUser:
    Type: Api
    Properties:
      Path: /users/{id}
      Method: GET
  CreateUser:
    Type: Api
    Properties:
      Path: /users
      Method: POST

レベルは点数ではなく、どの恩恵が欲しいかの目印として使う。キャッシュや再送の判断を HTTP に任せたいならレベル 2 まで上げる意味があり、クライアント側の分岐を減らしたいならレベル 3 の要素を部分的に足す。逆に、段を上げて何が楽になるかを言えないなら、上げる必要はない。

この記事は役に立ちましたか?

関連用語

関連する記事