REST Intro

Conventions That Make Your API Read Like Documentation

REST Intro

REST isn't a spec — it's a set of conventions. Following them makes your API predictable for every dev who hits it.

4 min read Level 1/5 #express#rest#api
What you'll learn
  • Apply REST conventions to URLs and methods
  • Pick the right status codes
  • Shape JSON responses consistently

REST is a set of conventions for HTTP APIs. Follow them and any dev can read your API at a glance.

Resources, Not Actions

URLs name nouns, methods name verbs:

GoodBad
GET /usersGET /listUsers
POST /usersPOST /createUser
DELETE /users/42POST /deleteUser?id=42
PATCH /users/42POST /updateUser?id=42

The verb is in the HTTP method, not the URL.

Pluralize Collections

/users, /posts, /orders — not /user, /post. Even when operating on one item: /users/42. The URL pattern reads as “the user resource with ID 42.”

Methods Map to Operations

MethodWhat it doesIdempotent?
GET /usersListyes
GET /users/42Read oneyes
POST /usersCreateno
PUT /users/42Full replaceyes
PATCH /users/42Partial updateyes-ish
DELETE /users/42Deleteyes

Idempotent = repeating the same call gives the same end state.

Status Codes

Use them with intent:

res.status(200).json(user);           // OK
res.status(201).json(newUser);         // Created
res.status(204).end();                 // No Content (after DELETE)
res.status(400).json({ ... });         // Bad Request (invalid input)
res.status(401).json({ ... });         // Unauthorized (not logged in)
res.status(403).json({ ... });         // Forbidden (no permission)
res.status(404).json({ ... });         // Not Found
res.status(409).json({ ... });         // Conflict (duplicate, version mismatch)
res.status(422).json({ ... });         // Unprocessable (valid format, invalid semantics)
res.status(429).json({ ... });         // Too Many Requests
res.status(500).json({ ... });         // Internal Server Error

The 401 vs 403 distinction trips lots of devs:

  • 401 — “I don’t know who you are” (no/invalid auth)
  • 403 — “I know you, but you can’t”

Consistent Response Shape

Pick one shape for success and one for errors:

// single resource
{ "data": { "id": 1, "name": "Ada" } }

// collection
{ "data": [...], "pagination": { "nextCursor": "...", "total": 100 } }

// error
{ "error": { "code": "user_not_found", "message": "..." } }

Mix shapes ({ user: ... }, { users: [...] }, { data: ... }) and your client code becomes a special-case grab-bag.

Versioning

Bake a version into the URL when you might break clients:

/api/v1/users
/api/v2/users

Bump when you make a breaking change. The other approach (header versioning, Accept: application/vnd.myapi.v2+json) is cleaner in theory and a pain in practice.

Pragmatic Exits

Some operations don’t fit REST:

  • Login? POST /auth/login (creating a session).
  • Trigger a recompute? POST /reports/:id/recompute.
  • Bulk operation? POST /users/bulk-update with a request body.

REST is conventions, not religion. Break them where they don’t help.

Controllers →