HATEOAS Introduction — Making APIs Self-Discoverable
In this tutorial, you will learn about HATEOAS Introduction. We cover key concepts, practical examples, and best practices to help you master this topic.
HATEOAS (Hypermedia as the Engine of Application State) is a principle of REST where the server drives client navigation by including links in responses that describe available transitions and actions.
What You'll Learn
- What HATEOAS means and why it completes REST
- How hypermedia links reduce client-server coupling
- Real-world examples of HATEOAS in action
Why It Matters
Most REST APIs claim to be RESTful but ignore HATEOAS. Without it, clients must hardcode URL patterns, creating tight coupling that HATEOAS eliminates.
flowchart LR
A["Client"] -->|"GET /accounts/123"| B["Server"]
B -->|"Response + Links"| A
A -->|"Client follows\n'withdraw' link"| C["POST /accounts/123/withdrawals"]
C -->|"Response + New Links"| A
style B fill:#dbeafe,stroke:#2563eb
Real-World Use
The Stripe API uses hypermedia patterns. When you create a payment, the response includes URLs to confirm, cancel, or retrieve the payment. The client doesn't construct URLs — it follows the provided links.
Code Examples
# HATEOAS response example
response = {
"order_id": "ORD-123",
"status": "pending",
"total": 2999,
"_links": {
"self": {"href": "/orders/ORD-123", "method": "GET"},
"items": {"href": "/orders/ORD-123/items", "method": "GET"},
"pay": {"href": "/orders/ORD-123/payments", "method": "POST"},
"cancel": {"href": "/orders/ORD-123", "method": "DELETE"}
}
}
# Client follows links instead of hardcoding URLs
import requests
base = "https://api.example.com"
order = requests.get(f"{base}/orders/ORD-123").json()
payment_url = order["_links"]["pay"]["href"]
payment = requests.post(f"{base}{payment_url}", json={"amount": 2999})
print(payment.status_code)
// Client using HATEOAS links
async function processOrder(orderId) {
const res = await fetch(`/api/orders/${orderId}`);
const order = await res.json();
// Follow links - no hardcoded URLs
if (order._links.pay) {
await fetch(order._links.pay.href, {
method: 'POST',
body: JSON.stringify({ amount: order.total })
});
}
}
Common Mistakes
1. Building APIs Without Any Links
Without HATEOAS, clients must hardcode URL patterns.
2. Including Links but Ignoring Method Info
Links should include the HTTP method so clients know how to use them.
3. Hardcoding URLs on the Client
The whole point of HATEOAS is that clients discover URLs from responses.
4. Providing Links for All States
Links should reflect the current resource state. A paid order shouldn't have a "pay" link.
5. Inconsistent Link Formats
Use a consistent format (HAL, JSON:API, or custom) across all responses.
Practice Questions
- What does HATEOAS stand for?
- How does HATEOAS reduce client-server coupling?
- What should a HATEOAS link include besides the URL?
- Why should links change based on resource state?
- Is HATEOAS required for REST?
Answers:
- Hypermedia as the Engine of Application State.
- Clients discover URLs from responses instead of hardcoding them.
- The HTTP method and relation type (rel).
- Different states allow different actions. A paid order shouldn't offer payment.
- Yes. HATEOAS is one of the six REST constraints.
Challenge: Design a HATEOAS response for a blog post resource that shows different links based on whether the current user is the author (edit, delete) or a reader (share, report).
FAQ
What's Next
Learn about REST Constraint HATEOAS in detail, then explore Links and Rels.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro