Lesson 10 of 129
REST API Design
REST (Representational State Transfer) is an architectural style for networked systems described by Roy Fielding. In practice, a "REST API" is an HTTP API organized around resources: named things (a user, an order) that clients read and modify by exchanging representations of them, usually JSON, using standard HTTP methods.
Constraints of the REST style
- Client-server: separates UI concerns from data storage.
- Stateless: each request contains all information needed to process it. The server keeps no client session state between requests.
- Cacheable: responses declare whether they can be cached.
- Uniform interface: resources are identified by URLs, manipulated through representations, messages are self-descriptive, and (in the strict form) hypermedia drives state transitions.
- Layered system: proxies, gateways, and caches can sit between client and server.
Statelessness has design consequences. Any server instance can handle any request, so servers scale horizontally behind a load balancer. Authentication data (a token) is sent with every request rather than stored in a server-side session tied to one machine. The cost is larger requests and repeated authentication work.
Resources and URLs
Model nouns, not actions. Use plural collection names and hierarchical paths for containment.
| Purpose | URL |
|---|---|
| Collection of orders | /orders |
| One order | /orders/1001 |
| Items within an order | /orders/1001/items |
| Filtered, sorted collection | /orders?status=shipped&sort=-created_at |
Guidelines:
- Use nouns in paths (
/orders), and let the HTTP method express the action. - Keep nesting shallow. Prefer
/items/55or/orders/1001/itemsover deep chains such as/customers/1/orders/2/items/3/parts/4. - Use query parameters for filtering, sorting, and pagination (see pagination, idempotency, and versioning).
- Operations that do not map to CRUD can be modeled as sub-resources (
POST /orders/1001/cancellation) or as an action endpoint (POST /orders/1001:cancel). Choose one convention and apply it consistently.
HTTP methods
Two properties define method semantics:
- Safe: does not change server state. Safe methods can be prefetched and retried freely.
- Idempotent: applying the same request several times has the same effect on server state as applying it once. Idempotent methods can be retried after a timeout without further protection.
| Method | Typical use | Safe | Idempotent |
|---|---|---|---|
GET |
Read a resource or collection | Yes | Yes |
HEAD |
Same as GET without body | Yes | Yes |
POST |
Create a resource, or run a non-idempotent action | No | No |
PUT |
Replace a resource at a known URL (full update) | No | Yes |
PATCH |
Partial update | No | Not guaranteed by definition |
DELETE |
Remove a resource | No | Yes |
Notes:
PUTreplaces the whole representation, so repeating it leaves the same state. Fields omitted from aPUTbody are reset or removed.PATCHsends only the changes. Formats include JSON Merge Patch (RFC 7396, a partial JSON object wherenullremoves a field) and JSON Patch (RFC 6902, a list of operations such asadd,replace,remove). A patch can be idempotent (set name = "x") or not (increment counter, or JSON Patchaddto an array), depending on the format and content.DELETEis idempotent in terms of state: after the first call the resource is gone, and later calls do not change anything further, although the response code may differ (404instead of204).POSTis not idempotent, so a retry after a timeout can create a duplicate. Idempotency keys address this.GETmust not change state, because caches, crawlers, and prefetchers issue GETs freely.
Status codes
| Class | Meaning | Common codes |
|---|---|---|
| 2xx | Success | 200 OK, 201 Created (with Location header), 202 Accepted (asynchronous processing), 204 No Content |
| 3xx | Redirection | 301 permanent, 302/307 temporary, 304 Not Modified |
| 4xx | Client error | 400 malformed request, 401 unauthenticated, 403 forbidden, 404 not found, 405 method not allowed, 409 conflict, 412 precondition failed, 415 unsupported media type, 422 semantic validation failure, 429 too many requests |
| 5xx | Server error | 500 internal error, 502 bad gateway, 503 unavailable, 504 gateway timeout |
Points of precision:
401means the credentials are missing or invalid.403means the caller is identified but not permitted.- Clients should treat
4xxas errors that retrying will not fix (except429and sometimes409or408), and5xxas potentially transient. - Return a structured error body with a machine-readable code and a human-readable message. The Problem Details format (RFC 9457, which replaced RFC 7807) standardizes this as
application/problem+jsonwith fields such astype,title,status, anddetail. - A
405response includes anAllowheader listing the methods the resource supports.
Request flow example
sequenceDiagram
participant C as Client
participant S as API server
C->>S: POST /orders (JSON body)
S-->>C: 201 Created, Location: /orders/1001
C->>S: GET /orders/1001
S-->>C: 200 OK, ETag "v1", body
C->>S: GET /orders/1001, If-None-Match "v1"
S-->>C: 304 Not ModifiedCaching headers
HTTP caching lets clients, proxies, and CDNs reuse responses.
Cache-Control: max-age=60: the response is fresh for 60 seconds.publicallows shared caches to store it,privaterestricts it to the client's own cache,no-storeforbids storing, andno-cacheallows storing but requires revalidation before reuse.- Validators:
ETag(an opaque version identifier) andLast-Modified. On a later request the client sendsIf-None-MatchorIf-Modified-Since. If unchanged, the server returns304 Not Modifiedwith no body, saving bandwidth. - Optimistic concurrency: an update sends
If-Match: "<etag>". If the resource changed since, the server returns412 Precondition Failed, preventing lost updates. Varylists request headers that affect the response (for exampleAccept-Encoding), so caches key entries correctly.
Only GET and HEAD responses are cached in practice. Responses that contain user-specific data should be private.
Representations and content negotiation
The client states what it accepts with Accept (application/json) and what it sends with Content-Type. Compression uses Accept-Encoding and Content-Encoding. JSON is the common format, and the schema of request and response bodies is described with a specification such as OpenAPI.
HATEOAS
HATEOAS (Hypermedia as the Engine of Application State) means responses include links describing the actions available next, so a client follows links instead of constructing URLs from documentation.
{
"id": 1001,
"status": "pending",
"_links": {
"self": { "href": "/orders/1001" },
"cancel": { "href": "/orders/1001/cancellation" },
"payment": { "href": "/orders/1001/payment" }
}
}It lets servers change URLs and expose only currently valid transitions (a shipped order has no cancel link). Most production JSON APIs skip it, and describe URLs in documentation, so they satisfy fewer REST constraints than the strict definition requires.
Design trade-offs
- Over-fetching and under-fetching: fixed resource shapes can return more fields than needed or force several round trips. GraphQL and field selection parameters address this.
- Chatty clients: many small calls raise latency. Composite endpoints or an API gateway can aggregate.
- Versioning and evolution: adding optional fields is compatible; removing or changing meaning is not.
- Internal RPC: for high-volume service-to-service calls, gRPC offers a binary format and generated clients.
Interview questions
- What is the difference between PUT and POST? PUT targets a known URL and replaces the resource, and is idempotent. POST usually targets a collection, lets the server assign the identifier, and is not idempotent.
- What does stateless mean, and why does it help scaling? The server keeps no per-client state between requests, so any instance can serve any request, and instances can be added or removed freely behind a load balancer.
- How do you prevent lost updates in a REST API? Return an ETag with the resource and require
If-Matchon updates. A mismatch yields412, so the client refetches and retries. - When is 401 correct versus 403? 401 for missing or invalid authentication, 403 when the authenticated caller lacks permission.
