REST Architectural Style

Resources, HTTP methods, and the principles behind RESTful API design

What Is REST?

REST (Representational State Transfer) is an architectural style for building web APIs, defined by Roy Fielding in his 2000 doctoral dissertation. The core idea is simple:

  • Resources are identified by URLs (/api/books, /api/books/42)
  • HTTP methods are the verbs that act on those resources (GET, POST, PUT, DELETE)
  • Representations (usually JSON) are how resources are transferred between client and server
  • Each request is stateless — it contains all the information the server needs

Think of it this way: URLs are nouns, HTTP methods are verbs.

CRUD and REST

REST maps the four basic data operations (CRUD) to HTTP methods:

CRUD Operation HTTP Method Collection URL Item URL
Create POST /api/books
Read GET /api/books /api/books/42
Update PUT / PATCH /api/books/42
Delete DELETE /api/books/42

There are two URL patterns:

  • /api/resource — the collection (all books)
  • /api/resource/:id — a specific item (book #42)

URL Design: The RESTful Spectrum

Not all API URLs are equally RESTful. URLs should name resources (nouns), not actions (verbs):

URL RESTfulness Why
GET /api/books/1 RESTful Resource in the URL, method implies action
GET /api/books?id=1 Less RESTful Works, but ID should be in the path
GET /api?record=books&id=1 Not RESTful Resource type hidden in query params
GET /api?id=1&action=delete Definitely not REST Action in URL, wrong HTTP method for delete

Status Codes for REST APIs

A REST API communicates results through HTTP status codes. Using the right code tells the client exactly what happened.

Status Codes by CRUD Operation

Operation Success Common Errors
POST (Create) 201 Created 400 Bad input, 409 Conflict
GET (Read) 200 OK 404 Not found
PUT/PATCH (Update) 200 OK 404 Not found, 400 Bad input
DELETE 200 or 204 No Content 404 Not found

Key client error codes: 400 (malformed request), 401 (not authenticated), 403 (not authorized), 404 (not found), 405 (method not allowed), 409 (conflict), 422 (valid JSON but semantically invalid), 429 (rate limited).

PUT vs PATCH

Both update a resource, but they have different semantics:

Aspect PUT PATCH
Semantics Full replacement — send the entire resource Partial update — send only changed fields
Missing fields Should be set to defaults or removed Left unchanged
Idempotent? Yes — same PUT twice = same result Not guaranteed

Richardson Maturity Model

Leonard Richardson described a maturity model for REST APIs with four levels:

                    ┌─────────────────────┐
                    │     Level 3         │
                    │  Hypermedia Controls│  ← HATEOAS: responses include links
                    │     (HATEOAS)       │    to related actions/resources
                  ┌─┴─────────────────────┴─┐
                  │       Level 2           │
                  │  HTTP Verbs + Status    │  ← GET/POST/PUT/DELETE + proper
                  │       Codes             │    status codes (200, 201, 404...)
                ┌─┴─────────────────────────┴─┐
                │         Level 1             │
                │    Individual Resources     │  ← Different URLs per resource
                │   /users  /books  /orders   │    (/users, /books, /orders)
              ┌─┴─────────────────────────────┴─┐
              │           Level 0               │
              │      "The Swamp of POX"         │  ← One URL, POST everything
              │  POST /api  (do everything here)│    (like XML-RPC or SOAP)
              └─────────────────────────────────┘

Most modern APIs aim for Level 2 and that's generally sufficient. Level 3 (HATEOAS) is the full REST ideal but adds complexity many teams don't need.

HATEOAS

At Level 3, API responses include links that tell the client what it can do next. Instead of hardcoding API URLs, the client discovers them dynamically:

{ "id": 42, "title": "REST in Practice", "author": "Jim Webber", "_links": { "self": { "href": "/api/books/42" }, "update": { "href": "/api/books/42", "method": "PUT" }, "delete": { "href": "/api/books/42", "method": "DELETE" }, "author": { "href": "/api/authors/7" }, "reviews": { "href": "/api/books/42/reviews" } } }

The GitHub API is one of the best real-world examples of HATEOAS. Try curl https://api.github.com/users/tj — the response includes URLs for repos, followers, and organizations without the client needing to construct them.