Back to Blog
Lesson 9 of the REST API Design: Design Your First Clean REST API course
API ArchitectureJuly 26, 20264 min read

URI Hierarchy and Collections: Designing Clean REST API Paths

Master URI design by distinguishing between collections and individual resources. Learn to build logical hierarchies for a predictable REST API.

RESTAPI DesignURI DesignHierarchyCollections
A tranquil park scene with a wooden bench amidst greenery, perfect for relaxation.

Previously in this course, we discussed designing resources as nouns to keep our API intuitive. Now that we know what our resources are, we need to decide where they live.

In this lesson, we’ll explore how to arrange those resources into a logical URI hierarchy. Good URI design isn’t just about making endpoints look pretty; it's about creating a navigable map that tells developers exactly how your data relates to itself.

Collections vs. Individual Resources

In REST, a URI acts as the address for a resource. To keep your API consistent, you must distinguish between two fundamental types of URIs:

  1. Collections: A group of resources. These represent a set of items, like "users" or "tasks."
  2. Individual Resources: A specific item within that collection, identified by a unique identifier (ID).

By convention, collections use the plural form of the noun, while individual resources are accessed by appending their unique ID to the collection path.

ConceptURI PathDescription
Collection/tasksRepresents the list of all tasks.
Individual/tasks/123Represents the single task with ID 123.

Building Hierarchical Relationships

Real-world data is rarely flat. A user might have many tasks, and a task might have many comments. We represent these relationships using a nested hierarchy in our URI structure.

The rule of thumb for hierarchy is: If a resource cannot exist without its parent, nest it.

If you have a task and that task has comments, the comment doesn't exist in a vacuum—it belongs to a specific task. Therefore, the hierarchy flows from the parent down to the child:

  • GET /tasks/123/comments — Returns all comments for task 123.
  • GET /tasks/123/comments/45 — Returns the specific comment 45 belonging to task 123.

Why Hierarchy Matters

When you follow this structure, you provide developers with a predictable pattern. If they know how to fetch a task, they can reasonably guess how to fetch that task's sub-resources without consulting your documentation for every single endpoint.

Worked Example: The Task Manager API

Let's apply this to our ongoing project. We are building a task management system. Our primary entities are users and tasks.

If we define our hierarchy, it might look like this:

TEXT
/users                  # Collection of all users
/users/1                # Specific user (ID: 1)
/users/1/tasks          # Collection of tasks belonging to user 1
/users/1/tasks/50       # Specific task (ID: 50) for user 1

If we wanted to add categories to our tasks, the hierarchy would extend:

TEXT
/tasks/50/categories    # All categories associated with task 50

Notice that we keep the paths short. Avoid "deep nesting" (e.g., /users/1/tasks/50/comments/12/author). If your path exceeds three levels, it often indicates that you should rethink your resource modeling or consider using query parameters instead.

Hands-on Exercise

Design the URI structure for a "Library System" that includes books, authors, and reviews.

  1. Write the base collection URI for all three resources.
  2. Write the URI to get a specific book.
  3. Write the URI to get all reviews for a specific book.
  4. Write the URI to get a specific review for a specific book.

Check your work: Did you use plural nouns for collections? Did you use IDs for individual resources? Is the hierarchy logical?

Common Pitfalls

  • Verbs in URIs: Never include actions in your path. Use /tasks instead of /getTasks or /createTask. Let the HTTP methods define the action (GET, POST, etc.).
  • Deep Nesting: Over-nesting makes URLs fragile and hard to read. If you find yourself nesting more than three levels deep, flatten the structure.
  • Inconsistent Pluralization: Choose a style (usually plural) and stick to it across your entire API. Don't mix /user and /tasks.

FAQ

Q: Should I always nest resources? A: No. Only nest when there is a strict ownership or hierarchical relationship. For example, a Category might be a global resource, so /categories is better than /tasks/50/categories.

Q: What if I have a resource that doesn't fit into a collection? A: If a resource is a "singleton" (like the currently logged-in user's profile), it is acceptable to use a singular path, such as /me or /profile.

Recap

We’ve learned that a clean URI design uses collections for sets of data and identifiers for specific items. By organizing resources into a logical hierarchy, we build APIs that are intuitive and easy to navigate. Remember: keep it flat, use nouns, and let HTTP methods handle the heavy lifting.

Up next: Identifying Task Manager Resources

Similar Posts