REST API Fundamentals
REST is an architectural style for networked APIs built on resources, representations, and the uniform interface of HTTP. Learn the constraints that make an API truly RESTful.
Prerequisites: HTTP Request and Response, HTTP Methods
Learning objectives
- Explain REST as an architectural style and list its core constraints.
- Model a domain as resources with clean, noun-based URIs and JSON representations.
- Use HTTP methods and status codes correctly to express operations on resources.
- Place an API on the Richardson Maturity Model and explain the role of HATEOAS.
Simple explanation
Think of a well-organized library. Every book has a stable address — a shelf location you can point to — and you interact with it using a small, fixed set of verbs: *borrow*, *return*, *read*, *remove*. You don't need a new instruction manual for each book; the same verbs work everywhere. REST applies that same idea to APIs. Your data is organized into resources (books, users, orders), each with a stable URI (its address), and you act on them with the same small set of HTTP verbs (GET, POST, PUT, PATCH, DELETE) that already exist on the web.
REST (Representational State Transfer) is not a protocol, a library, or a framework. It is an *architectural style* — a set of constraints described by Roy Fielding in his 2000 PhD dissertation. When an API honors those constraints, it inherits the scalability and simplicity of the web itself.
Technical explanation
REST is defined by a handful of constraints. Follow them and your system is RESTful; break them and you lose the guarantees.
- Client–server — the client (UI) and server (data storage) are separated by a uniform interface, so they can evolve independently.
- Statelessness — every request contains all the information needed to process it. The server stores no client session state between requests; state lives on the client (or in a resource).
- Cacheability — responses must declare whether they are cacheable (via headers like
Cache-ControlandETag), so clients and intermediaries can reuse them safely. - Uniform interface — the cornerstone of REST. It has four sub-constraints: identification of resources (URIs), manipulation through representations, self-descriptive messages, and HATEOAS (hypermedia as the engine of application state).
- Layered system — a client cannot tell whether it is talking to the origin server or an intermediary (a proxy, gateway, or load balancer), which enables caching, security, and scaling layers.
- Code on demand *(optional)* — servers may extend clients by shipping executable code (e.g. JavaScript).
The central abstraction is the resource: any concept worth naming — a user, an article, a collection of orders. A resource is identified by a URI; what travels over the wire is a representation of that resource, usually JSON. Crucially, the URI is a *noun* (the thing), and the HTTP method is the *verb* (the action). GET /articles/42 fetches article 42; DELETE /articles/42 removes it. You never put the action in the URL (/getArticle, /deleteArticle).
Why it matters
Almost every backend you will build or consume exposes a REST-style HTTP API: SaaS products, mobile backends, public developer platforms (Stripe, GitHub, Twilio). Designing along REST's constraints gives you predictable, self-documenting endpoints, free HTTP caching, and clients that don't break when the server changes internally. Getting it wrong — verbs in URLs, 200 OK on failures, ignoring status codes — produces APIs that are hard to cache, hard to debug, and hard to evolve.
How it works
Designing a REST API is mostly resource modeling plus disciplined use of HTTP:
- Identify resources. Nouns from your domain:
articles,users,comments. Use plural collection names. - Assign URIs. A collection (
/articles) and its members (/articles/42). Nest to show ownership:/articles/42/comments. Keep nesting shallow (avoid more than two levels). - Map methods to operations.
GETreads,POSTcreates in a collection,PUTreplaces,PATCHpartially updates,DELETEremoves. Respect safety (GETnever mutates) and idempotency (PUT/DELETErepeat safely;POSTdoes not). - Return correct status codes.
200 OK,201 Created(+Locationheader),204 No Content,400 Bad Request,401/403,404 Not Found,409 Conflict,422 Unprocessable Entity,500. - Choose representations. JSON by default; use
Content-TypeandAcceptfor content negotiation. Support filtering, sorting, and pagination via the query string:GET /articles?status=published&sort=-createdAt&page=2. - Add hypermedia (optional but ideal). Include links in representations so clients can discover related actions without hardcoding URLs.
The Richardson Maturity Model
Leonard Richardson's model grades how "RESTful" an API is across four levels:
- Level 0 — The Swamp of POX. A single URI, one method (usually
POST), tunneling everything through the body. This is plain RPC over HTTP (e.g. old SOAP endpoints). - Level 1 — Resources. Many URIs, one per resource, but still one method for everything. You have nouns, not yet verbs.
- Level 2 — HTTP verbs. URIs *and* the proper HTTP methods and status codes. This is where the vast majority of "REST" APIs in production actually sit, and it is a perfectly good target.
- Level 3 — Hypermedia controls (HATEOAS). Responses include links that tell the client what it can do next, so the API becomes self-descriptive and navigable.
HATEOAS, briefly
HATEOAS (Hypermedia As The Engine Of Application State) means a client drives the application purely by following links the server provides, rather than by hardcoding URLs. A response for an order might include {"status": "pending", "_links": {"cancel": {"href": "/orders/9/cancel"}}}. When the order ships, the cancel link disappears — the server communicates *what is possible now*. Full HATEOAS (Level 3) is rare in practice, but the idea of returning links (pagination next/prev, related resources) is widely and usefully applied.
REST vs RPC
RPC (Remote Procedure Call) style APIs expose *actions* as endpoints — /createUser, /sendEmail — and typically POST everything. REST exposes *resources* and relies on HTTP's uniform verbs. RPC can feel natural for operation-centric designs (and gRPC is excellent for internal service-to-service calls), while REST shines for resource-centric, cacheable, broadly consumed web APIs. They are different tools; REST's advantage is that it reuses the web's existing, well-understood semantics.
Important terminology
- Resource — any named concept the API exposes (a user, an article, a collection).
- Representation — the concrete serialized form of a resource sent over the wire, usually JSON.
- Uniform interface — the constraint that all resources are manipulated through the same standard operations and self-descriptive messages.
- Idempotency — repeating a request yields the same server state (
GET,PUT,DELETE);POSTis generally not idempotent. - HATEOAS — using hypermedia links in responses to drive client navigation and available actions.
Key definitions
- Resource
- Any named concept the API exposes — a user, an article, a collection — identified by a stable URI.
- Representation
- The serialized form of a resource sent over the wire, typically JSON, negotiated via Content-Type and Accept.
- Uniform interface
- The core REST constraint: resources are identified by URIs and manipulated through standard, self-descriptive HTTP messages.
- HATEOAS
- Hypermedia As The Engine Of Application State — responses include links so clients discover actions instead of hardcoding URLs.
Must memorize
Must memorize
- REST is an architectural style, not a protocol; its heart is the uniform interface.
- URIs are nouns (the resource); HTTP methods are the verbs (the action).
- The six constraints: client–server, stateless, cacheable, uniform interface, layered system, and (optional) code on demand.
- Richardson levels: 0 = one URI/one verb (RPC), 1 = resources, 2 = HTTP verbs + status codes, 3 = HATEOAS.
Real-world example
The GitHub REST API
GitHub exposes resources like repositories, issues, and pull requests with clean noun-based URIs (GET /repos/{owner}/{repo}/issues), proper HTTP methods, and JSON representations. Its responses include pagination links in the Link header — a practical touch of HATEOAS that lets clients page through results without constructing URLs by hand.
A blog API endpoint set
A typical blog backend models articles and their comments: GET /articles lists them, POST /articles creates one and returns 201 with a Location header, GET /articles/42 fetches one, PATCH /articles/42 edits a field, DELETE /articles/42 removes it, and GET /articles/42/comments lists that article’s comments through shallow nesting.
Code example
# Collection
GET /articles # list articles (supports ?status=&sort=&page=)
POST /articles # create an article -> 201 Created + Location
# Member
GET /articles/42 # fetch one article -> 200 OK (or 404)
PUT /articles/42 # full replace -> 200 OK / 204 No Content
PATCH /articles/42 # partial update -> 200 OK
DELETE /articles/42 # remove -> 204 No Content
# Nested sub-collection (shallow)
GET /articles/42/comments # list comments for article 42
POST /articles/42/comments # add a comment -> 201 CreatedA resource-oriented route table for an articles API.
{
"id": 42,
"title": "Understanding REST",
"slug": "understanding-rest",
"status": "published",
"authorId": 7,
"createdAt": "2026-01-10T09:30:00Z",
"tags": ["rest", "http", "api"],
"_links": {
"self": { "href": "/articles/42" },
"author": { "href": "/users/7" },
"comments": { "href": "/articles/42/comments" }
}
}A JSON representation of a single article resource, with hypermedia links.
const res = await fetch('https://api.example.com/articles', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: 'Bearer ' + token,
},
body: JSON.stringify({ title: 'Understanding REST', status: 'draft' }),
});
console.log(res.status); // 201
console.log(res.headers.get('Location')); // /articles/42
const article = await res.json(); // the created representationCreating an article and reading the Location of the new resource.
Common mistakes
Mistake
Putting verbs in URLs, e.g. GET /getArticles or POST /createArticle.
Do this instead
Use nouns for resources and let the HTTP method be the verb: GET /articles, POST /articles, DELETE /articles/42.
Mistake
Returning 200 OK for every response, including errors, and signaling failure only in the body.
Do this instead
Use status codes that match the outcome: 400/422 for bad input, 401/403 for auth, 404 for missing, 409 for conflicts, 5xx for server faults.
Interview questions
Quiz
Flashcards
Show answer · Space