3

I'm building a REST API, and I have some relationships that are making my links very long. They make sense to me, but it's a mess. I'm not sure what the best way is to handle this. Is it a problem to have links that are so long? Am I violating a principle with these? How should I handle relationships like this?

The example below is a bit contrived, but it illustrates what I'm trying to do.

A company has many departments. Each department has many employees. Each employee can have many computers. Each computer can have many documents on it.

The path to GET a specific document would be:

/companies/:companyId/departments/:departmentId/employees/:employeeId/computers/:computerId/documents/:documentId 

Each ID is globally unique within that layer--no two document IDs will be the same across the entire system, but a document ID could be the same as an employee ID.

This makes sense to me, because each layer is only associated with the one thing above it. A department will belong only to a single company, an employee to only a single department, a computer to only a single employee, and a document to only a single computer.

I could break these out into separate endpoints, such as /computers, but then how would I know where to break them? Why would I choose /computers as the endpoint and not /employees/:employeeId/computers?

7
  • Is documentId globally unique? Commented Oct 4, 2016 at 15:37
  • @JonSG Yes, it would be unique within all document IDs. I edited the question to clarify. Commented Oct 4, 2016 at 15:39
  • 2
    My opinion here, but I feel there is no need to represent they hierarchy in the API. The one you have illustrated in an example, but there are likely many others. I feel like your get api should be simplified to /document/[id]. Similarly if employeeid is globally unique then employee/[id]. Why make the consumer know about employees and departments if they want to contents of a file with a known Id? On the other hand, an initial post/put is a different problem as then the hierarchy would likely be required. Is it a requirement to support a "full" verb set, or is get enough? Commented Oct 4, 2016 at 15:45
  • @JonSG That makes sense, definitely. Would I then search on an endpoint, like GET /documents?computerId=123, or extend computers to GET /computers/:computerId/documents? Commented Oct 4, 2016 at 15:48
  • Ya to enumerate documents for a known computer I think the latter example you use above makes sense. Commented Oct 4, 2016 at 15:50

1 Answer 1

3

In this example, I would move each of those resources to be top-level. Each top-level resource could have the next "level" as a member. So,

/companies /companies/{id} /companies/{id}/departments /departments etc.. 

I'd only add the sub-resources if it was actually necessary for end users to manipulate the contents of the collection.

Deeply nested resources are problematic. What happens in 3 months when you get a business requirement to find all employees, regardless of department, which work for company {id}? With employees as a top-level resource, you add support for GET /employees?companyId={id}. In the design you present above, your choices are all bad. There's a lot of flexibility for relationships between resources that you give up when you formalize a nesting structure like you have.

As far as some of your specific concerns:

I'm building a REST API

REST is totally agnostic on the subject of URI design.

I have some relationships that are making my links very long. They make sense to me, but it's a mess. [..] Is it a problem to have links that are so long?

End users will hopefully never be typing these in. If your API really is RESTful, then clients will be using the links you're returning, and they shouldn't have to type them in either. In a RESTful system, I'd expect the "I have some X" relationship to be held in a link, and not just documented via the shape of your URIs. I agree they're on the long side, and I would change them for the reasons mentioned above, but I don't think your specific concerns are a good reason to change them.

Am I violating a principle with these?

Not that I'm aware of.

Sign up to request clarification or add additional context in comments.

6 Comments

I fully agreee that REST is URI agnostic and that too much emphasis is put on a so called clean-URI design. Though, I wouldn't change every sub-resource to a top-level resource either. My personal preference is to convert resources to top-level resources if they can "survive" on their own. A department is tightly coupled to a company, an employee will still live without a company, though it isn't an employee of that company anymore hence I'd leave it as sub-resource. A computer on the other hand remains a computer regardless of the company and thus is suited for a top level resource.
@RomanVottner So in this example you'd only have departments as a subresource? I don't disagree with that approach if you can ensure that the tight coupling is forever and ever. If that business rule ever changes, though ...
Employee is also coupled to the company else it wouldn't be an employee. In case the employee quits the company and nothing life-threatening happens to her, she will still live but without being an employee of that company. Even if business rules change and/or departments merge/divide, a true RESTful client won't break as they simply learn from previous responses. URI related questions always have a tendency for opinionated answers, though SO-community isn't very keen on closing such questions IMO.
@RomanVottner If the employee moves from one client company to another, are they a new employee? As far as the business rule change, the issue is that now you need to make a totally new URI instead of using the existing ones. True RESTful clients will be fine, but it's a maintenance issue for the dev team. And not many clients are truely RESTful in my experience. But yes, questions like this often lie between "we don't have enough information to answer" and "it depends".
This makes perfect sense, thank you! One other question that came up: If I want to add a new employee to a department, should I POST to /departments/:id/employees, or to /employees but with the department ID specified in the body?
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.