Richardson Maturity Model
Levels of REST API Maturity#
The Richardson Maturity Model, described by Leonard Richardson and popularized by Martin Fowler, classifies REST API maturity into four levels. Understanding these levels helps you design APIs that grow with your system and provide clear contracts for clients.
The model doesn’t say which level is “best”—rather, it describes what you’re committing to at each level. Higher maturity levels provide more flexibility but require more sophistication from clients.
Level 0: Plain Old XML (POX)#
At this level, you’re using HTTP as a transport mechanism for Remote Procedure Calls (RPCs). There’s no concept of resources or methods—just endpoints that accept requests and return responses.
Example:
POST /service HTTP/1.1
Content-Type: application/xml
<request>
<action>getUser</action>
<userId>123</userId>
</request>
Response:
<response>
<user>
<id>123</id>
<name>John</name>
</user>
</response>
All operations go through the same endpoint. The HTTP method is usually POST because you’re not using HTTP semantics—you’re just tunneling calls through HTTP.
Problems:
- No standardization—every API designer invents their own contract
- No caching—intermediary proxies can’t cache responses
- No standard error handling—each API defines errors differently
- High coupling—clients must understand the specific request/response format
Level 1: Resources#
At level 1, you introduce the concept of resources. Instead of procedures, you have entities that clients interact with.
Example:
POST /users/123 HTTP/1.1
Content-Type: application/xml
<request>
<action>update</action>
<name>John Smith</name>
</request>
Response:
<user>
<id>123</id>
<name>John Smith</name>
</user>
Now you have /users/123 as a resource endpoint. Operations still use POST and custom action parameters, but at least you’ve acknowledged that your API is manipulating resources.
Benefits:
- Resources are easier to reason about than arbitrary procedures
- Multiple clients can be built around the same resource model
- You can start thinking about caching
Problems:
- Still using POST for everything
- Still mixing semantic meaning into request bodies
- No standard HTTP status codes
Level 2: HTTP Verbs#
At level 2, you use HTTP methods (GET, POST, PUT, DELETE) with proper semantics:
GET /users/123 HTTP/1.1
→ 200 OK
PUT /users/123 HTTP/1.1
Content-Type: application/json
{"name": "John Smith"}
→ 200 OK
DELETE /users/123 HTTP/1.1
→ 204 No Content
Now HTTP verbs have meaning:
- GET retrieves a resource (safe, idempotent)
- POST creates a new resource
- PUT updates a resource (idempotent)
- DELETE removes a resource (idempotent)
- Status codes convey meaning (200 success, 404 not found, 400 bad request)
Benefits:
- Caching proxies can distinguish GET requests from modifications
- Standard HTTP clients and tools work correctly
- Cleaner, more intuitive API design
- HTTP status codes provide standard error semantics
Problems:
- Resources and their relationships are static in the response
- Clients still need to know all possible resource URLs
- Evolution is hard—new endpoints break client assumptions
Level 3: Hypermedia Controls#
At level 3, responses include links to related resources and available operations. This is true REST in Fielding’s original formulation.
Example:
{
"id": "123",
"name": "John Smith",
"_links": {
"self": { "href": "/users/123" },
"update": { "href": "/users/123", "method": "PUT" },
"delete": { "href": "/users/123", "method": "DELETE" },
"orders": { "href": "/users/123/orders" }
}
}
Clients don’t need to construct URLs; they follow links in responses. This enables servers to change URL structures without breaking clients.
Benefits:
- Loose coupling: clients follow links instead of constructing URLs
- Server evolution: URLs can change without breaking clients
- Dynamic discovery: clients can discover available operations from responses
- Enables API versioning without multiple versions
Problems:
- Significantly more complex for both servers and clients
- Standards (HAL, JSON:API, Siren) compete for adoption
- Not all operations fit the hypermedia model
- Performance impact from additional data in responses
Choosing Your Level#
Use Level 0 Only For:#
- Legacy systems transitioning to better APIs
- Extremely simple internal services
- One-off integrations that won’t grow
Use Level 1 For:#
- Internal APIs where change is controlled
- Simple CRUD operations
- Systems where resource concept is clear and stable
Use Level 2 For:#
- Most modern APIs—this is the sweet spot
- Public APIs where stability is important
- When HTTP caching is valuable
- The vast majority of well-designed REST APIs
Use Level 3 For:#
- Highly complex systems with frequent evolution
- Public APIs serving diverse client types
- Systems where you want client resilience to change
- When the overhead is justified by flexibility needs
The Maturity Question#
Higher maturity doesn’t mean better. Level 3 is more flexible but more complex. Many successful APIs (Twitter, GitHub, Stripe) use Level 2 with occasional Level 3 hypermedia additions.
Evaluate based on:
- Stability of resources: If your resource model is stable, Level 2 is sufficient
- Client diversity: Different client types benefit from hypermedia
- Evolution frequency: Rapid API evolution favors higher levels
- Coupling tolerance: Can your clients handle resource URL changes?
Implementation Advice#
- Start at Level 2: Use resources and HTTP verbs. This is standard and solves most problems
- Add hypermedia strategically: Certain endpoints benefit from HATEOAS, others don’t
- Don’t over-commit: Just because you use hypermedia for some endpoints doesn’t mean all endpoints need it
- Document your level: Make explicit what maturity level clients should expect
Conclusion#
The Richardson Maturity Model helps you think about API design systematically. Most teams should aim for Level 2 (HTTP verbs and status codes) as the baseline—it’s a sweet spot between simplicity and standardization.
Level 3 (hypermedia) is valuable but adds complexity. Adopt it only where the flexibility justifies the cost. Don’t feel pressured to achieve Level 3 for everything; pragmatism about where hypermedia adds value is more important than purity.
Your API maturity should match your system’s volatility and your clients’ sophistication. Choose accordingly.