Ask five backend developers the difference between a "REST API" and a "RESTful API" and you'll get five different answers — including "there is none." The truth sits somewhere in between: in everyday conversation the two terms are used interchangeably, but they do point at different things, and understanding that difference will make you a better API designer even if you never say "RESTful" out loud again.
Here's the short version before we go deep:
- REST is an architectural style — a set of constraints described by Roy Fielding in his 2000 PhD dissertation.
- A REST API is an API that is built with REST in mind — in practice, usually an HTTP API that uses resources, verbs, and status codes sensibly.
- A RESTful API is an API that actually adheres to the REST constraints — all of them, including the ones almost everybody skips.
So "RESTful" is really a claim of degree of conformance. Most APIs we call REST APIs are only partially RESTful. Let's unpack why.
Where REST actually comes from
REST stands for Representational State Transfer. It isn't a protocol, a library, or a spec — it's an architectural style that Roy Fielding derived while working on the standards that shaped HTTP/1.1. The key insight of his dissertation was that the web itself — pages, links, caches, browsers — scaled to billions of users because of a specific set of architectural constraints. REST is the name for that set.
That origin matters, because it explains the biggest misconception in this whole debate: REST is not "JSON over HTTP." You can build a REST-style system over other protocols, and you can (very easily) build an HTTP+JSON API that violates nearly every REST constraint. Most of the industry has done exactly that, and it's fine — but it's why the "vs" in this article's title exists at all.
The six constraints of REST
For an API to be genuinely RESTful, it needs to satisfy six constraints. When people argue about whether an API is "really RESTful," they're arguing about these.
1. Client–server separation
The client and the server evolve independently. The server exposes resources; the client consumes them. Your API shouldn't know or care whether the caller is a React app, a mobile client, or a cron job. Almost every HTTP API gets this one for free.
2. Statelessness
Every request must contain everything the server needs to process it. The server keeps no session state between requests — no "the user is on step 3 of the wizard" living in server memory.
This is the constraint that makes horizontal scaling trivial: any instance behind the load balancer can serve any request. It's also why token-based auth (a JWT in the Authorization header) is more RESTful than a server-side session:
GET /orders/8412 HTTP/1.1
Host: api.example.com
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
Accept: application/json
Everything the server needs — identity, the resource, the desired format — is in the request itself.
3. Cacheability
Responses must declare whether they can be cached. HTTP gives you the whole toolkit — Cache-Control, ETag, Last-Modified — and a RESTful API actually uses it:
HTTP/1.1 200 OK
Cache-Control: public, max-age=300
ETag: "a7f3c2d9"
Content-Type: application/json
A follow-up request with If-None-Match: "a7f3c2d9" can get a body-less 304 Not Modified back. Most "REST APIs" in the wild skip this entirely and slap Cache-Control: no-store on everything — one of the clearest gaps between REST API and RESTful API in practice.
4. Uniform interface
This is the heart of REST, and it breaks into four sub-constraints:
- Identification of resources. Everything is a resource with a stable URI:
/users/42,/users/42/orders. Nouns, not verbs —/getUserOrders?id=42is RPC wearing an HTTP costume. - Manipulation through representations. You don't touch the resource directly; you exchange representations of it (JSON, XML, whatever
Content-Typenegotiates). - Self-descriptive messages. Each message carries enough information to be understood on its own — media types, standard methods, standard status codes.
- Hypermedia as the engine of application state (HATEOAS). Responses contain links that tell the client what it can do next. More on this one below, because it's the constraint that separates the sheep from the goats.
5. Layered system
A client can't tell (and shouldn't care) whether it's talking to the origin server, a CDN, a reverse proxy, or an API gateway. Statelessness and cacheability are what make this layering possible.
6. Code on demand (optional)
The server may extend the client by shipping executable code — the way a web server ships JavaScript to a browser. This is the only optional constraint, and for JSON APIs it's almost never used.
HATEOAS: the constraint everyone skips
Here's a typical "REST API" response:
{
"id": 8412,
"status": "pending",
"total": 129.99
}
And here's what a genuinely RESTful (hypermedia-driven) response looks like:
{
"id": 8412,
"status": "pending",
"total": 129.99,
"_links": {
"self": { "href": "/orders/8412" },
"cancel": { "href": "/orders/8412/cancellation", "method": "POST" },
"payment": { "href": "/orders/8412/payment", "method": "POST" },
"invoice": { "href": "/orders/8412/invoice" }
}
}
The difference isn't cosmetic. In the second response, the server tells the client which state transitions are currently valid. When the order ships and can no longer be cancelled, the cancel link simply disappears — the client doesn't need to replicate business rules like "orders can be cancelled only while pending." The API becomes discoverable and evolvable the same way a website is: you follow links instead of hardcoding URL patterns from out-of-band documentation.
Fielding was blunt about this. In a famous 2008 blog post he wrote that APIs without hypermedia shouldn't call themselves REST at all. By that strict definition, the overwhelming majority of "REST APIs" — including ones from major tech companies — aren't RESTful. The industry shrugged and kept using the word anyway.
The Richardson Maturity Model
Since "RESTful" is a spectrum, Leonard Richardson proposed a useful ladder for measuring how far up it an API sits:
| Level | Name | What it looks like |
|---|---|---|
| 0 | The Swamp of POX | One URL, one verb. POST /api with {"action": "getUser"} in the body. SOAP-style tunneling. |
| 1 | Resources | Distinct URIs per resource (/users/42), but still abusing one verb for everything. |
| 2 | HTTP Verbs | Proper use of GET/POST/PUT/PATCH/DELETE and meaningful status codes. This is where most production "REST APIs" live. |
| 3 | Hypermedia Controls | HATEOAS. Responses drive the client via links. This is what Fielding means by REST. |
This model gives us the cleanest answer to the title question:
A REST API, as the industry uses the term, is typically a Level 2 API. A RESTful API, in the strict sense, is a Level 3 API. Everything else is marketing.
Level 2 done well
Since Level 2 is where most of us live, it's worth being precise about what "done well" means there. The verb/resource grid:
| Method | /orders |
/orders/8412 |
|---|---|---|
| GET | List orders (200) | Fetch one order (200 / 404) |
| POST | Create an order (201 + Location header) |
— (405) |
| PUT | — | Replace the order entirely (200 / 204) |
| PATCH | — | Update part of the order (200) |
| DELETE | — | Delete/cancel (204 / 404) |
A few rules that separate a clean Level 2 API from a sloppy one:
- GET is safe and idempotent. It never mutates state. If your
GET /orders/8412/cancelendpoint cancels an order, a browser prefetcher or a monitoring probe can destroy data. - PUT and DELETE are idempotent. Calling them twice has the same effect as calling them once. This is what makes client retries safe.
- POST for creation returns
201 Createdwith aLocation: /orders/8413header pointing at the new resource. - Status codes carry meaning.
400for a malformed request,401for missing auth,403for insufficient permission,404for a missing resource,409for a state conflict,422for a semantically invalid body. Returning200 OKwith{"error": true}inside defeats every generic HTTP tool between your server and the client — caches, monitors, client libraries that key retry behavior off the status code. - Use plural nouns and nesting judiciously.
/users/42/ordersreads well;/users/42/orders/8412/items/3/product/reviewsis a sign you should promote something to a top-level resource.
Here's what that looks like in a NestJS controller, since that's my daily driver:
@Controller('orders')
export class OrdersController {
@Get(':id')
findOne(@Param('id') id: string) {
return this.ordersService.findOne(id); // 404 via NotFoundException
}
@Post()
@HttpCode(HttpStatus.CREATED)
create(@Body() dto: CreateOrderDto) {
return this.ordersService.create(dto);
}
@Patch(':id')
update(@Param('id') id: string, @Body() dto: UpdateOrderDto) {
return this.ordersService.update(id, dto);
}
@Delete(':id')
@HttpCode(HttpStatus.NO_CONTENT)
remove(@Param('id') id: string) {
return this.ordersService.remove(id);
}
}
Side-by-side summary
| "REST API" (common usage) | RESTful API (strict sense) | |
|---|---|---|
| Definition | HTTP API organized around resources and verbs | API satisfying all six REST constraints |
| Richardson level | Usually Level 2 | Level 3 |
| Statelessness | Usually yes | Required |
| HTTP caching semantics | Often ignored | Required (declared cacheability) |
| HATEOAS | Almost never | Required — links drive client state |
| Client coupling | Client hardcodes URLs from docs | Client discovers URLs from responses |
| Real-world examples | The vast majority of public JSON APIs | GitHub's API (partially), HAL/JSON:API-based systems, PayPal's HATEOAS links |
Does the distinction actually matter?
Pragmatically: in a job interview or an architecture review, treat the terms as synonyms unless someone signals otherwise — that's how the industry uses them. But the concepts behind the distinction matter a lot:
- Statelessness is why your API scales horizontally without sticky sessions.
- Cacheability is free performance that most teams leave on the table. Adding correct
ETag/Cache-Controlheaders to hot read endpoints is often a bigger win than another week of query optimization. - Uniform interface is why a new developer can guess your endpoints without reading the docs, and why generic tooling (OpenAPI generators, API gateways, retry middleware) works at all.
- HATEOAS is worth knowing even if you never ship it. The underlying idea — the server owns the business rules about which actions are valid right now — will improve your API design even when you express it as a plain
"can_cancel": truefield instead of a link.
And to be honest about trade-offs: full Level 3 REST has real costs. Payloads get bigger, clients need hypermedia-aware tooling that mostly doesn't exist for JSON, and frontend teams generally just want a typed client generated from an OpenAPI spec. That's why the industry settled on Level 2 + OpenAPI as the de facto standard, and why alternatives like GraphQL and gRPC carved out the niches where resource-oriented HTTP fits poorly (highly relational reads and low-latency internal RPC, respectively).
Wrapping up
- REST is Fielding's architectural style: six constraints that made the web scale.
- REST API is what we call any resource-oriented HTTP API — usually Richardson Level 2.
- RESTful API is, strictly, an API that honors all the constraints including hypermedia — Richardson Level 3 — though colloquially it means the same thing as REST API.
Don't lose sleep over the terminology. Do steal the ideas: stateless requests, honest status codes, real cache headers, resources instead of verbs, and a server that owns its own state transitions. An API built that way is a pleasure to consume — whatever you decide to call it.