Kokil Thapa - Professional Web Developer in Nepal
Freelancer Web Developer in Nepal with 15+ Years of Experience

Kokil Thapa is an experienced full-stack web developer focused on building fast, secure, and scalable web applications. He helps businesses and individuals create SEO-friendly, user-focused digital platforms designed for long-term growth.

The Richardson Maturity Model Explained

By Kokil Thapa | Last reviewed: September 2026

You inherit an API that accepts every action through one POST endpoint. Clients hard-code URLs. Updates fail because nobody agreed on status codes. The Richardson Maturity Model explained here gives you a shared vocabulary for that mess. Leonard Richardson defined four REST maturity levels in 2008. Martin Fowler popularised them in a 2010 essay. Teams still use the model in 2026 because it turns vague “RESTful” debates into concrete design steps. If you build or review APIs, this framework belongs in your toolkit alongside API development standards and your OpenAPI spec.

What is the Richardson Maturity Model?

The Richardson Maturity Model is a staircase for REST API design. Each step adds constraints that make your API more aligned with how the web actually works. Higher levels are not automatically better for every project. A Level 0 RPC gateway can be the right call for a quick internal integration. A public partner API usually belongs at Level 2 or above.

Richardson grouped REST maturity into four numbered levels, often written 0 through 3. Fowler mapped them to “REST” letters: Level 0 ignores REST entirely. Level 1 introduces Resources. Level 2 adds Verbs. Level 3 adds Hypermedia controls. That mnemonic helps in architecture reviews when someone says “we need REST” but the codebase is still one giant POST handler.

In my experience working on production Laravel applications, the model works best as a diagnostic tool. You score an existing API, identify the lowest hanging gap, and fix that before debating JSON:API versus plain JSON. It pairs well with API rate limiting and abuse prevention because Level 2 semantics make idempotent retries and cache headers meaningful.

Richardson REST Maturity LevelsLevel 0Single URI RPCLevel 1Many resourcesLevel 2HTTP verbsLevel 3HATEOAS linksTypical client couplingHighMediumLowerLowestMost Laravel and WordPress REST APIs ship at Level 1 or 2Level 3 suits long-lived public platforms
Richardson Maturity Model overview: four REST levels from single-endpoint RPC to hypermedia-driven APIs

The model does not replace Roy Fielding’s architectural definition of REST. Fielding’s dissertation describes constraints: client-server separation, statelessness, cacheability, uniform interface, and layered system. Richardson’s levels are a practical ladder toward that uniform interface. You can read Fielding’s original work at the University of California REST architecture page. Fowler’s essay remains the clearest short introduction at martinfowler.com.

What are the four levels of the Richardson Maturity Model?

Each level adds one major design constraint. Skipping a level usually creates hidden coupling. Clients embed assumptions that break when you rename a route or split a monolith.

Level 0: The swamp of POX

Level 0 means one URI and one HTTP method—almost always POST—for every operation. The body carries an action name and payload. This is RPC over HTTP, not REST. It works for legacy bridges and quick prototypes. It fails under public traffic because caches cannot help you and gateways cannot infer intent from the verb.

POST /api/rpc
Content-Type: application/json

{
  "action": "createOrder",
  "product_id": 42,
  "qty": 2
}

On a real client project I saw this pattern survive for years. Every mobile release hard-coded action strings. Renaming createOrder to placeOrder required coordinated app store submissions. That pain is exactly what higher levels prevent.

Level 1: Resources

Level 1 splits operations across resource URIs. You stop tunneling actions through one endpoint. Each noun gets its own path. Many teams still POST everything to those paths, so they sit halfway between 0 and 2.

POST /api/orders        → create
POST /api/orders/15     → update (action in body)
POST /api/products/42   → fetch detail (should be GET)

Resource-oriented URLs help SEO-friendly URL design on public sites too. The same thinking applies to APIs: stable, readable paths age better than opaque RPC tunnels.

Level 2: HTTP verbs and status codes

Level 2 is where most serious REST APIs land in 2026. You map operations to HTTP methods. GET reads. POST creates. PUT or PATCH updates. DELETE removes. You return meaningful status codes: 201 on create, 404 when missing, 409 on conflict, 422 on validation failure.

GET    /api/v1/orders/15      → 200 OK
POST   /api/v1/orders         → 201 Created
PATCH  /api/v1/orders/15      → 200 OK
DELETE /api/v1/orders/15      → 204 No Content

Level 2 also implies correct use of safe and idempotent methods. GET must not change server state. PUT and DELETE should be idempotent. POST creates new resources. Clients, proxies, and CDNs rely on those semantics. Laravel’s API resources and Form Requests make Level 2 straightforward on PHP 8.3+ with Laravel 13.x.

Level 3: Hypermedia controls (HATEOAS)

Level 3 adds hypermedia as the engine of application state. Responses include links that tell the client what it may do next. The client discovers actions from the representation instead of from out-of-band documentation alone.

{
  "id": 15,
  "status": "pending",
  "total": 2500,
  "_links": {
    "self": { "href": "/api/v1/orders/15" },
    "cancel": { "href": "/api/v1/orders/15/cancel", "method": "POST" },
    "pay": { "href": "/api/v1/orders/15/payments", "method": "POST" }
  }
}

Full HATEOAS is rare outside large public APIs. Stripe and GitHub expose rich metadata but still expect developers to read docs. For a booking portal or legal-tech intake API, Level 2 plus a maintained OpenAPI file is usually enough. You can validate payloads during development with a JSON formatter and viewer before they hit integration tests.

Level 2 REST Request FlowClientMobile or SPAGatewayRate limit + authLaravel APIRoutes + policyMySQLPersistent dataPATCH /api/v1/bookings/88422 if validation fails404 if booking missing200 with JSON body on successCorrect verb + status = Level 2 compliance
Level 2 Richardson Maturity Model flow: HTTP verbs, validation, and meaningful status codes through a Laravel API

How do you score and upgrade an existing API on the Richardson Maturity Model?

Scoring is a short audit. List your endpoints. Mark the HTTP method each one accepts. Note whether responses include hypermedia links. Count how many operations still POST to a single RPC URL. That spreadsheet tells you your level in an hour.

  1. Inventory endpoints. Export routes from Laravel with php artisan route:list --path=api or grep your OpenAPI file.
  2. Flag Level 0 patterns. Any /api/execute or action-in-body POST goes on a fix list.
  3. Normalize resources. Replace verb-heavy paths like /getUser with /users/{id}.
  4. Align verbs and codes. GET for reads, PATCH for partial updates, 201 with Location header on create.
  5. Document contracts. Publish OpenAPI 3.1 even if you skip full HATEOAS.
  6. Add hypermedia selectively. Embed _links only where clients benefit—pagination, multi-step workflows.

For projects I have worked on—booking systems, eCommerce carts, legal intake portals—the biggest win is usually Level 1 to Level 2. Resource URLs already exist. The team only misused POST and ignored status codes. Fixing that cuts integration bugs before you touch hypermedia.

Versioning belongs in this conversation too. When you break Level 2 semantics, ship /api/v2 rather than silently changing behaviour. See model versioning patterns for related lifecycle thinking. Pair route design with Laravel route model binding so invalid IDs return 404 automatically.

LevelURI patternHTTP usageClient couplingTypical fit
0Single endpointPOST onlyVery highLegacy RPC, quick internal scripts
1Per-resource pathsOften POST for allHighEarly CRUD APIs, some WP REST plugins
2Resource-orientedGET POST PATCH DELETEModerateMobile backends, partner APIs, SaaS
3Resource + linksVerbs + HATEOASLowPublic platforms, long-lived SDK consumers

Most teams should target Level 2 with excellent documentation and tests. Level 3 costs more to build and maintain. Your API testing and optimization budget may deliver more value than embedding links in every DTO.

Level 2 HTTP Method MapGETSafe readPOSTCreate newPATCHPartial updateDELETERemoveStatus codes clients expect201 + Location on POST create204 empty body on DELETE success422 validation, 409 conflictLevel 2 = verbs plus meaningful responses
Richardson Maturity Model Level 2: map GET, POST, PATCH, and DELETE to safe reads, creates, updates, and deletes

How does the Richardson Maturity Model compare to OpenAPI and JSON:API?

These tools solve different problems. Richardson levels describe architectural style. OpenAPI describes a machine-readable contract. JSON:API describes a response envelope. You can be Level 2 with plain JSON and no OpenAPI. You can publish OpenAPI while still stuck at Level 0 RPC.

OpenAPI shines at Level 2 and above. It documents paths, methods, schemas, and error shapes. Client generators consume it. CI pipelines diff breaking changes. That documentation layer does not automatically give you HATEOAS. Some teams add link objects manually to reach partial Level 3 while keeping OpenAPI as the source of truth.

JSON:API pushes you toward consistent resource structure and relationship links. It nudges you up the maturity ladder but does not replace correct HTTP semantics. A JSON:API endpoint that always returns 200 OK on errors is still weak at Level 2.

For Laravel 13.x projects I prefer: Level 2 routes, API Resources for output shaping, Form Requests for input, Sanctum or Passport for auth, and an OpenAPI spec checked into the repo. That stack covers most enterprise application integrations without forcing full hypermedia on every response.

What do real production APIs look like at each Richardson level?

Honest scoring beats aspirational labelling. Many public APIs marketed as “RESTful” sit at Level 1 or low Level 2. That is acceptable if documentation is clear and versioning is disciplined.

A WooCommerce or WordPress REST plugin often exposes resource paths but uses POST where GET would suffice. Custom Laravel booking APIs—for trek agencies or appointment systems—typically reach solid Level 2 when built with standard controllers and policies. Payment callbacks are a common exception: gateways POST opaque payloads to a single webhook URI, which looks like Level 0 but is dictated by the provider, not your design.

On legal-tech portals I have shipped, document upload and case status endpoints stayed at Level 2. Clients needed predictable JSON, not discovery links. Hypermedia would have helped almost nobody. Conversely, a public directory with many optional filters might embed pagination links in responses—a pragmatic slice of Level 3.

If you want reference implementations, study the GitHub REST API documentation for Level 2 done at scale. Compare that to your own routes using regex testing on path patterns and contract tests in CI.

Pick Your Target REST LevelNew API project?Internal onlyTight deadlinePartner APIMobile + web clientsPublic platformUnknown clientsLevel 1 OKDocument wellTarget Level 2OpenAPI + testsLevel 2 + linksPartial Level 3Richardson Maturity Model: match level to client diversity and API lifespan
Decision guide for Richardson Maturity Model levels based on audience, lifespan, and integration complexity

Portfolio examples reflect this range. A Laravel booking and CRM API benefits from Level 2 semantics because mobile and admin clients share endpoints. A custom eCommerce API with cart and delivery zones needs idempotent updates and clear 409 responses when inventory shifts. Public law-firm sites expose mostly HTML; their JSON endpoints for lead capture still deserve Level 2 verbs even if the surface is small—see Court Marriage In Nepal for a content-heavy portal pattern.

Operational concerns sit beside maturity. Stateless Level 2 APIs scale horizontally behind load balancers. Cache headers on GET reduce origin load. Those wins disappear if you tunnel everything through POST. For infrastructure alignment, read about Linux API hosting and PHP-FPM tuning and keep Redis 8.10 available for rate limiting and session storage where needed.

Security does not map one-to-one to maturity level. A Level 3 API with broken auth is worse than a Level 1 API behind OAuth and tight scopes. Still, Level 2 status codes help clients fail visibly. Returning 401 versus 403 versus 404 is part of a coherent security story. Combine maturity upgrades with custom backend hardening rather than treating REST levels as a checkbox exercise.

Key Takeaways

  • The Richardson Maturity Model ranks REST APIs from Level 0 RPC through Level 3 HATEOAS—higher is not always better for every product.
  • Most production Laravel and PHP APIs should aim for Level 2: resource URIs, correct HTTP verbs, and meaningful status codes.
  • Audit with php artisan route:list, flag single-endpoint POST tunnels, and fix verbs before adding hypermedia links.
  • OpenAPI documents your contract; it does not by itself move you up the maturity ladder.
  • Payment webhooks and legacy bridges may stay Level 0 by necessity—isolate them instead of letting RPC patterns spread.
  • Match target level to client diversity: internal tools tolerate Level 1; partner and public APIs deserve Level 2 or selective Level 3.

People Also Ask

Who created the Richardson Maturity Model?

Leonard Richardson introduced the model in a 2008 talk at the QCon San Francisco conference. Martin Fowler wrote the widely cited article that names the four levels and the Level 0 “swamp of POX” label. The model remains informal industry vocabulary rather than an ISO standard.

Is HATEOAS required for a REST API?

According to Roy Fielding’s REST dissertation, hypermedia is part of the uniform interface constraint. In practice, most working APIs stop at Level 2 and use OpenAPI for discovery. Full HATEOAS pays off when you have many unknown client types and long API lifetimes.

What is the difference between REST and Level 2?

Level 2 captures one slice of REST: proper HTTP method usage and status codes. Full REST also expects statelessness, cacheability, layered systems, and optionally hypermedia. Teams often say “REST API” when they mean “Level 2 JSON HTTP API”—knowing the gap prevents mismatched expectations.

Can GraphQL score on the Richardson Maturity Model?

The model was designed for resource-oriented HTTP APIs. GraphQL uses a single endpoint and POST-heavy queries, which resembles Level 0 surface shape. That does not mean GraphQL is wrong—it solves different client fetch problems. Compare trade-offs per use case instead of forcing GraphQL into Richardson levels.

Apply the Richardson Maturity Model on your next API

Start with an honest score of your current endpoints. Fix resource paths and HTTP verbs before chasing hypermedia. Publish OpenAPI, add contract tests, and treat maturity as an incremental path—not a rewrite mandate. When you want a second pair of eyes on route design, auth, or Level 2 compliance, review the portfolio of shipped Laravel and API projects or reach out via contact us to discuss an architecture review. The Richardson Maturity Model explained in this guide is only useful once it matches your codebase—and once your clients can integrate without reading your Slack history.

Frequently Asked Questions

A four-level staircase for REST API design, from single-endpoint RPC to hypermedia-driven APIs. Each step adds constraints that align your API with how the web actually works.

Level 0 is one URI and POST for every operation (RPC over HTTP). Level 1 splits operations across resource URIs. Level 2 maps operations to correct HTTP verbs and status codes. Level 3 adds hypermedia links so clients discover next actions from responses instead of hard-coded docs alone.

Leonard Richardson introduced it in a 2008 talk at QCon San Francisco. Martin Fowler popularised the four levels in a 2010 essay, including the Level 0 swamp of POX label. It remains informal industry vocabulary, not an ISO standard.

Level 0 means one URI and one HTTP method, almost always POST, for every operation. The request body carries an action name and payload. This is RPC over HTTP, not REST. It works for legacy bridges and quick prototypes but fails under public traffic because caches cannot help and gateways cannot infer intent from the verb.

Level 1 introduces resource-oriented URLs. Each noun gets its own path instead of tunneling every action through one endpoint. Many teams still POST everything to those paths, so they sit halfway between Level 0 and Level 2. Resource paths reduce client coupling compared to action strings in a single RPC tunnel.

Level 2 maps operations to HTTP methods: GET reads, POST creates, PUT or PATCH updates, DELETE removes. Responses use meaningful status codes like 201 on create, 404 when missing, 409 on conflict, and 422 on validation failure. GET must not change state; PUT and DELETE should be idempotent. Most serious REST APIs land here in 2026.

Level 3 adds hypermedia as the engine of application state. Responses include links telling the client what it may do next, such as cancel or pay actions on an order. The client discovers operations from the representation rather than out-of-band documentation alone. Full HATEOAS is rare outside large public platforms; Stripe and GitHub expose rich metadata but still expect developers to read docs.

Export routes with php artisan route:list --path=api or grep your OpenAPI file. Flag Level 0 patterns like /api/execute or action-in-body POST. Normalize verb-heavy paths to resource URLs. Align GET for reads, PATCH for partial updates, and 201 with Location header on create. Publish OpenAPI 3.1 even without full HATEOAS. On booking systems and legal intake portals, the biggest win is usually Level 1 to Level 2 before touching hypermedia.

Most teams should target Level 2 with excellent documentation and tests. Level 3 costs more to build and maintain, and your API testing budget may deliver more value than embedding links in every DTO. Internal tools can tolerate Level 1; partner and public APIs deserve Level 2 or selective Level 3. Payment webhooks and legacy bridges may stay Level 0 by necessity—isolate them rather than letting RPC patterns spread.

Richardson levels describe architectural style; OpenAPI describes a machine-readable contract. You can be Level 2 with plain JSON and no OpenAPI, or publish OpenAPI while still stuck at Level 0 RPC. OpenAPI shines at Level 2 and above by documenting paths, methods, schemas, and error shapes for client generators and CI diffing, but it does not automatically give you HATEOAS.

JSON:API pushes consistent resource structure and relationship links, nudging you up the maturity ladder, but it does not replace correct HTTP semantics. A JSON:API endpoint that always returns 200 OK on errors is still weak at Level 2. Richardson levels describe how RESTful your HTTP usage is; JSON:API describes a response envelope format. They solve different problems and can coexist.

Roy Fielding's REST dissertation treats hypermedia as part of the uniform interface constraint. In practice, most working APIs stop at Level 2 and use OpenAPI for discovery. Full HATEOAS pays off when you have many unknown client types and long API lifetimes. For a booking portal or legal-tech intake API, Level 2 plus a maintained OpenAPI file is usually enough.

Level 2 captures one slice of REST: proper HTTP method usage and status codes. Full REST also expects statelessness, cacheability, layered systems, and optionally hypermedia. Teams often say REST API when they mean Level 2 JSON HTTP API. Knowing the gap prevents mismatched expectations during architecture reviews and client integrations.

The model was designed for resource-oriented HTTP APIs. GraphQL uses a single endpoint and POST-heavy queries, which resembles Level 0 surface shape. That does not mean GraphQL is wrong—it solves different client fetch problems. Compare trade-offs per use case instead of forcing GraphQL into Richardson levels.

No. A Level 3 API with broken auth is worse than a Level 1 API behind OAuth and tight scopes. Security does not map one-to-one to maturity level. Still, Level 2 status codes help clients fail visibly: returning 401 versus 403 versus 404 is part of a coherent security story. Combine maturity upgrades with proper auth hardening rather than treating REST levels as a security checkbox.

Share this article

0 Comments

Leave a comment

Your email is not published. Comments appear once they have been read. Sign in to have your details filled in.

Quick Contact Options
Choose how you want to connect me: