API Architecture

REST APIs

REST is a style for designing HTTP APIs around resources. Get the nouns, methods and status codes right and your API feels obvious to every client.

intermediate15 min readUpdated Sep 15, 2026
routes.js
js
// routes.js
import { Router } from "express";

const router = Router();

router.get("/posts", listPosts);
router.post("/posts", createPost);
router.get("/posts/:id", getPost);
router.patch("/posts/:id", updatePost);
router.delete("/posts/:id", deletePost);

export default router;
Style
Resource-oriented
Nouns
URIs name resources
Verbs
HTTP methods
State
Stateless requests
Format
Usually JSON
Codes
Status codes matter

Why it matters

Why REST still works

Familiar and universal

Every HTTP client already understands methods, status codes and headers, so there is nothing bespoke to learn.

Predictable resources

Consistent naming and behaviour let clients guess endpoints and handle responses without special cases.

Cacheable and stateless

Self-contained requests work with caches, proxies and load balancers, which makes scaling straightforward.

The big picture

The three ideas behind REST

Model resources, use HTTP methods for actions, and keep every request self-contained.

Resources

Model

Nouns in URLs represent things, with collections and individual items.

Methods

Act

GET, POST, PUT, PATCH and DELETE describe what to do, with clear semantics.

Representation

Respond

A status code, headers and a JSON body describe the outcome.

REST at a glance

The core of REST

Nouns, not verbs

Use /posts and /posts/42, not /getPosts or /createPost.

Methods

GET reads, POST creates, PUT replaces, PATCH updates, DELETE removes.

Status codes

200, 201, 204, 400, 401, 403, 404, 409 and 422 each mean something.

Collections and items

A plural collection and a single item by id.

Filtering and pagination

Query parameters for filtering, sorting, paging and field selection.

Consistent errors

One error shape with a code, message and details.

A short history

From SOAP to pragmatic REST

  1. 2000

    REST described

    Roy Fielding names the architectural style in his dissertation.

    00
  2. 2000s

    Web APIs grow

    JSON over HTTP becomes the default for web services.

    2000s
  3. 2010s

    API-first practice

    Documentation, versioning and pagination become expected.

    2010s
  4. 2015

    GraphQL and gRPC

    Alternatives appear, but REST remains the default for public APIs.

    15
  5. Today

    Pragmatic REST

    Teams apply the useful parts of REST without chasing purity.

    Today

The complete guide

REST APIs: Everything you need to know

What is REST?

REST, or Representational State Transfer, is an architectural style for designing HTTP APIs. Instead of inventing commands, you model your domain as resources and use the methods HTTP already defines to act on them. A POST /posts creates a post, GET /posts/42 reads one, PATCH /posts/42 updates it and DELETE /posts/42 removes it.

The value is familiarity. Every HTTP client, proxy, cache and tool already understands methods, status codes and headers. When you follow the conventions, clients can predict how your API behaves without reading a bespoke manual.

Resources and URIs

Resources are the nouns of your API. Use plural collections and identify individual items by id.

GET    /posts
POST   /posts
GET    /posts/42
PUT    /posts/42
PATCH  /posts/42
DELETE /posts/42
  • Use nouns, not verbs. The method is the verb.
  • Use plural collection names consistently.
  • Keep URLs lowercase with hyphens, not underscores or camelCase.
  • Nest only when the relationship is essential, like /posts/42/comments.
  • Do not put the format in the path; use the Accept header.

Deeper nesting gets awkward fast. /users/1/posts/2/comments/3 is hard to build and document; prefer /comments/3 and let clients filter.

Methods and their semantics

Each method has defined semantics that clients and infrastructure rely on.

Method Purpose Safe Idempotent
GET Read a resource or collection Yes Yes
POST Create a resource or trigger an action No No
PUT Replace a resource No Yes
PATCH Partially update a resource No No
DELETE Remove a resource No Yes

Safe means it does not change state; idempotent means repeating it has the same effect as doing it once. Never change data with GET, because clients, crawlers and caches may issue GET requests freely.

Status codes

Return the code that matches what happened. This is the part clients depend on most.

  • 200 OK — success with a body.
  • 201 Created — a resource was created; include a Location header.
  • 204 No Content — success with no body, common for DELETE.
  • 400 Bad Request — malformed request.
  • 401 Unauthorized — authentication missing or invalid.
  • 403 Forbidden — authenticated but not allowed.
  • 404 Not Found — no such resource.
  • 409 Conflict — state conflict, such as a duplicate.
  • 422 Unprocessable Entity — syntactically valid but fails validation.
  • 429 Too Many Requests — rate limited; include Retry-After.
  • 500 Internal Server Error — unexpected server failure.

Returning 200 with { "success": false } hides failures from clients, caches and monitoring, and forces every client to invent its own error handling.

Collections: filtering, sorting and pagination

Collections need a consistent query language.

GET /posts?status=published&sort=-createdAt&limit=20&cursor=abc123
  • Filtering with field=value, and repeated keys for OR.
  • Sorting with sort=field or sort=-field for descending.
  • Pagination with limit and cursor (or page and perPage).
  • Field selection with fields=id,title when clients want less.
  • Search with a dedicated q parameter.

Prefer cursor pagination for large or changing datasets, and always return the next cursor in the response so clients can page without guessing.

{
  "data": [{ "id": "42", "title": "Hello" }],
  "pagination": { "nextCursor": "abc123", "hasMore": true }
}

Representations and responses

Responses are representations of resources. JSON is the norm, with a stable shape.

{
  "id": "42",
  "title": "Hello",
  "createdAt": "2026-09-15T10:00:00Z"
}
  • Use camelCase or snake_case consistently, not both.
  • Use ISO 8601 strings for dates.
  • Use stable ids as strings when clients might exceed number precision.
  • Envelope collections with data and pagination, but return single resources directly.
  • Support Accept and set Content-Type correctly.

Statelessness and caching

Each request should carry everything needed to process it: the URL, method, headers and body. Do not rely on server memory between requests, which is what lets you run many instances behind a load balancer.

Because GET is safe and responses are self-contained, REST works well with HTTP caching. Set Cache-Control and validators such as ETag on cacheable resources, as covered in the HTTP guide.

Errors

Use one error shape everywhere and document it.

{
  "error": {
    "code": "validation_error",
    "message": "Title is required",
    "details": [{ "field": "title", "issue": "required" }]
  }
}

A machine-readable code lets clients branch, a message is safe to show users, and details helps forms highlight fields. Pair it with the right status code.

Best practices

  • Model resources with nouns and let methods express actions.
  • Return the most specific status code you can.
  • Version the API before you need to, and document it (see API Versioning).
  • Paginate every collection and cap limit.
  • Validate input and return structured errors.
  • Use consistent naming and casing throughout.
  • Cache safe GET responses with explicit headers.
  • Rate limit and authenticate (see Rate Limiting).

Common mistakes

  • Verb-based URLs that duplicate HTTP methods.
  • Returning 200 for errors.
  • Unbounded collections with no pagination.
  • Inconsistent casing, date formats or error shapes.
  • Deep nesting that becomes impossible to maintain.
  • Mutating state on GET.
  • Breaking clients by changing response shapes silently.

Where to go next

REST is the default way to expose a backend. Ground it in the HTTP guide, document it with OpenAPI, evolve it safely with API Versioning, and protect it with Rate Limiting. Compare the model with GraphQL when clients need more flexibility.

Naming an endpoint

Name the resource with a noun and let the method express the action. Verb-based paths duplicate HTTP and multiply endpoints.

Prefer
GET    /posts
POST   /posts
GET    /posts/42
PATCH  /posts/42
DELETE /posts/42
Avoid
GET  /getPosts
POST /createPost
POST /updatePost?id=42
POST /deletePost?id=42

Returning errors

Use the status code that matches the failure and a consistent error body. Returning 200 with an error hides failures from clients and caches.

Prefer
// HTTP/1.1 422 Unprocessable Entity
{
  "error": {
    "code": "validation_error",
    "message": "Title is required",
    "details": [{ "field": "title" }]
  }
}
Avoid
// HTTP/1.1 200 OK
{ "success": false, "error": "bad input" }

Trade-offs

Is REST the right default?

REST fits most APIs because HTTP already solves caching, tooling and familiarity. Know where it strains before you commit.

Strengths

  • Familiar to every client

    Methods, status codes and headers are understood by browsers, proxies, caches and libraries, so clients can predict how your API behaves.

  • Caching for free

    GET responses are cacheable by URL, which lets CDNs, browsers and gateways take load off your servers.

  • Simple to design and debug

    Resources map cleanly to nouns and each request is independent, so an endpoint is easy to reason about and test in isolation.

Trade-offs

  • Over-fetching and under-fetching

    A fixed response shape often returns more fields than a screen needs, or forces several round-trips to assemble one view.

  • Chatty for complex screens

    Nested or related data means multiple requests, which hurts mobile clients on slow networks.

  • Versioning is manual

    Without hypermedia, clients hard-code URLs, so evolving the API needs explicit versioning and deprecation.

FAQ

Frequently asked questions

Keep learning

Related topics from the roadmap.

$ start learning

Ready to start learning REST APIs?

Our interactive tutorial walks you through REST APIs step by step — with quizzes and real code you can run in the browser.