Richardson Maturity Model: Levels 0 to 3 (HATEOAS)
Evaluate REST compliance: Level 0 (The Swamp of POX), Level 1 (Resources), Level 2 (HTTP Verbs), and Level 3 (HATEOAS hypermedia controls).
Richardson Maturity Pyramid
Climb levels 0 to 3, pay the order, and watch wire format, links, and client coupling change.
HTTP request
GET /v1/orders/ord_9082 HTTP/1.1
Response (100 bytes, 200 OK)
{
"order_id": "ord_9082",
"status": "AWAITING_PAYMENT",
"amount": 129.5,
"currency": "USD"
}URLs hardcoded in SDK
6
Link metadata overhead
+0%
Order state
AWAITING_PAYMENT
HTTP semantics used
verbs + codes
Client UI action buttons render from
#Pay order (hardcoded route)
#Cancel order (hardcoded route)
The pragmatic sweet spot (95% of production APIs): verbs and accurate status codes give caching, retries and monitoring for free, but the SDK must hardcode URL templates and guess valid transitions.
The Richardson Maturity Pyramid 🏛️
The four progressive steps from basic RPC-over-HTTP to pure Hypermedia-driven REST.
01.The 4 Levels of the Richardson Maturity Model
Developed by Leonard Richardson, the Richardson Maturity Model (RMM) breaks down the principal elements of a RESTful approach into four progressive stages:
Level 0: The Swamp of POX (Plain Old XML / RPC)
- Characteristics: Uses HTTP purely as a transport tunneling mechanism for Remote Procedure Calls (XML-RPC, SOAP, or single-endpoint GraphQL/JSON-RPC).
- URI: A single monolithic endpoint, typically
POST /api/service. - Payload: The operation name and arguments are passed entirely inside the request body:
httpPOST /api/service HTTP/1.1 Host: api.example.com Content-Type: application/json { "action": "getUserDetails", "userId": 42 }
Level 1: Distinct Resources
- Characteristics: Introduces individual URIs for distinct business entities, organizing the system into addressable resources instead of a single monolithic endpoint.
- URI: Distinct paths:
/v1/users/42,/v1/orders/109. - Limitation: Often still uses a single HTTP method (like
POST) for all operations:
httpPOST /v1/users/42 HTTP/1.1 { "action": "delete" }
Level 2: HTTP Verbs & Status Codes
- Characteristics: Applies standard HTTP methods according to their formal RFC specifications (
GETfor safe reads,POSTfor creation,PUTfor full replacement,PATCHfor delta updates,DELETEfor removal). - Semantics: Uses accurate HTTP status codes (
200 OK,201 Created,204 No Content,404 Not Found,409 Conflict,422 Unprocessable). - Industry Standard: 95% of modern production "REST" APIs operate at Level 2.
Level 3: Hypermedia Controls (HATEOAS)
- Characteristics: Hypermedia As The Engine Of Application State (HATEOAS). Responses include discoverable hypermedia links (
_links) that tell the client what operations and state transitions are valid next. - Advantage: Decouples client routing from hardcoded URL templates. If an order cannot be cancelled because it has already shipped, the server simply omits the
cancellink from the response payload.
02.Anatomy of a Level 3 HATEOAS Response (HAL Standard)
Hypertext Application Language (HAL) is an IETF draft standard for structuring hypermedia links in JSON:
json{ "order_id": "ord_9082", "status": "AWAITING_PAYMENT", "amount": 129.50, "currency": "USD", "items_count": 3, "_links": { "self": { "href": "/v1/orders/ord_9082", "method": "GET" }, "payment": { "href": "/v1/orders/ord_9082/payments", "method": "POST", "title": "Submit payment for this order" }, "cancel": { "href": "/v1/orders/ord_9082/cancel", "method": "POST", "title": "Cancel order before payment" }, "customer": { "href": "/v1/customers/cus_4102", "method": "GET" } } }
Dynamic State Transition:
Once the client executes POST /v1/orders/ord_9082/payments and the transaction completes, the subsequent GET /v1/orders/ord_9082 returns:
json{ "order_id": "ord_9082", "status": "PROCESSING", "_links": { "self": { "href": "/v1/orders/ord_9082", "method": "GET" }, "tracking": { "href": "/v1/orders/ord_9082/tracking", "method": "GET" }, "refund": { "href": "/v1/orders/ord_9082/refunds", "method": "POST" } } }
Notice that payment and cancel links have disappeared, preventing the client UI from rendering invalid action buttons.
03.Why Level 2 is the Pragmatic Industry Sweet Spot
While Roy Fielding famously stated that an API that does not implement HATEOAS is not a true REST API, the industry has predominantly standardized on Level 2.
The Challenges of Level 3 (HATEOAS) in Practice:
- Payload Bloat: Hypermedia links add 20% to 40% bandwidth overhead to every JSON response, which degrades mobile performance over high-latency cellular networks.
- Client Complexity & Friction: Frontend web and mobile SDKs prefer static TypeScript types generated from OpenAPI/Swagger contracts over dynamic runtime hypermedia traversal engines.
- Caching Difficulties: Dynamic link generation often depends on the user's specific authorization role and resource state, reducing edge CDN cache hit ratios.
When Level 3 HATEOAS is Justified:
- Payment & Checkout Gateways (e.g., PayPal): Directing third-party SDKs through multi-step redirect and authorization states.
- Workflow State Engines: Dynamic business process workflows where allowed actions frequently change based on server-side compliance rules.
Architectural Trade-offs & Production Realities
Architectural Advantages
- Level 2 provides predictable, clean resource semantics with minimal client complexity and high cacheability
- Level 3 decouples client UIs from backend URI schemes and enforces server-driven business state machines
- Provides a clear maturity ladder to evaluate legacy API refactoring milestones
Trade-offs & Constraints
- Level 3 adds significant JSON payload size overhead (20-40% link metadata)
- Client libraries for Level 3 hypermedia parsing are complex and non-standard compared to OpenAPI-generated clients
- Level 0 (SOAP/RPC) loses standard HTTP caching, load balancer routing, and idempotent retry guarantees
PayPal's v2 Orders API utilizes Level 3 HATEOAS: creating an order returns hypermedia links (`payer-action`, `capture`, `authorize`) that dynamic client checkout SDKs navigate to complete payments across various authorization flows without hardcoded redirect routes.
Staff+ Engineering Takeaways
- Level 0 is RPC over HTTP; Level 1 introduces discrete resource URIs; Level 2 uses HTTP verbs and status codes.
- Level 3 (HATEOAS) embeds hypermedia links (`_links`) so responses dictate valid next state transitions.
- Level 2 is the pragmatic sweet spot for 95% of real-world REST microservices and public APIs.
- HATEOAS prevents invalid client transitions by dynamically omitting unavailable action links.
Topic Knowledge Check
Exercise 1 of 2 • Test your architectural comprehension.
Which Richardson Maturity level is characterized by an API having discrete URIs (/users/123, /orders/456) and using GET, POST, PUT, and DELETE with proper HTTP status codes, but without embedded hypermedia link relations?
How clear and actionable was this distributed systems breakdown?