API · Rest

REST API HATEOAS — A Field Guide

What HATEOAS actually means in Roy Fielding's original REST definition, and an honest accounting of when the hypermedia-driven approach is worth its implementation cost.

John Kihiu12 min read

HATEOAS — Hypermedia As The Engine Of Application State — is the part of Roy Fielding's original REST dissertation that almost nobody implements and almost everybody's API claims to be, because "RESTful" became a synonym for "uses HTTP verbs and JSON" long before it meant what Fielding actually described. The real idea is narrower and, honestly, more interesting than the watered-down popular usage: a client shouldn't need out-of-band knowledge of the API's URL structure, because the server tells it what it can do next, embedded in every response.

What HATEOAS actually requires

In a fully hypermedia-driven API, a client starts at a single well-known entry point and discovers everything else by following links in the responses — the way a human browsing a website discovers pages by clicking links rather than by knowing every URL in advance. A response for an order doesn't just return the order's fields; it returns links describing what can legally be done to that order right now: cancel, if it hasn't shipped; return, if it has been delivered; pay, if it's unpaid. The client's logic becomes "follow the link labeled 'cancel' if present" rather than "construct DELETE /orders/123 and hope the current state allows it."

JSON · HAL-STYLE HYPERMEDIA RESPONSE
{
  "id": 4471,
  "status": "unpaid",
  "total_cents": 152000,
  "_links": {
    "self": {"href": "/v1/invoices/4471"},
    "pay": {"href": "/v1/invoices/4471/payments", "method": "POST"},
    "void": {"href": "/v1/invoices/4471", "method": "DELETE"}
  }
}

The real benefit: the server can change its URL structure and workflow without breaking clients

The actual payoff of HATEOAS is decoupling: because the client never hardcodes a URL beyond the entry point, the server is free to restructure endpoints, add new states, or change which actions are available under which conditions, and a well-built hypermedia client keeps working because it was never told those specifics in the first place — it just follows whatever links are present. This matters most for long-lived integrations you don't control the client side of, where a breaking URL change would otherwise require a coordinated release across every consumer.

The real cost: almost nobody actually builds a generic hypermedia client

Here's the honest problem: the benefit only materializes if clients are actually written to discover and follow links dynamically, rather than being hardcoded against the link relations the developer saw in the docs during integration — which is what happens in practice almost universally. A client that greps the response for a "pay" link and calls the URL inside it has effectively hardcoded the string "pay", gaining none of the decoupling benefit while paying the full cost of parsing and following a more complex response shape. Full HATEOAS pays off for public APIs with many independent, unknown consumers over a long timeline; it's usually not worth it for an internal API where you control both ends and can just coordinate a version bump.

Link relations need a shared vocabulary to mean anything

A "pay" link is only useful if every client agrees what "pay" means and what to do with it — which is why serious hypermedia APIs adopt a standard format (HAL, JSON:API, Siren) with registered link relation names, rather than inventing ad hoc keys per endpoint that only the original author's documentation explains.

Partial adoption is usually the practical answer

Most production APIs land somewhere between "no hypermedia at all" and "full HATEOAS": returning a self link and maybe one or two state-dependent action links, without building the fully generic, self-describing media type Fielding's dissertation describes. That's a reasonable compromise — it gives clients a documented, discoverable way to find the next valid action without requiring every consumer to build a link-following state machine, and it costs one extra field in the response rather than a different design philosophy for the whole API.

Don't call an API "RESTful" as a synonym for "HATEOAS-compliant"

Fielding himself pushed back publicly on APIs calling themselves REST while just using HTTP verbs over JSON without hypermedia controls. It's not wrong to build that kind of API — it's an extremely common and often better choice — but know the vocabulary is being used loosely, and don't expect true hypermedia-driven decoupling from an API that never implemented it.

Wrapping up

HATEOAS is a specific, narrower idea than the industry's casual use of "REST" implies: the server drives the client's next move through embedded links, not a shared URL scheme memorized in advance. It's worth the cost for public APIs with long-lived, independently-evolving clients; for most internal APIs, a simpler contract with versioned breaking changes gets you further for less implementation effort.

John Kihiu
Acumatica ERP Developer · Laravel Engineer

Independent software engineer in Nairobi specialising in Acumatica customisations, Laravel backends, and tax fiscalisation integrations across East and Southern Africa.