Saikat
← Back to blog

REST API vs RESTful API: What's the Actual Difference?

July 19, 2026·10 min read
RESTAPI DesignHTTPBackend
Share:
REST API vs RESTful API: What's the Actual Difference?

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=42 is RPC wearing an HTTP costume.
  • Manipulation through representations. You don't touch the resource directly; you exchange representations of it (JSON, XML, whatever Content-Type negotiates).
  • 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/cancel endpoint 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 Created with a Location: /orders/8413 header pointing at the new resource.
  • Status codes carry meaning. 400 for a malformed request, 401 for missing auth, 403 for insufficient permission, 404 for a missing resource, 409 for a state conflict, 422 for a semantically invalid body. Returning 200 OK with {"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/orders reads well; /users/42/orders/8412/items/3/product/reviews is 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:

  1. Statelessness is why your API scales horizontally without sticky sessions.
  2. Cacheability is free performance that most teams leave on the table. Adding correct ETag/Cache-Control headers to hot read endpoints is often a bigger win than another week of query optimization.
  3. 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.
  4. 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": true field 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.