Back to Blog
Lesson 39 of the REST API Design: Design Your First Clean REST API course
API ArchitectureAugust 26, 20263 min read

Mastering Resource Relationships and HATEOAS in REST APIs

Learn to design intuitive nested URIs and implement HATEOAS in your REST API to create discoverable, professional-grade resource relationships.

RESTAPI DesignHATEOASRelationshipsURI Modeling
A beekeeper in protective gear examines a honeycomb inside a sunlit greenhouse.

Previously in this course, we explored content negotiation to make our API more flexible. Now, we're taking a massive leap forward: we’re connecting our resources. In any real-world application, data doesn't exist in isolation; a Task belongs to a User, and a User owns multiple Tasks.

Managing these Relationships is the difference between a simple CRUD script and a professional, navigable system. In this lesson, we'll design nested URI structures and introduce HATEOAS (Hypermedia as the Engine of Application State) to link these resources together.

Designing Nested URIs for Relationships

In our Task Manager modeling, we identified two primary entities: users and tasks. When a resource has a clear parent-child or ownership relationship, nesting the URI is the most intuitive way to express that hierarchy.

Consider these two approaches:

  1. Flat: /tasks/123
  2. Nested: /users/45/tasks/123

The nested approach tells the API consumer exactly where this task sits in the system. It implies that the task belongs to the user with ID 45.

When to Nest

Follow the rule of thumb: If you cannot identify the child resource without the parent, nest it. If a Task can exist independently of a User, keep the URI flat for the primary collection but use nesting for association.

Relationship TypeExample URI
Ownership/users/{userId}/tasks
Association/tasks/{taskId}/assignees
Sub-resource/users/{userId}/profile

Linking Resources with HATEOAS

Close-up of crossed rusty chains over a blurred green background.

REST isn't just about endpoints; it's about the state of your application. HATEOAS, a core principle of REST architecture, suggests that the API should provide the client with links to related actions or resources. Instead of the client guessing the URL for the next step, the server provides it.

By including a _links object in your JSON response, you make your API "discoverable."

A Worked Example

Let’s look at a response for a single task that belongs to a user.

JSON
{
  "id": "123",
  "title": "Finish the API documentation",
  "status": "pending",
  "_links": {
    "self": { "href": "/v1/tasks/123" },
    "owner": { "href": "/v1/users/45" },
    "collection": { "href": "/v1/tasks" }
  }
}

By providing these links, your client doesn't need to hardcode URL logic. If the location of the owner changes, the client simply follows the new href provided by the server.

Hands-on Exercise: Linking Your Tasks

In our project, update your GET /v1/tasks/{taskId} endpoint to return a _links property.

  1. Add a self link pointing to the current task URL.
  2. Add an owner link pointing to the user who created the task (use a placeholder ID for now).
  3. Verify that your JSON response includes this new object without breaking the existing title or status fields.

Common Pitfalls

  • Deep Nesting: Never go beyond two levels (e.g., /users/1/tasks/2/comments/3). It makes URIs unmanageable. If you need deeper access, flatten the structure.
  • Over-linking: HATEOAS is helpful, but don't overwhelm the response with every possible action. Include only the most relevant links for that specific resource state.
  • Ignoring the Parent: When using nested URIs, ensure your backend actually validates that the child resource belongs to the parent (e.g., ensure Task 123 is actually owned by User 45).

FAQ

Does HATEOAS replace the need for API documentation? No. While HATEOAS helps with discovery, it doesn't document the expected request bodies or authentication requirements. Use OpenAPI for that.

Should I always nest URIs? Not always. Sometimes, a flat structure is cleaner, especially if the relationship is complex or many-to-many. When in doubt, prefer flat URIs and use _links to represent the relationship.

Recap

Team members presenting a project in a modern office setting with a focus on collaboration.

Relationships define how your data interacts. By nesting URIs, you create a logical hierarchy, and by using HATEOAS, you make your API self-documenting and resilient to path changes. These tools ensure your API behaves like a robust, professional service rather than a collection of disconnected endpoints.

Up next: We will dive deeper into the core principles of HATEOAS to make your API truly navigation-ready.

Similar Posts