codingstairs
NotesEDULifeContact
⌕Search⌘K
koen

Navigation

  • Intro
  • Blog
  • Life

Get in touch

Send without signing in. Add your email if you'd like a reply.

  • Leave a message anonymously →
  • ✉ warragon112@gmail.com
  • KakaoTalk Open Chat ↗

© 2026 codingstairs

  • Notes
  • EDU
  • Search
  • Life
  • Contact
  • Legal
  • RSS
  • GitHub
Notes›backend

REST API introduction

Published 2026-04-28· Updated 2026-05-18·0 views

REST API introduction — resources and verbs

When writing an API on top of HTTP, REST is the word that comes up most often. It stands for Representational State Transfer, organized in Roy Fielding's 2000 doctoral dissertation.

1. About REST

Event Time
Roy Fielding "Architectural Styles" doctoral dissertation 2000
RFC 7230 ~ 7235 (HTTP/1.1 reorganized) 2014
OpenAPI 3.0 2017
HATEOAS resurfaces in discussion 2010s

The 6 constraints Fielding presented in the dissertation:

① Client-Server          — separation of concerns
② Stateless              — each request is independent
③ Cacheable              — responses declare cacheability
④ Uniform Interface      — consistent interface
⑤ Layered System         — intermediaries are transparent
⑥ Code on Demand (optional) — rarely used

The most violated constraint is HATEOAS — including links to next possible actions in the response. It is usually omitted in real-world JSON APIs.

Over time the meaning has loosened, often used to mean "a JSON API that uses HTTP verbs."

2. Resource-centric design

The core of REST is "URLs point to resources, HTTP verbs point to actions." Verbs do not go into the URL.

Good shape:
GET    /users          (list)
GET    /users/123      (one)
POST   /users          (create)
PATCH  /users/123      (partial update)
DELETE /users/123      (delete)

Common antipatterns:
GET /getUsers
POST /createUser
POST /users/123/delete

Resource names are usually plural nouns. Nested resources only when the parent-child relationship is clear.

GET /users/123/posts        (posts of user 123)
POST /users/123/posts       (create a post for user 123)

3. HTTP verbs and CRUD

Verb Meaning Idempotent Safe
GET Read O O
POST Create / arbitrary action X X
PUT Replace whole O X
PATCH Partial update Usually X (depends on impl) X
DELETE Delete O X
  • Safe — does not change resource state.
  • Idempotent — repeated requests yield the same result.

The difference between PUT and PATCH is meaning — PUT replaces the resource with the body, while PATCH modifies parts. In practice, PATCH is used more often.

4. Response codes

Code Use
200 OK Success (with body)
201 Created Creation succeeded. Location header points to the new resource.
204 No Content Success, no body (DELETE etc.)
400 Bad Request Input error
401 Unauthorized Not authenticated
403 Forbidden Authenticated but no permission
404 Not Found Resource not found
409 Conflict Concurrency / duplicate
422 Unprocessable Entity Validation failure (semantic error)
429 Too Many Requests Rate limit
500 Internal Server Error Server error
503 Service Unavailable Transient outage

The boundary between 400 and 422 is a matter of opinion. A common flow is 400 when JSON itself is broken, 422 when the format is fine but the meaning does not fit.

5. Pagination

Offset-based:

GET /posts?page=3&size=20
GET /posts?offset=40&limit=20

The strength is arbitrary page jumps and UI friendliness. The downsides are that large offsets get slower (the DB has to skip OFFSET rows) and that concurrent inserts and deletes cause omissions or duplicates.

Cursor-based:

GET /posts?cursor=eyJpZCI6MTIzfQ&limit=20

The response includes nextCursor. The client sends it in the next request. The strengths are O(1) paging and concurrency safety. The downside is that arbitrary page jumps are hard.

There are many opinions that cursors are recommended for large datasets and real-time feeds. Places where arbitrary jumps are needed, like admin UIs, use offsets.

6. Filtering, sorting, searching

Conventions exist but are not standards.

GET /posts?status=published&author=123&sort=-createdAt&search=react
  • sort=field or sort=-field (negative prefix for descending).
  • q or search for free-text search.
  • Filters as simple parameters (status=published).

For complex filters, separate standards (JSON:API · OData · GraphQL) sometimes take over.

Reducing response size (sparse fieldset):

GET /users/123?fields=id,name,email

JSON:API and GraphQL standardize this. In REST it remains a convention.

7. Comparison with GraphQL · gRPC · tRPC

Candidate Place
REST Standard, general purpose. The majority of public APIs.
GraphQL Mobile and varied clients, places where the response shape changes often.
gRPC Internal service-to-service, where performance and schema matter.
tRPC Fast development inside TS monorepos.

GraphQL (Facebook, 2015) — the client defines the response shape with a query. Strengths are solving over-fetching and under-fetching, single endpoint, and a strong schema. Downsides are caching difficulty, learning curve, and N+1 risk.

gRPC (Google, 2015) — Protobuf serialization + HTTP/2 + code generation. Strengths are very high speed, a strong schema, and automatic multi-language SDKs. Downsides are hard to use directly from a browser and complex debugging (binary).

tRPC — clients and servers share the same types in a TypeScript monorepo. Strengths are automatic type sharing without code generation and fast development. Downsides are TypeScript dependence and difficulty with non-TS clients.

8. Idempotency-Key · ETag

A convention to backstop idempotency on POST. Stripe popularized it.

POST /payments
Idempotency-Key: 2025-04-25-abc123

The server treats the same key on retries as the same response. Useful for payments and other critical side effects.

ETag with If-Match · If-None-Match:

  • ETag — a resource version identifier in the response.
  • If-None-Match — same ETag returns 304 Not Modified.
  • If-Match — PUT/DELETE allowed only when the ETag matches (optimistic concurrency).

9. Common pitfalls

Doing everything via POST — that is not REST. The flow of putting verbs in URLs follows. Separate into GET/POST/PATCH/DELETE wherever possible.

Non-standard error responses — somewhere it is {"error": "..."}, somewhere else it is {"message": "..."}. Consider adopting RFC 7807 (application/problem+json).

Missing status codes — every response is 200 with success: false in the body. Clients struggle to distinguish ordinary flows from errors.

Missing versioning — URL-based like /v1/users or header-based versioning. The place where compatibility-breaking changes happen later.

N+1 queries — fetching a collection plus each item's relations one by one explodes. Eager loading or joins.

Heavy responses — returning 1000 rows at once. Enforce pagination.

CORS — preflight when the browser calls a different-origin API. Check Access-Control-Allow-Origin and -Allow-Methods.

Closing thoughts

REST is more a collection of conventions than a standard. There is no single right answer, but keeping just one or two promises like "no verbs in URLs" makes consistency visible quickly. For externally exposed APIs, pairing RFC 7807 with an OpenAPI spec is operationally safer.

Next

  • websocket-sse

See Roy Fielding dissertation · RFC 9110 — HTTP Semantics · RFC 7807 — Problem Details · OpenAPI Spec · GraphQL · gRPC.

More in backend

All in this category →
  • Wrap public OpenAPIs with your own BFF
  • Email Delivery and OTP — SMTP
  • Audit Log — logAdminAction pattern
  • WebSocket and SSE — real-time communication
  • OpenAPI Specification
  • Crawler ethics and tooling