The idea came from a doctoral thesis describing why the web scaled: addressable resources, a uniform interface, stateless requests, cacheable responses, and responses that tell the client what it can do next. Applied to APIs, most of that survived and the last part did not. A working REST API names its things as nouns in the path, uses GET to read them, POST to create, PUT or PATCH to change and DELETE to remove, returns the status code that describes what happened, and documents its shapes in a machine-readable schema. Clients call the addresses they were told about rather than discovering them from responses, which purists regret and nobody has changed.
The four properties worth insisting on
Resources are nouns at stable addresses, so a customer is at one place and stays there. Methods mean what HTTP says they mean, so a GET never changes anything and a PUT can be safely repeated. Status codes tell the truth, so a failure is a 4xx or 5xx and never a 200 with an error inside the body. And a published schema, in the OpenAPI format almost everyone has settled on, lets a client be generated and validated before the first call. An API with those four is a pleasure to integrate against; each one missing costs every consumer hours.
The alternatives answer different problems. GraphQL lets a client ask for exactly the fields it needs across related objects in one request, at the cost of a query language and a server that must guard against expensive queries. gRPC uses a binary encoding and generated code for fast, typed calls between services that both sides control. Neither replaces REST for the public, browser-facing, cache-friendly case, and most systems run REST at the edge and something else between their own services. The developer certifications examine the discipline directly: the AWS developer and Azure DevOps papers assume you can read an API definition, and the Cisco automation exam gives APIs a fifth of its weight.
- Version in the path or a header, and never break an existing version; consumers you have never met depend on it.
- Paginate lists, because the collection that fits in one response today will not next year.
- Make writes idempotent where you can, so a client that retried after a timeout does not create two orders.
- Rate-limit and say so, with a 429 and a header that says when to try again.
- Return errors in one consistent shape, with a machine-readable code and a human-readable message, so every consumer handles them the same way.
