HTTP Semantics, Richardson Maturity Model and HATEOAS

Read a raw HTTP request, learn which methods are safe and idempotent, see Fielding’s REST constraints, the Richardson levels 0–3 and hypermedia links in…

HTTP semantics and REST maturity: common questions

Is PATCH idempotent?

Not by definition. RFC 9110 and the PATCH spec make no idempotency promise, because a patch such as “add one seat” changes the result each time. A particular PATCH can be designed to be idempotent, but clients may not assume it.

What are the levels of the Richardson Maturity Model?

Level 0 sends every call as a POST to one URL. Level 1 adds a URL per resource. Level 2 uses HTTP methods and status codes correctly. Level 3 adds hypermedia links that tell the client what it can do next. Most public APIs stop at level 2.

Related chapters

Keep learning

Overview

Host: api.tickets.example Accept: application/json Authorization: Bearer eyJhbGciOi… Content-Type: application/json Event pages are public, so no token is needed. The client asked for JSON and got JSON. Still works: with no Accept header the server falls back to its default format. Saying what you want is still the better habit. 401 Unauthorized HTTP/1.1 401 Unauthorized\nWWW-Authenticate: Bearer Booking needs to know who is paying. The WWW-Authenticate header tells the client which kind of credential to send. 415 Unsupported Media Type HTTP/1.1 415 Unsupported Media Type\nAccept: application/json The body arrived with no Content-Type, so the server refuses to guess how to parse it. 201 Created Every part is in place. Location points at the new booking, so the client knows its address without building it. Lab: assemble a request, read the response Request line What goes on the wire What comes back Level 0 · one URL, one verb HTTP is only a tunnel. Every call is a POST to the same address, and even a failure comes back as 200, so proxies, caches, monitoring and retry logic learn nothing. Classic SOAP and many home-made RPC APIs live here. Level 1 · resources Things now have their own addresses, which is easier to read and route. But reading and cancelling still look the same on the wire, so nothing between client and server can tell a safe call from a dangerous one. Level 2 · HTTP methods and status codes HTTP/1.1 201 Created\nLocation: /bookings/9\n\n(seat gone: HTTP/1.1 409 Conflict) Methods and codes mean what HTTP says they mean. A cache knows GET is safe, a client knows DELETE can be retried, and a dashboard can count 4xx and 5xx. This is where most public APIs stop. Level 3 · hypermedia controls The response also says what the client can do next and where. The app follows the “pay” link instead of gluing URLs together, so the server can move or change steps without shipping a new app. Lab: John books seats A1 and A2, at each maturity level Lab: Priya’s booking 9, and the links the server offers Event starts in under 24 hours Start over GET /bookings/9 0.3rem 0 0 No action links, so no action buttons. Seats are held for a few minutes. The server offers “pay” and “release”, and nothing else. Paid. “cancel” is offered because the venue’s rule allows it more than 24 hours before the show. Toggle the clock and watch it vanish. Paid, but the show is under 24 hours away, so the server leaves out “cancel”. The app hides the button without knowing the rule.

Under REST: HTTP semantics, maturity levels and hypermedia

The REST chapter used HTTP like a vocabulary: paths, verbs, status codes. This one opens the box. You will read a raw HTTP message, learn the promises each method makes, see what Roy Fielding actually meant by REST, place APIs on the Richardson maturity ladder, and decide when links in responses are worth the effort.

A raw HTTP message, line by line

Under every library call, a request is plain text with a fixed order. This is John booking two seats, as an HTTP/1.1 server reads it, with notes added on the right: Request lineThe method, the target path with any query, and the protocol version. One line, nothing else. HeadersMetadata about the message: who is calling, what format the body is in, what format the reply should be in. Host is required in HTTP/1.1, since one server can host many sites. Blank lineHow the parser knows the headers are over. Content-Length then tells it how many bytes of body to read. Status lineThe response starts with version, code and reason: HTTP/1.1 201 Created. Then headers, a blank line and a body, the same shape as the request. HTTP/2 and HTTP/3 send the same message as binary frames instead of text, but the meaning (methods, headers, status codes) is identical, so everything below applies to all three. Build one yourself:

Every method makes promises: safe, idempotent, cacheable

The client asks for no change. A crawler, a prefetching browser or a link checker may call it freely. GET /bookings/9 must never cancel anything. reusable answer A cache may store the response and reuse it. In practice that means GET and HEAD. How to do it well is in the efficiency chapter. The failure mode: a team writes GET /bookings/9/cancel because it is easy to test in a browser. Then a link-preview bot or a prefetch visits the URL and cancels Priya’s booking. Breaking a method’s promise breaks every tool that trusted it. Caching and ETags live in the efficiency chapter the patterns chapter

REST is an architectural style, not a URL format

Roy Fielding described REST in his 2000 PhD dissertation as the set of constraints behind the web’s success. It is not a standard and has no spec to validate against. Each constraint takes away a freedom and gives back a property. Here is what each one buys the ticket site: The app owns the screens, the server owns the data. The Android app and the website evolve on their own schedules against one API. scale out Each request carries everything needed, including the token. Any of 20 booking servers can answer it, and a crashed one loses no session. Responses say whether they may be reused. The event page for a Coldplay show can be served from a CDN to a million fans. Layered system middle boxes The client cannot tell whether it talks to the server or to a gateway, cache or load balancer in front. You can add those without touching the app. Uniform interface the core Every resource is used the same way: same methods, same codes, self-describing messages, links. Generic tools work on every API. Next section. Code on demand Stateless is the one people break most often, usually with a server-side “current cart” that only one machine remembers. Principle 4

The uniform interface, in four parts

every resource has a URI change it by sending a representation each message explains itself responses say what comes next Resource identification Manipulation through representations The client never touches the booking itself. It gets a JSON picture of it, and changes it by sending a picture back (PUT, PATCH). The server may store it any way it likes. Self-descriptive messages A message carries what is needed to process it: the method, Content-Type, cache headers, status code. A proxy can handle it without knowing your business. Hypermedia as the engine of state The client moves through the workflow by following links the server put in the response, the way you move through a website by clicking. Section 7 shows it live.

The Richardson maturity model: four levels of “RESTful”

In 2008 Leonard Richardson described the stages he saw teams go through when adopting REST, and Martin Fowler’s write-up made it famous. Each level uses more of HTTP. Same interaction, four ways:

Content negotiation: one resource, several representations

406 Not Acceptable 415 Unsupported Media Type About the request. Asha uploads a seating plan with Content-Type: text/csv and the endpoint only reads JSON. The server cannot parse what it was given. The same mechanism also carries API versions and hypermedia formats: Accept: application/hal+json asks for the linked flavour. Error bodies have their own media type, application/problem+json, covered in the payload chapter

Hypermedia: links that change with the state

At level 2 the app hard-codes the rules: “show Cancel if status is confirmed and the show is more than 24 hours away”. Every app version copies that rule, and when the venue changes it to 48 hours, old apps are wrong until users update. With hypermedia the server includes a cancel link only while cancelling is allowed, and the app shows the button only if the link is there: Adds _links and _embedded to plain JSON. Small and easy to adopt, but links carry only an address, not the method or fields. Built for lists: items, links, query templates and a write template. A good fit for admin screens like Asha’s list of events.

Where to stop: level 2 or level 3?

Stop at level 2 Clear resources, correct methods and codes, an OpenAPI spec. Clients are written once by people reading docs, often generated from the spec. Cheaper to build, and what most public APIs, Stripe’s and GitHub’s included, ship. Go to level 3 Workflows with many states (booking, refund, approval), clients you cannot force to update (mobile apps, partners’ systems), and rules that change often. The server moves the workflow without a client release. Cost: bigger responses Cost: client discipline It only pays off if apps really follow links. One app that builds URLs by hand loses the benefit and still pays the cost. Middle ground Many teams add only self, paging links and a few state-dependent actions like cancel. That captures most of the value. A good rule: be fully correct at level 2 everywhere, then add links where the state machine lives. For the ticket site that is the booking and payment flow, not the event search. Push-style updates for those state changes (webhooks, SSE) are a different tool, see polling, SSE and webhooks (opens in a new tab).

In the interview

“I’d build to Richardson level 2: resources as nouns, methods that keep their HTTP promises (GET safe, PUT and DELETE idempotent, POST guarded by an idempotency key), and real status codes, which is what lets caches, gateways and retries work. The API is stateless so any node can serve any request. For the booking workflow I’d add hypermedia links, so a booking only carries a cancel link while it is cancellable, and the cancellation rule lives on the server, not in every app version.” REST’s remaining weak spot is the busy screen: an event page that needs the event, the venue, the seat map and Priya’s bookings means four round trips. GraphQL was built for exactly that. Spotify documents 202, 204 and 304 in its status table, and answers If-None-Match with 304. Status codes in Spotify ETags and snapshot_id on Spotify playlists. Caching on Spotify

More courses

  • Jobs, linked to lessons — Browse jobs where every requirement links to the chapter that teaches it. See how ready you are, how long the gap takes to close, and which listings look stale.
  • Match a job post to courses — Paste a job post. Each skill is matched to a track here and put in learning order, foundations first.
  • React from open source with patterns — Patterns extracted from Material UI, Radix, React Aria, React Hook Form, Redux Toolkit, TanStack, and Next.js — not slides about hooks.
  • Database in depth — How a query becomes work. Indexes, isolation, locks, and the plans that explain why a page is slow — not an ORM tour.
  • Build a real API with NestJS — One ticket-booking API, built in order: a plain Node server first, then NestJS modules, validation, a real database, and the features real clients lean on.
  • Microservices — Microservice patterns one diagram at a time: how to split a monolith, how services talk, and how data stays consistent without distributed transactions.
  • Kafka — A beginner-to-senior path through event logs, reliable delivery, production operations, and disaster recovery.
  • AI engineering for software engineers — Eight free reads, in order, for software engineers moving into AI: when to build an agent, how to build one, how to test it, and how the model works underneath.
  • Frontend system design — How a UI is sliced when it is a product, not a page: ownership of state, cache, routes, and what happens when the network lies.
  • TypeScript in depth — The type system as a design tool. Inference, narrowing, generics, and the errors that mean the model is wrong — not a catalog of utility types.
  • CSS in depth — See the box, then the page. Visual chapters from the box model through Flexbox surprises, Grid, selectors, and units, then backgrounds, shapes, and visual effects, each with a playground.
  • Accessibility — Foundations first (WCAG in plain words, semantic HTML, lists, alt text), then hands-on HTML labs, a full pass of WAI-ARIA 1.3, and a final fix-the-page challenge.
  • Docker — What an image is, why layers cache, and how containers find each other on a network.
  • Redis — Fifteen Redis patterns, one picture each: cache, session, lock, counter, rate limiter, queue, and when Redis is the wrong tool.
  • Kubernetes — Kubernetes from zero to operators: why it exists, Pods, Deployments and Services, then configuration, networking, storage, scheduling, scaling and security.