Web API vs REST API — When the Distinction Actually Matters
Knowing the difference prevents caching bugs and scaling failures.
Every REST API is a Web API. Not every Web API is a REST API. That one-directional relationship is where teams get into trouble, usually right around the moment someone says "we're building a REST API" and nobody checks whether that's actually true. Roy Fielding coined the term in 2000, in his doctoral dissertation, and he meant something specific by it: not a protocol, not a library you install, but six constraints describing how to use the existing web properly.
Those constraints are Client-Server separation, Layered System, Stateless Communication, Cache, Code-On-Demand, and Uniform Interface (which splits into four sub-rules, including the notoriously-skipped HATEOAS). Most working engineers use "REST API" and "Web API" as though they are interchangeable. They are not, and the gap between them is where caching bugs, scaling assumptions, and integration timelines quietly accumulate.
What else lives under the Web API umbrella
"Web API" just means an API that talks over HTTP. REST clears that bar, but so do at least four other major styles, and none of them behave alike under the hood.
SOAP is the oldest: XML-based, heavier, wrapped in its own formal envelope structure. It still appears in banking and telecom, mostly because those industries need built-in standards for security and transactions that SOAP provides by default. It is rarely the right choice for something new, but it has not disappeared.
GraphQL flips the usual model. Instead of the server deciding what data comes back, the client specifies the exact shape it wants, so no one is fetching a giant user object just to retrieve a name and an email. It travels over HTTP and returns JSON, so it carries the "Web API" label alongside REST, but the way it operates has almost nothing in common with REST's resource-and-endpoint model. Adoption has grown noticeably since the early 2020s, moving from a niche choice to something a meaningful share of organizations now run in production.
gRPC came out of Google and uses Protocol Buffers (Protobuf) for serialization, so data gets packed tightly and parsed quickly. It runs over HTTP/2, which means a different wire format and different tooling than conventional REST APIs typically require. It is built for low latency and high throughput, which is why it appears constantly in microservices communicating internally, where no one outside the organization ever sees the traffic.
WebSocket removes the request-response cycle entirely. It holds a connection open and lets data flow in both directions continuously, which makes it the right choice for live feeds, collaborative editors, or dashboards that update automatically rather than waiting on a refresh.
None of this mixing is theoretical. A single e-commerce company might run its product catalog through GraphQL while keeping other flows on REST for simpler, well-understood CRUD operations. Both count as "Web APIs" and neither choice is wrong. Running three architectural styles at once means three sets of tooling, three sets of debugging habits, and three things engineers need to learn before touching the codebase. That is acceptable when it is deliberate, and problematic when it is just drift.
How real APIs measure up against REST
REST is the label on the vast majority of APIs built today. That raises an immediate question: how many of those APIs actually satisfy all six of Fielding's constraints?
Not many. Fielding has said as much himself. Most systems calling themselves "REST APIs" are actually HTTP APIs with JSON bodies and CRUD-shaped endpoints, carrying a label they never earned.
The constraint that gets skipped most often is HATEOAS, the requirement that a server's response tells the client what actions are available next through links embedded in that response. Without it, the client must already know the URL structure in advance, typically from a documentation page. The API ends up relying on external documentation to do the job the response itself was supposed to do.
A typical shipped "REST API" satisfies Client-Server easily enough, sometimes satisfies Stateless, sometimes satisfies Cache, and almost never touches Code-on-Demand or full HATEOAS. Three habits are usually responsible, and none of them are exotic mistakes:
Session tokens or server-side session state, which breaks Stateless the moment the server must remember who the client is between requests.
Responses marked uncacheable, or not marked at all, on data that rarely changes, which breaks Cache.
Hardcoded endpoint paths the client must memorize in advance, which breaks Uniform Interface and HATEOAS.
Calling a system "REST" is a spectrum claim, not a box anyone checks. The constraints that fall off first happen to govern caching, scaling, and how tightly clients get coupled to an API's internals.
When the REST label genuinely doesn't matter
Not every decision depends on this distinction. Some of the REST versus Web API debate is purely vocabulary, and treating it as a design-review priority wastes time.
Authentication is a good example. OAuth 2.0, API keys, and JWTs all work across REST and non-REST Web APIs alike. Implementation details shift depending on architecture, but the label changes nothing about whether a client can authenticate.
Basic CRUD work on a data model everyone already understands is another case where the distinction does not matter. If the team knows the shape of the data and the client is a web app hitting a handful of endpoints, arguing over whether that counts as "real REST" or just "HTTP with JSON" is not a productive design conversation.
Tooling does not care either. Postman and Insomnia work against any HTTP-based API regardless of how many Fielding constraints it satisfies, and none of the developers using them sort their requests by REST compliance.
Documentation quality is its own separate problem, and a common one: developers routinely name inconsistent docs as one of the biggest sources of friction when integrating with a new API. That friction appears in fully RESTful systems and loosely-REST systems equally. It is a documentation maintenance problem, not an architectural style problem.
Encryption in transit, TLS, and tokens do not shift based on architectural style either. If a team is building a small internal tool with one client and no scaling requirements, a long debate about REST purity consumes time that produces nothing.
Where label confusion creates real engineering problems
This is where the distinction stops being theoretical and starts costing actual hours.
Caching decisions. REST's Cache constraint requires responses to identify themselves as cacheable or not. A team that assumes their "Web API" is properly RESTful and then builds a CDN layer or reverse-proxy cache on top of that assumption will encounter stale or incorrect data the moment it turns out the API never set Cache-Control headers correctly. Fixing that requires rethinking the caching strategy from the header level upward, not swapping a single configuration value, because the cache layer was built on a guarantee the API never made.
Statelessness and horizontal scaling. Statelessness is what allows these systems to scale horizontally: any server can handle any request because no server holds session context between calls. If session state lives server-side, and the system is still labeled REST, then infrastructure gets designed around the assumption that any node can serve any client. When a load balancer routes a request to a node that does not have the required session data, the resulting bug looks like a networking problem when it is actually an architectural problem. A significant share of microservice architectures rely on REST for service-to-service communication, which means this assumption is embedded in a lot of modern infrastructure.
Skipping HATEOAS couples clients to whatever URL structure appears in out-of-band documentation. When an endpoint gets renamed or a resource gets restructured, every client that hardcoded the old path breaks simultaneously, rather than following an updated link the server would have provided. That cost gets paid again every time the API changes shape.
Handing an integration developer a generic Web API with proprietary formats, unpredictable endpoints, and custom methods increases build time and ongoing maintenance costs. A mislabeled "REST API" that behaves like an arbitrary Web API carries that same cost, except the team did not budget for it because they assumed a standard level of predictability. For a team managing integrations across a dozen platforms, that mislabeling compounds: every integration becomes its own puzzle instead of following one predictable pattern.
Interoperability choices. Public-facing APIs generally do better with REST or GraphQL, since broad compatibility matters more in that context. Internal APIs can use gRPC or event-driven patterns, since the team controls both ends of the connection. Making that call correctly requires knowing which style is actually running, not which word appeared in the README years ago.
Audit what you have before deciding architecture
The audit is not complicated. It means checking, honestly, whether the constraints everyone assumes are in place actually hold up.
Start with statelessness. Pick any endpoint. Can a server that has never seen this client handle that request using only what is in the payload and headers? Or does it need to retrieve session data from somewhere first? If session state lives on the server, that fact needs to be documented clearly, and any infrastructure decision that assumed stateless horizontal scaling should be revisited.
Move to caching. Pull up the response headers. Are Cache-Control, ETag, or Last-Modified actually set and set correctly? If responses come back uncacheable by default, even on data that rarely changes, any caching layer in front of that API serves no purpose and actively misleads anyone reading stale results.
Check the Uniform Interface, specifically HATEOAS. Does a response include links pointing to related actions and next steps, or does the client need to know the URL in advance? Skipping HATEOAS is a legitimate design decision that many teams make deliberately. However, it means clients get tightly bound to the URL structure, which makes API changes more disruptive than they would be if the server provided embedded links to guide clients through transitions.
Finally, check Client-Server separation. Can the data model on the server change without the client needing to know? Or are the two sides synchronized on assumptions that nobody wrote down?
None of this produces a pass-or-fail score. It produces a clear picture of which constraints are actually in force and which ones exist only in the name of the API. Infrastructure and integration decisions should be built against that picture, not against the label on the folder.
If the audit reveals a Web API carrying a REST label it never earned, the fix is usually smaller than a rewrite. It requires accurately relabeling the system, documenting which constraints are absent, and ensuring that whoever consumes the API knows what they are actually working with.
Match the API style to the actual use case
None of these styles is universally better. Each one solves a different problem, and mismatches happen when teams choose based on habit rather than fit.
REST earns its default status when an API is public-facing, the client base is broad and largely unknown, the data maps cleanly to CRUD operations, and caching and statelessness are constraints the team can genuinely commit to rather than just claim.
GraphQL is worth choosing when several different clients (mobile, web, third-party integrations) each need a different slice of the same underlying data, and over-fetching or under-fetching is causing a real, measurable performance problem rather than a theoretical concern.
gRPC fits when traffic is internal, latency matters, and both ends of the connection are controlled by the same team, since the Protobuf contract requires strict agreement on both sides.
WebSocket is the right choice when the use case requires continuous, bidirectional state (live feeds, collaborative editing, auto-updating dashboards), and the alternative would require the client to poll the server repeatedly to check for new data.
SOAP still earns its place in regulated environments like banking and telecom, where its built-in transaction and security standards are environmental requirements rather than optional features.
Running REST externally, GraphQL for clients assembling screens, and gRPC internally is a common and reasonable architecture. It requires three sets of tooling, and it needs to be a deliberate decision rather than a pattern that emerged because three different teams each chose their preferred tool without coordinating.
The filter that works is use case first, label second. Start with what the communication actually requires: real-time or request-response, public or internal, one client or many. Then choose the style that matches those requirements. A growing share of companies now monetize their APIs directly, which raises the stakes considerably. Getting the architectural fit wrong does not appear as a tidy technical-debt line item. It surfaces as a product reliability problem, in someone else's production system, on someone else's schedule.



