Most API design advice is really HTTP trivia — which status code, which verb, which URL shape. Those choices matter, but they are also the easy, reversible part. The decisions that actually determine whether an API ages well or gets rewritten in two years are the expensive-to-reverse ones: how you version, whether writes are safe to retry, and how consistently you tell a client what went wrong. Get those right and the URL conventions barely matter; get them wrong and no amount of REST purity saves you.
What changed in 2026
- Idempotency keys became expected, not optional, for any API that takes payments or triggers side effects, following the pattern popularized by Stripe.
- OpenAPI-first design overtook code-first design as the default starting point for new APIs — see the OpenAPI spec guide for 2026.
- Structured, machine-parseable error responses (RFC 9457 Problem Details) gained real adoption after years of every API inventing its own error shape.
- Deprecation headers (
Sunset, Deprecation) became common enough that API gateways now surface them automatically in client dashboards.
Design decisions that are expensive to reverse
| Decision |
Why it is expensive later |
Get it right by |
| Versioning strategy |
Every consumer has to migrate on your timeline |
Committing to one strategy before the first external client |
| Resource shape |
Renaming a field breaks every client parsing it |
Modeling the consumer's need, not your database columns |
| Idempotency |
Retrofitting safe retries means auditing every write path |
Requiring an idempotency key on every mutating endpoint |
| Pagination style |
Switching from offset to cursor breaks integrations |
Picking cursor-based pagination up front for large collections |
None of these are visible in a demo. All four are exactly what determines whether your third-party integrations still work after the fifth major release.
A consistent error taxonomy
{
"type": "https://api.example.com/errors/insufficient-funds",
"title": "Insufficient funds",
"status": 422,
"detail": "Account balance is lower than the requested transfer amount.",
"instance": "req_9f2a1c",
"code": "INSUFFICIENT_FUNDS"
}
Same shape every time: a type, a human title, the status, a specific detail, a request id for support, and a stable machine-readable code a client can branch on. A client written against this shape once handles every endpoint's errors forever, instead of special-casing each one.
Common mistakes
Modeling resources after database tables. A join table or a normalization detail leaking into the API forces every consumer to understand your schema instead of your domain.
Treating versioning as something to add later. Retrofitting a version scheme onto an API with existing unversioned clients means every future change has to guess who is still on the old shape.
Making writes unsafe to retry. A network timeout after a write actually succeeded is common; without an idempotency key, the client's only options are risking a duplicate or risking a lost write.
Inventing a new error shape per endpoint. Five endpoints, five error formats, and every client integration needs five branches of error-handling code instead of one.
FAQ
Should I version in the URL or in a header?
URL path versioning (/v1/...) is the pragmatic default — it is explicit, cacheable, and testable directly in a browser or curl. Header versioning is cleaner but harder to debug and document.
What counts as a breaking change?
Removing or renaming a field, changing a field's type, tightening validation, or changing authentication requirements. Adding a new optional field is not breaking and does not need a new version.
How long should a deprecated version stay alive?
Long enough for your slowest real consumer to migrate — often 6 to 12 months for external APIs — communicated with a firm sunset date, not an open-ended "eventually."
Does REST have a monopoly on good API design?
No. Stable contracts, idempotent writes, and consistent errors apply whether the transport is REST, GraphQL, or gRPC; see REST vs GraphQL vs gRPC compared for how each protocol expresses them differently.
Where to go next
See the OpenAPI spec guide for 2026 for turning these decisions into a shared contract, REST vs GraphQL vs gRPC compared for how protocol choice interacts with them, and what a cookie is on the web in 2026 for the session mechanics many API auth flows still lean on.