A well-designed REST API feels obvious: developers can guess the endpoints, predict the responses, and recover from errors without reading pages of docs. A poorly designed one fights its users at every turn. The difference comes down to a handful of conventions that have proven themselves over years. This guide walks through the principles that make an API age well.
Model resources, not actions
REST is built around resources — nouns, not verbs. A URL identifies a thing (/users, /users/42, /users/42/orders), and the HTTP method says what to do with it. Avoid endpoints like /getUser or /createOrder; the method already conveys the action. Use plural nouns consistently, and nest relationships only one level deep to keep URLs readable.
Use HTTP methods for their meaning
- GET — read a resource, never causing side effects.
- POST — create a new resource.
- PUT — replace a resource entirely; PATCH — update it partially.
- DELETE — remove a resource.
Honouring these meanings lets caches, proxies and clients reason about your API. GET in particular must be safe and idempotent — calling it should never change data.
Return the right status codes
Status codes are the API’s first line of communication. Return 201 when you create, 204 when there is nothing to return, 400 for malformed requests, 401 versus 403 for authentication versus authorization, 404 for missing resources, 422 for validation failures, and 429 when rate-limiting. Never wrap an error in a 200 response.
Version from day one
APIs change, and breaking existing clients is costly. Put a version in the path (/v1/users) or a header from the start, so you can evolve without forcing every consumer to update at once. Treat removing a field or changing its type as a breaking change that warrants a new version.
Be consistent and predictable
Consistency is worth more than cleverness. Use the same naming style everywhere, the same pagination scheme on every list endpoint, the same error shape for every failure, and the same date format throughout. A predictable API is one developers can learn once and use everywhere.