InterviewPrepKit

Home / Cheat Sheet / System Design

Cheat sheet

How to design a REST API

Read the full lesson →

A REST API is a contract: clear to call, safe to retry, changeable without breaking existing clients.

Resources and methods

Model nouns as resources with stable IDs; let the method carry the verb. Keep paths plural and hierarchical (/orders/{id}/items), never /createOrder.

MethodMeaningSafeIdempotent
GET /orders/{id}Read oneyesyes
GET /ordersListyesyes
POST /ordersCreatenono
PUT /orders/{id}Replacenoyes
PATCH /orders/{id}Partial updatenono
DELETE /orders/{id}Removenoyes
  • Safe: no side effects, cacheable.
  • Idempotent: repeating leaves the same server state, so retry after a timeout is fine.
  • POST is neither, so a dropped response after a create is dangerous.

Request chain (cheap rejections first)

Each stage can reject before expensive work runs.

Client -> Gateway (TLS, routing) -> AuthN/AuthZ -> Rate limit
       -> Validate/parse -> Handler -> Data store -> Response

Auth fails before rate limiting spends a lookup; rate limiting rejects before validation parses; validation catches bad input before the handler hits the store.

Status codes

  • 2xx: 200 OK read/update, 201 Created (return Location), 202 Accepted (async), 204 No Content (delete).
  • 4xx: 400 malformed, 401 missing/invalid creds, 403 authenticated-but-not-allowed, 404 missing/hidden, 409 state clash (dup create), 422 semantically invalid, 429 rate limited.
  • 5xx: server fault.
  • Retry 5xx and 429; never blindly retry other 4xx (the request itself is wrong).

Consistent error body

Same machine-readable shape everywhere so clients branch without parsing prose.

  • code: stable enum the client switches on.
  • message: prose for a human.
  • request_id: lets support trace one call in the logs.
  • details: optional per-field issues.

Pagination (never unbounded)

  • Offset/limit (?limit=50&offset=100): simple, jumpable; slow on deep pages (DB walks and discards skipped rows), unstable under inserts/deletes.
  • Cursor (?limit=50&cursor=...): opaque pointer to last item; stable under writes, maps to indexed range scan. Prefer for large or fast-changing collections.
  • Filter/sort via query params (?status=paid&sort=-created_at); each filterable field implies an index.

Versioning

  • Put major version in path (/v1/orders) for visibility and cache-friendliness.
  • Additive = compatible: new endpoint, new optional request field, new response field.
  • Subtractive = breaking: remove/rename a field, change a type, make optional required, change default behavior.
  • Deprecate on a timeline: announce, emit Deprecation header, remove after the window.

Auth: authenticate then authorize

Authentication = who you are; authorization = what you may do (in that order).

  • API keys: identify a caller, good server-to-server; scope and rotate.
  • OAuth 2.0 / OIDC: short-lived access tokens (+ refresh) for user-facing and third-party.
  • JWT: self-contained signed token, no DB lookup; fast but hard to revoke, so keep lifetime short.
  • Enforce authorization in the service layer, never only the client.
Want the full picture? The lesson has the derivations, worked examples, and diagrams this card compresses into bullets. Read the full lesson →
Report a bug