What Is REST?

REST (Representational State Transfer) is an architectural style, not a protocol. It defines a set of constraints for how web services should behave. When an API follows these constraints, we call it RESTful. The key idea is simple: a client sends a request to a URL that represents a resource, and the server responds with a representation of that resource — usually JSON.

The six constraints that define REST are: client-server separation, statelessness, cacheability, uniform interface, layered system, and code on demand (optional). In practice, the ones that matter most day-to-day are statelessness and uniform interface. Statelessness means each request must contain all the information needed to process it — the server does not store session state between requests. Uniform interface means using standard HTTP methods and predictable URL patterns.

diagram showing REST client-server stateless request-response cycle with resource representation

HTTP Methods and Their Meaning

HTTP methods tell the server what action to perform on a resource. Each method carries a specific semantic meaning that you should respect — ignoring this leads to APIs that are confusing and hard to consume.

GET retrieves a resource without side effects. POST creates a new resource. PUT replaces an existing resource entirely. PATCH partially updates a resource. DELETE removes a resource.

Here is how these map to a typical users resource:

text
GET /users → list all users
GET /users/42 → get user with id 42
POST /users → create a new user
PUT /users/42 → replace user 42 entirely
PATCH /users/42 → update specific fields of user 42
DELETE /users/42 → delete user 42

GET and DELETE are idempotent — calling them multiple times produces the same result. PUT is also idempotent. POST is not — calling it twice usually creates two resources.

HTTP Status Codes

Status codes tell the client what happened. They are grouped into five classes: 1xx informational, 2xx success, 3xx redirection, 4xx client error, 5xx server error. The ones you will use most often in API development are:

200 OK — the request succeeded and there is a response body. Use this for successful GET and PATCH responses.

201 Created — a resource was successfully created. Use this after a successful POST. Include a Location header pointing to the new resource.

204 No Content — success, but no body to return. Use this for DELETE.

400 Bad Request — the client sent invalid data (missing fields, wrong types, validation failures).

401 Unauthorized — the request lacks valid authentication credentials.

403 Forbidden — the client is authenticated but does not have permission.

404 Not Found — the resource does not exist.

409 Conflict — the request conflicts with current state (for example, creating a user with an email that already exists).

422 Unprocessable Entity — the request is well-formed but fails semantic validation.

500 Internal Server Error — something went wrong on the server. Never expose stack traces here in production.

A concrete example in an Express handler:

javascript
app.post('/users', (req, res) => {
const { email, name } = req.body;
if (!email || !name) {
return res.status(400).json({ error: 'email and name are required' });
}
// imagine createUser() saves to a database and returns the new record
const user = createUser({ email, name });
res
.status(201)
.location(`/users/${user.id}`)
.json(user);
});
flowchart of HTTP status code decision tree: success path 2xx vs client error 4xx vs server error 5xx

HTTP Headers in API Context

Headers carry metadata about the request or response. A handful are essential for REST APIs.

Content-Type declares the format of the request or response body. For JSON APIs this is always application/json. Express sets this automatically when you call res.json(), but when building raw responses you must set it explicitly.

Accept tells the server what format the client can handle. Clients should send Accept: application/json when calling a JSON API.

Authorization carries credentials. The most common pattern for REST APIs is Bearer token authentication:

text
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

Cache-Control directs caching behavior for GET responses. For public data that rarely changes, setting Cache-Control: public, max-age=300 reduces load on your server. For user-specific or sensitive data, use Cache-Control: no-store.

In Express you can read incoming headers via req.headers and set outgoing ones via res.set():

javascript
app.get('/products', (req, res) => {
const products = getProducts();
res
.set('Cache-Control', 'public, max-age=300')
.json(products);
});

Summary

REST is an architectural style built on stateless client-server communication with a uniform interface. HTTP methods define what action to take on a resource — GET reads, POST creates, PUT replaces, PATCH updates, DELETE removes. Status codes communicate the outcome precisely: 2xx for success, 4xx for client mistakes, 5xx for server failures. Headers carry metadata like content type, auth credentials, and cache directives. Getting these fundamentals right is what separates an API that is easy to integrate with from one that forces consumers to guess.

Lesson Checkpoint

1. Which REST constraint means that each request must contain all the information needed to process it, and the server does not store session state between requests?

2. You want to partially update a user's email address without replacing the entire user record. Which HTTP method is most appropriate?

3. Which of the following HTTP methods is NOT idempotent?

4. A client sends a POST request to create a new resource and the server succeeds. What is the most appropriate status code to return?

5. A user is logged in but tries to access an admin-only endpoint they do not have permission to use. Which status code should the server return?

6. Which HTTP header should a client include to tell the server it expects a JSON response?

7. In the Express example from the lesson, what does res.json() do automatically that you would otherwise have to set manually?