REST API design hasn't changed its fundamentals in over a decade, and that's the point: resources, representations, and a small fixed set of HTTP methods and status codes are still the most boring, most interoperable way to expose a service over HTTP. What has changed is the tooling around it — OpenAPI 3.1 as a near-universal contract format, JSON:API and similar conventions maturing into defaults rather than niche opinions, and a broader industry consensus on the handful of design decisions that used to be argued from scratch on every new project.
Model resources, not actions
The single highest-leverage decision in REST API design is naming things as resources (nouns) rather than actions (verbs): POST /invoices/4471/payments instead of POST /processPayment. This isn't pedantry — it's what makes the rest of HTTP's machinery (caching, idempotency semantics, uniform status codes) apply predictably. When an operation genuinely doesn't fit the resource model — triggering a batch export, say — model it as a resource anyway: POST /exports creates an export job resource that the client can then GET to check status, rather than inventing a bespoke RPC-style action endpoint.
POST /v1/exports HTTP/1.1
Content-Type: application/json
{"type": "invoices", "format": "csv", "filter": {"status": "open"}}
HTTP/1.1 202 Accepted
Location: /v1/exports/9931
{"id": 9931, "status": "pending"}
Status codes as a small, fixed vocabulary
Pick a small set and use it consistently rather than reaching for an obscure status code because it's technically more precise: 200/201/202/204 for success, 400/401/403/404/409/422 for client error, 500/503 for server error, is enough vocabulary for the overwhelming majority of APIs. 422 Unprocessable Entity specifically for validation failures on an otherwise well-formed request, distinct from 400 for malformed requests, is the one distinction worth being deliberate about — it lets a client distinguish "you sent garbage" from "you sent valid JSON that failed a business rule," which are different bugs on the client's side.
Pagination and filtering as defaults, not afterthoughts
Every collection endpoint should be paginated from day one, even the ones that "will never have more than a handful of records" — that assumption is wrong often enough that retrofitting pagination onto a stable API is a breaking change, while shipping it up front costs nothing when the collection is small. Cursor-based pagination (?after=cursor_token) beats offset-based (?page=3) for anything backed by a frequently-changing table, since offset pagination skips or duplicates rows when records are inserted or deleted between page requests.
Writing the OpenAPI 3.1 spec first and generating both server-side validation and client SDKs from it keeps the contract and the implementation from drifting apart — the alternative, hand-written docs next to a hand-written implementation, reliably goes stale the first time someone ships a field without updating both.
Idempotency keys for anything that moves money or state irreversibly
Any POST that creates a side effect a client might legitimately retry — a payment, an order, a provisioning request — needs an idempotency key so a network timeout followed by a retry doesn't create the resource twice. This is table stakes for payment APIs now (Stripe popularized the pattern and most billing-adjacent APIs have converged on it) and is worth adopting even outside payments, anywhere a duplicate side effect is worse than a slightly more complex request contract.
Resource shapes should reflect what the client needs, not a 1:1 mirror of internal tables — a foreign key column name, an internal enum value, or a join artifact showing up in the response is a sign the API is exposing implementation rather than designing a contract, and it means every internal refactor risks becoming a breaking API change.
Wrapping up
The 2026 version of good REST API design is mostly the same discipline it's always been — resources over actions, a small consistent status code vocabulary, pagination and idempotency built in from the start — with better tooling (OpenAPI 3.1, generated SDKs) making that discipline cheaper to maintain than it used to be. The fundamentals didn't change; the excuses for skipping them got weaker.
Independent software engineer in Nairobi specialising in Acumatica customisations, Laravel backends, and tax fiscalisation integrations across East and Southern Africa.