DEV Community

Cover image for Should REST APIs Implement HATEOAS Hypermedia Links?
Wanda
Wanda

Posted on • Originally published at apidog.com

Should REST APIs Implement HATEOAS Hypermedia Links?

Should REST APIs Implement HATEOAS Hypermedia Links?

TL;DR:

HATEOAS (Hypermedia as the Engine of Application State) is a REST principle that’s elegant in theory but complex in practice. Most APIs skip full HATEOAS, opting for selective hypermedia links for pagination, related resources, and actions. Modern PetstoreAPI implements practical hypermedia links without forcing clients to be hypermedia-driven.

Try Apidog today


Introduction

If you’re designing REST APIs, you’ve probably come across HATEOAS. The idea is that clients should discover all actions through hypermedia links in responses, not by hardcoding URLs.

In reality, almost no one implements full HATEOAS. Although Roy Fielding (REST’s creator) says it’s essential, most API practitioners skip it due to complexity. The result: most “REST” APIs aren’t fully RESTful in the Fielding sense.

Modern PetstoreAPI uses hypermedia links pragmatically—adding them only where they improve client usability, such as pagination, related resources, and actions.

💡 Tip: If you’re building or testing REST APIs, Apidog lets you test hypermedia links, validate link formats, and ensure your API provides effective navigation.

In this post, you’ll learn what HATEOAS is, why it’s divisive, and how to implement actionable hypermedia links using Modern PetstoreAPI as a practical reference.


What Is HATEOAS?

HATEOAS is a REST constraint stating that clients should discover API capabilities by following hypermedia links in responses—no hardcoded URLs.

The Concept

Instead of hardcoding URLs:

// Client hardcodes URLs
const response = await fetch('https://petstoreapi.com/v1/pets/123');
const pet = await response.json();

// Client knows the URL structure
await fetch(`https://petstoreapi.com/v1/pets/${pet.id}/orders`);
Enter fullscreen mode Exit fullscreen mode

Clients should follow links from responses:

// Client starts at root
const root = await fetch('https://petstoreapi.com/v1');
const rootData = await root.json();

// Follow link to pets
const petsUrl = rootData._links.pets.href;
const pets = await fetch(petsUrl);
const petsData = await pets.json();

// Follow link to a specific pet
const petUrl = petsData._links.self.href;
const pet = await fetch(petUrl);
const petData = await pet.json();

// Follow link to orders
const ordersUrl = petData._links.orders.href;
const orders = await fetch(ordersUrl);
Enter fullscreen mode Exit fullscreen mode

The Theory

  • No hardcoded URLs: Clients don’t need to know URL patterns—the server controls them.
  • Discoverable capabilities: If a link is present, the action is available. If not, it isn’t.
  • Self-documenting APIs: Clients navigate by following links, similar to browsing a website.

Example: Full HATEOAS Response

{
  "id": "019b4132-70aa-764f-b315-e2803d882a24",
  "name": "Fluffy",
  "species": "CAT",
  "status": "AVAILABLE",
  "_links": {
    "self": {
      "href": "https://petstoreapi.com/v1/pets/019b4132-70aa-764f-b315-e2803d882a24"
    },
    "update": {
      "href": "https://petstoreapi.com/v1/pets/019b4132-70aa-764f-b315-e2803d882a24",
      "method": "PUT"
    },
    "delete": {
      "href": "https://petstoreapi.com/v1/pets/019b4132-70aa-764f-b315-e2803d882a24",
      "method": "DELETE"
    },
    "orders": {
      "href": "https://petstoreapi.com/v1/pets/019b4132-70aa-764f-b315-e2803d882a24/orders"
    },
    "adopt": {
      "href": "https://petstoreapi.com/v1/pets/019b4132-70aa-764f-b315-e2803d882a24/adopt",
      "method": "POST"
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Clients simply follow links—no need to know patterns or construct URLs.


HATEOAS: Theory vs. Practice

HATEOAS is debated because practical needs often diverge from the ideal.

Arguments For HATEOAS

  • Loose coupling: Clients don’t depend on URL structures.
  • Discoverability: API usage is discoverable without docs.
  • State-driven actions: Links reflect available actions (e.g., no "adopt" link if the pet is already adopted).
  • True REST: Required by REST’s original definition.

Arguments Against HATEOAS

  • Complexity: Clients must parse and handle hypermedia.
  • Performance: Multiple requests needed to discover URLs.
  • Debugging: Harder to debug via direct URL access.
  • Tooling: Most tools assume hardcoded URLs.
  • Adoption: Major APIs (GitHub, Stripe, Twilio, Twitter) don’t use full HATEOAS.

In practice: Most APIs are “REST-like”—using HTTP, but skipping full HATEOAS. Selective hypermedia links are more common.


Implementing Practical Hypermedia Links

Instead of strict HATEOAS, add hypermedia links where they provide real value.

1. Pagination Links

Problem: Clients must construct pagination URLs.

Solution: Provide next/prev links in responses.

{
  "data": [...],
  "pagination": {
    "page": 2,
    "limit": 20,
    "totalPages": 10
  },
  "links": {
    "self": "https://petstoreapi.com/v1/pets?page=2&limit=20",
    "first": "https://petstoreapi.com/v1/pets?page=1&limit=20",
    "prev": "https://petstoreapi.com/v1/pets?page=1&limit=20",
    "next": "https://petstoreapi.com/v1/pets?page=3&limit=20",
    "last": "https://petstoreapi.com/v1/pets?page=10&limit=20"
  }
}
Enter fullscreen mode Exit fullscreen mode

Benefit: Clients follow provided links—no manual URL construction.

2. Related Resource Links

Problem: Clients need to know how to fetch related resources.

Solution: Include explicit links for related resources.

{
  "id": "019b4132-70aa-764f-b315-e2803d882a24",
  "name": "Fluffy",
  "_links": {
    "self": "https://petstoreapi.com/v1/pets/019b4132-70aa-764f-b315-e2803d882a24",
    "orders": "https://petstoreapi.com/v1/pets/019b4132-70aa-764f-b315-e2803d882a24/orders",
    "owner": "https://petstoreapi.com/v1/users/019b4127-54d5-76d9-b626-0d4c7bfce5b6"
  }
}
Enter fullscreen mode Exit fullscreen mode

Benefit: Related resources are discoverable in the response.

3. Action Links

Problem: How do clients know what actions are allowed?

Solution: Include links for available actions; omit if not allowed.

{
  "id": "019b4132-70aa-764f-b315-e2803d882a24",
  "status": "AVAILABLE",
  "_links": {
    "adopt": {
      "href": "https://petstoreapi.com/v1/pets/019b4132-70aa-764f-b315-e2803d882a24/adopt",
      "method": "POST"
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

If the pet is already adopted:

{
  "id": "019b4132-70aa-764f-b315-e2803d882a24",
  "status": "ADOPTED",
  "_links": {
    // No "adopt" link
  }
}
Enter fullscreen mode Exit fullscreen mode

Benefit: Actions are discoverable and state-dependent.

4. Cursor-Based Pagination

Problem: Cursor tokens can be opaque.

Solution: Provide the correct next/prev URLs.

{
  "data": [...],
  "links": {
    "next": "https://petstoreapi.com/v1/pets?cursor=eyJpZCI6IjAxOWI0MTMyIn0"
  }
}
Enter fullscreen mode Exit fullscreen mode

Benefit: Clients use links directly, avoiding cursor parsing.


Modern PetstoreAPI: Practical Hypermedia

Modern PetstoreAPI Protocols uses selective hypermedia links.

Pagination Links

Every collection endpoint includes pagination links:

GET /v1/pets?limit=20

{
  "data": [...],
  "pagination": {
    "limit": 20,
    "hasMore": true
  },
  "links": {
    "self": "https://petstoreapi.com/v1/pets?limit=20",
    "next": "https://petstoreapi.com/v1/pets?cursor=eyJpZCI6IjAxOWI0MTMyIn0&limit=20"
  }
}
Enter fullscreen mode Exit fullscreen mode

Related Resource Links

Resource responses include links for navigation:

GET /v1/pets/019b4132-70aa-764f-b315-e2803d882a24

{
  "id": "019b4132-70aa-764f-b315-e2803d882a24",
  "name": "Fluffy",
  "ownerId": "019b4127-54d5-76d9-b626-0d4c7bfce5b6",
  "_links": {
    "self": "https://petstoreapi.com/v1/pets/019b4132-70aa-764f-b315-e2803d882a24",
    "owner": "https://petstoreapi.com/v1/users/019b4127-54d5-76d9-b626-0d4c7bfce5b6",
    "orders": "https://petstoreapi.com/v1/pets/019b4132-70aa-764f-b315-e2803d882a24/orders"
  }
}
Enter fullscreen mode Exit fullscreen mode

No Full HATEOAS Requirement

Clients can either:

Option 1: Follow links (hypermedia-driven):

const pet = await fetch(petUrl);
const ownerUrl = pet._links.owner.href;
const owner = await fetch(ownerUrl);
Enter fullscreen mode Exit fullscreen mode

Option 2: Construct URLs (traditional):

const pet = await fetch(`https://petstoreapi.com/v1/pets/${petId}`);
const owner = await fetch(`https://petstoreapi.com/v1/users/${pet.ownerId}`);
Enter fullscreen mode Exit fullscreen mode

Both work. Links are for convenience—not enforcement.


Testing Hypermedia APIs with Apidog

Apidog helps automate hypermedia testing.

Test Link Presence

Check for expected links in responses:

// Apidog test script
pm.test("Response includes pagination links", () => {
  const links = pm.response.json().links;
  pm.expect(links).to.have.property('self');
  pm.expect(links).to.have.property('next');
});
Enter fullscreen mode Exit fullscreen mode

Test Link Validity

Follow and validate links:

// Apidog test script
const nextUrl = pm.response.json().links.next;

pm.sendRequest(nextUrl, (err, response) => {
  pm.test("Next link returns 200", () => {
    pm.expect(response.code).to.equal(200);
  });
});
Enter fullscreen mode Exit fullscreen mode

Test Link Format

Ensure links are absolute URLs:

pm.test("Links are absolute URLs", () => {
  const links = pm.response.json().links;
  Object.values(links).forEach(link => {
    pm.expect(link).to.match(/^https:\/\//);
  });
});
Enter fullscreen mode Exit fullscreen mode

When (and Where) to Use HATEOAS

Use hypermedia links when they improve the developer experience or API usability.

Recommended for:

  • Pagination: Let clients follow next/prev links.
  • Related resources: Make navigation explicit.
  • State-dependent actions: Indicate available actions per resource state.
  • Complex workflows: Guide clients with workflow-specific links.

Consider skipping for:

  • Simple CRUD APIs: Clients can easily construct URLs.
  • Internal APIs: Coordinated changes make hardcoded URLs manageable.
  • Performance-critical APIs: Response size and bandwidth matter.
  • Mobile APIs: Minimize response payloads.

Conclusion

HATEOAS, while elegant, is complex and rarely implemented in full. Most APIs—including Modern PetstoreAPI—use selective hypermedia links for pagination, related resources, and actions, without forcing clients into a hypermedia-driven model.

To ensure link presence and correctness, use Apidog for automated hypermedia testing.

Key takeaways:

  • Full HATEOAS is rare and often unnecessary.
  • Selective hypermedia links add value with minimal complexity.
  • Pagination links are the most widely adopted and useful hypermedia feature.
  • Don’t require clients to be hypermedia-driven—offer links as convenience.
  • Always test your links for correctness and usability.

Explore the Modern PetstoreAPI documentation to see actionable hypermedia in practice.


FAQ

Is HATEOAS required for REST APIs?

By Roy Fielding’s definition, yes. In real-world APIs, almost never. Most APIs are technically “HTTP APIs” or “REST-like APIs.”

What does HATEOAS stand for?

Hypermedia as the Engine of Application State—clients discover API capabilities via links, not hardcoded URLs.

Do major APIs use HATEOAS?

No. Major APIs (GitHub, Stripe, Twilio, etc.) may include some hypermedia links (e.g., for pagination), but don’t require hypermedia-driven clients.

What’s the difference between HATEOAS and hypermedia links?

HATEOAS: Requires clients to be fully hypermedia-driven.

Hypermedia links: Simply links in responses—useful, but not enforced.

Should I implement HATEOAS in my API?

Full HATEOAS is rarely needed. Use selective hypermedia links for pagination and related resources; don’t require hypermedia-driven clients unless you have a specific need.

How do I test HATEOAS APIs?

Use Apidog to verify link presence, follow links, and validate link correctness.

What’s the HAL format?

HAL (Hypertext Application Language) is a standard for hypermedia links, using _links and _embedded fields. Modern PetstoreAPI uses a HAL-inspired structure.

Can clients ignore hypermedia links?

Yes. If your API provides links but doesn’t require their use, clients can construct URLs directly. This is the pragmatic approach most APIs take.

Top comments (0)