LearnFrenzy
Sign in Take a free test

REST API Fundamentals · Lesson 3 of 30

REST Architecture Constraints and the Richardson Maturity Model

4 min read Updated Nov 8, 2026 Saurabh Samir

"RESTful" is used loosely – often it just means "JSON over HTTP". Strictly, REST is a set of constraints: rules an architecture follows to get scalability, simplicity and evolvability. Knowing them helps you make better design decisions and answer a very common interview question properly.

In this lesson

  • The six REST constraints and what each buys you
  • Statelessness in practice
  • The Richardson Maturity Model
  • HATEOAS – hypermedia links, shown live

The six constraints

ConstraintRuleBenefit
Client–serverUI and data storage are separateclients and servers evolve independently
Statelesseach request carries all the context it needsany server can handle any request – easy horizontal scaling
Cacheableresponses say whether they can be cachedfewer requests, faster clients, less server load
Uniform interfaceresources with URLs, standard methods, self-descriptive messages, hypermediaany client can talk to any REST API the same way
Layered systemclients can't tell if they talk to the server or an intermediaryload balancers, CDNs, gateways and caches can sit in between
Code on demand (optional)servers may send executable coderarely used for APIs

Statelessness in practice

Stateless means the server keeps no client session between requests – not that the application has no state. Data lives in the database; who the user is travels with every request:

# stateless: every request identifies itself
GET /api/cart HTTP/1.1
Authorization: Bearer eyJhbGciOiJIUzI1NiJ9…

# not RESTful: the server must remember what "next" means for this client
GET /api/orders/next-page HTTP/1.1

Why stateless scales

  1. Request 1the load balancer sends it to server A
  2. Request 2goes to server B – fine, it carries its own token and parameters
  3. Server A restartsno client notices; nothing was stored in its memory

The Richardson Maturity Model

Leonard Richardson described four levels of "how RESTful" an HTTP API is:

From RPC over HTTP to full REST

  1. Level 3 – Hypermediaresponses include links to related actions and resources (HATEOAS)
  2. Level 2 – HTTP verbsGET, POST, PUT, DELETE and proper status codes – where most good APIs are
  3. Level 1 – Resourcesmany URLs (/orders/1), but everything is still POST
  4. Level 0 – One endpointPOST /api with an "action" in the body – RPC tunnelled over HTTP
# Level 0                                  # Level 2
POST /api  {"action": "getOrder", "id": 7} GET    /api/orders/7
POST /api  {"action": "cancelOrder", …}    DELETE /api/orders/7

Hypermedia As The Engine Of Application State means a response tells the client what it can do next, through links – like a web page's links tell you where you can go. The client follows links instead of hard-coding every URL:

// server.js
import express from 'express';

const app = express();
const orders = { 7: { id: 7, status: 'pending', total: 1499 }, 8: { id: 8, status: 'shipped', total: 899 } };

function withLinks(order) {
  const self = `/api/orders/${order.id}`;
  const links = { self: { href: self }, items: { href: `${self}/items` } };
  if (order.status === 'pending') {
    links.pay = { href: `${self}/payment`, method: 'POST' };       // only offered while pending
    links.cancel = { href: self, method: 'DELETE' };
  }
  if (order.status === 'shipped') {
    links.track = { href: `${self}/tracking` };
  }
  return { ...order, _links: links };
}

app.get('/api/orders/:id', (req, res) => {
  const order = orders[req.params.id];
  if (!order) return res.status(404).json({ error: 'Order not found' });
  res.json(withLinks(order));
});

app.listen(process.env.PORT ?? 3000);

Real responses

$ curl http://localhost:3000/api/orders/7
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8

{
  "id": 7,
  "status": "pending",
  "total": 1499,
  "_links": {
    "self": {
      "href": "/api/orders/7"
    },
    "items": {
      "href": "/api/orders/7/items"
    },
    "pay": {
      "href": "/api/orders/7/payment",
      "method": "POST"
    },
    "cancel": {
      "href": "/api/orders/7",
      "method": "DELETE"
    }
  }
}

$ curl http://localhost:3000/api/orders/8
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8

{
  "id": 8,
  "status": "shipped",
  "total": 899,
  "_links": {
    "self": {
      "href": "/api/orders/8"
    },
    "items": {
      "href": "/api/orders/8/items"
    },
    "track": {
      "href": "/api/orders/8/tracking"
    }
  }
}

The pending order offers pay and cancel; the shipped one offers track instead. The server – not every client – owns the rules about what's allowed. Formats such as HAL (the _links style used here) and JSON:API standardise this. In practice, many production APIs stop at Level 2, but links for pagination and related resources are common and very useful.

Be pragmatic

Aim for solid Level 2: meaningful resource URLs, correct methods and status codes, statelessness and cache headers. Add hypermedia where it removes real coupling – pagination links, state-dependent actions – rather than for its own sake.

Practice

Try it yourself

  1. Rewrite these Level 0 calls as Level 2 requests: POST /api {"action":"listInvoices"}, POST /api {"action":"getInvoice","id":5}, POST /api {"action":"deleteInvoice","id":5}.

    Show solution
    GET    /api/invoices
    GET    /api/invoices/5
    DELETE /api/invoices/5

Quick check

Which constraint lets any server in a cluster handle any request?

Statelessness.

Which Richardson level uses HTTP verbs and status codes?

Level 2.

What does HATEOAS add?

Links in responses describing what the client can do next.

Summary

  • REST = client–server, stateless, cacheable, uniform interface, layered system (+ optional code on demand).
  • Richardson levels: one endpoint → resources → HTTP verbs → hypermedia.
  • Most good APIs are Level 2; add hypermedia links where they reduce coupling.

Finished this lesson?

Mark it complete to track your progress, then carry on with the next lesson.

Next lesson

Popular