HATEOAS Link Formats — HAL, JSON:API, and Custom Hypermedia
In this tutorial, you will learn about HATEOAS Link Formats. We cover key concepts, practical examples, and best practices to help you master this topic.
HATEOAS link formats define how hypermedia links are structured within API responses, with HAL being the most popular and JSON:API offering a standardized alternative.
What You'll Learn
- The structure of HAL, JSON:API, and other link formats
- How to choose the right format for your API
- Implementing link generation in practice
Why It Matters
A consistent link format makes your HATEOAS API predictable. Different formats have different tradeoffs in terms of simplicity, expressiveness, and tooling support.
flowchart TD
A["Link Formats"] --> B["HAL\n_links, _embedded"]
A --> C["JSON:API\nlinks, relationships"]
A --> D["Siren\nactions, links"]
A --> E["Collection+JSON\nlinks, queries, templates"]
A --> F["Custom\napplication-specific"]
style A fill:#dbeafe,stroke:#2563eb
Code Examples
// HAL format
{
"_links": {
"self": { "href": "/orders/123" },
"items": { "href": "/orders/123/items" },
"customer": { "href": "/customers/456" }
},
"_embedded": {
"items": [{ "product": "Widget", "quantity": 2 }]
},
"order_id": "ORD-123",
"total": 2999
}
// JSON:API format
{
"data": {
"type": "orders",
"id": "123",
"attributes": { "total": 2999, "status": "pending" },
"relationships": {
"items": {
"links": {
"self": "/orders/123/relationships/items",
"related": "/orders/123/items"
}
}
}
}
}
# Generating HAL links in Python
def hal_response(data, links):
return {
**data,
"_links": {
rel: {"href": url} for rel, url in links.items()
}
}
order_data = {"order_id": "ORD-123", "total": 2999}
links = {
"self": f"/orders/{order_data['order_id']}",
"items": f"/orders/{order_data['order_id']}/items"
}
response = hal_response(order_data, links)
Common Mistakes
1. Mixing Different Link Formats in One API
Pick one format and use it consistently across all endpoints.
2. Using HAL Without _embedded
HAL's _embedded provides efficient data loading. Use it alongside _links.
3. Overcomplicating with Siren for Simple APIs
Siren is powerful but complex. HAL is simpler for most APIs.
4. Ignoring Content Negotiation
Let clients request different formats via the Accept header.
5. Not Versioning Your Link Format
Format changes should be versioned like any other API change.
Practice Questions
- What does HAL stand for in HATEOAS?
- How does JSON:API handle relationships differently from HAL?
- What is
_embeddedused for in HAL? - Why might you choose a custom format over HAL?
- How can clients request a specific link format?
Answers:
- Hypertext Application Language.
- JSON:API separates relationships into a dedicated section; HAL uses
_linksand_embedded. _embeddedincludes related resources inline to reduce API calls.- When you need domain-specific link metadata that standard formats don't support.
- Via the
Acceptheader, e.g.,Accept: application/hal+json.
Challenge: Take a simple REST API response and transform it into HAL, JSON:API, and a custom format. Compare the three approaches.
FAQ
What's Next
Learn about Actions and Forms for state transitions, then explore Dynamic Discovery in HATEOAS.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro