Collection response vs singular response (for a 'collection style' endpoint that returns only one resource at most)

Just had a discussion amongst my team when designing an endpoint that we expect will only return (at most) one resource, at a path like /orders/{order_id}/gift_options

My opinion was that API users would expect the convention for endpoints like that to be an array of resources, even if there is only one resource in the array. After getting the ‘array’ (of a singular resource) for an order id then we can re-request it by unique id (at an endpoint that unambiguously returns a single resource) : /orders/gift_options/{gift_option_id}

This seemed to be broadly accepted so I went away happy. Then as an afterthought I came looking for confirmation that this is about right… and I see an example on the json api which has /articles/{article_id}/author - which I presume returns a single resource?!

This seems potentially confusing to have some endpoints that look like collections but return individual resources. I’m sure I’m not the first to consider this, so is there any prior discussion on this that can help explain the reasoning? Thanks!

If there’s at most one gift_options resource for an order resource, why would you ever want it to be a collection?

It sounds like the order should include a to-one relationship to a gift_options resource, and that can have a URL as indicated in your first suggested URL. There would then be no need for a second URL for the gift_options resource (simpler to explain).

This would make your /orders/{order_id} response look something like this:

{
  "data": {
    "id": "{order_id}",
    "type": "order",
    "attributes": {...},
    "relationships": {
      "gift_options": {
        "data": {"id": "{order_id}", "type": "gift_options"},
        "links": {"related": "/orders/{order_id}/gift_options"}
      },
    },
  }
}

Keep in mind the specification doesn’t impose any constraints on your URL structure; they don’t have to follow the patterns from the examples when that doesn’t make sense.

-Fred

I suppose I was thinking of it from the API user’s perspective. From the outside looking in, we tend to get started with APIs by querying collection style endpoints so that we can find the individual resource ids.

So we’d query /orders and (because no id is in the path) expect it to return multiple items. Same with any path that doesn’t end with an id.

And then we throw a spanner into that pattern by having an endpoint like /orders/id/gift_options. Without knowledge of the API, that instinctively returns a collection of gift_option resources, so when the API user queries that expecting an array, things blow up in a non-intuitive way.

This might be a tangent to the ‘should endpoint names always be pluralised’ discussion. If all endpoints that look like collections always return an array, then those endpoints are also naturally pluralised too. The quirk, as you say, is that some endpoints with one-to-one relationships would only return one item in the array. But maybe the standardisation of all endpoints having the same pluralisation rule, and all collection style endpoints always return collections outweighs that quirk?

(Digging my own hole deeper it’s arguably more forward compatible to return arrays and pluralise as ‘authors’ for some future point in time when the API is updated to allow multiple authors against an article. The reverse - an endpoint that used to return an array being updated to only return a single item - seems like a much easier non-breaking change to deal with in this approach too)

I’m sure a lot of this has been considered already, but just putting it out there incase not!

Relying on pluralisation to provide additional hints sounds like a bad idea helping nobody.

I see no reason why a client should expect to know whether an array or a single item will be returned without having an OPENAPI spec to tell them. Along with the schema for the data content.
I think we can hope that HATEOS can allow the client to explore relationships, but we still need the schema to understand the syntax and content.

The only reason to return a list would be if the “zero or one” rule is an internal situation you expect not to last - i.e. there is no logical reason not to have 2 gift options. If it is and always will be impossible to have more than 1 gift option - then it should be a “to one” as suggested by @fdrake, and call it gift option.

Just my twopenneth :slight_smile:

I don’t know what a “collection style endpoint” is.

For my current application, where I’m applying JSON:API, there’s a single resource that’s retrieved to start from, and that includes a variety of relationships, mostly to collections, that clients know how to start from (based on understanding the specific relationships).

There is nothing about a URL that says anything about whether it’ll return a collection, a resource, or a relationship other than where you obtained it. Since the only URLs a client has are ones that you provide, either as documented starting points or via an API call, it never needs to consider whether a URL “looks like” it should yield a collection.

-Fred

1 Like