william
william

Reputation: 479

Is it ok to nest REST resources in "directories" that indicate the resources are of a similar type, as opposed to indicating a belongs-to hierarchy?

It's common to nest resources in a RESTful API. For example, to retrieve the employees in company having ID=5:

GET /companies/5/employees

Is it also generally acceptable in a REST design to put resources in a common "directory" where they don't really belong-to a common parent resource instance? This is more of a "is-a" relationship, where I think the typical nested structure has the nested resources in a "belongs-to" relationship.

For example, is it acceptable to group two different resources (internal agents, external agents) like follows? In this case the agents part of the path is a category that describes its descendants but isn't really a parent resource.

GET /agents/internal
GET /agents/external

There are no plans to add any resources using the /agents path; it is solely for grouping purposes.

Or is that to be avoided for something like this?

GET /internal-agents
GET /external-agents

I feel like the second option is more correct, but there is an aesthetic to the first option that that I like.

Upvotes: 0

Views: 99

Answers (1)

Arnaud Lauret
Arnaud Lauret

Reputation: 5281

Given that you have some agents which can be internal or external:

  • /agents/internal is a terrible idea breaking URL consistency
  • /internal-agents is a valid idea but beware of drawbacks
  • A filter could be better for this use case: GET /agents?status=internal

/agents/internal is a terrible idea breaking URL consistency

Having /agents/internal is a terrible idea, it MUST not be used as it will lead to inconsistent URLs in your API which will not be easily understand by humans but also programs.

  • The best pattern for REST URL (exluding domain and versioning matters) is this one: /resources/{resouce id}/sub-resources/{sub-resource id}// No more than 2 levels should be allowed. Your first example /companies/5/employees is a perfect good example.
  • Adding a /agents/internal URL will make your API's URLs inconsistent and difficult to understand for humans but also programs. You can end having GET /agents/2 which return agent with id 2 and also GET /agents/internal which return a list of internal agents. Same URL structure but different meanings.

Using a consistent structure for URL helps to understand the semantic without even knowing what an API does.

/internal-agents is a valid idea but beware of drawbacks

Your idea of having two specific resources internal-agents and external-agents is valid. But it can have some drawbacks depending on the exact use case:

  • if you add more status, like partner for example, you'll have to add a new resource partner-agents
  • if a consumer want to retrieve both type it'll have to make to calls or you'll have to create a /agents resource

A filter could be better for this use case: GET /agents?status=internal

A third idea would be to consider internal and external as filter on some status on /agents resource.

  • GET /agents returns all agents (internal + external)
  • GET /agents/2 returns agent with id 2
  • GET /agents?status=internal returns agents with internal status
  • GET /agents?status=external returns agents with external status

And if you add a new status like partner:

  • GET /agents returns all agents (internal + external + new partner status)
  • GET /agents/2 still returns agent with id 2
  • GET /agents?status=internal still returns agents with internal status
  • GET /agents?status=external still returns agents with external status
  • GET /agents?status=partner returns agents with new partner status
  • GET /agents?status=internal,partner returns agents with internal or partner status

Choosing between filter and specific resources is only a metter of context. The only thing to keep in mind is to ensure URLs consistency.

Upvotes: 1

Related Questions