REST API – Single Item Endpoint Responses: List vs. Object

apirest

So I'm currently working on building a restful API. Let's keep it simple and say I have two endpoints, both GET:

/products
/products/{productId}

The first returns a list of all products, the second returns a particular product.

The response for the first endpoint would likely look something this:

[
   {
       "id": 1,
       "name": ...
   },
   ...
]

However, when designing the second endpoint, I was curious whether it would be better to return a singular object like this:

{
    "id": 1,
    "name": ...
}

or a list of one object like:

[
   {
       "id": 1,
       "name": ...
   }
]

In my mind, the former feels more clean and natural (I am getting a particular product, the endpoint should return that product to me), but I could also see arguments for the latter giving more flexibility (ie. the ability to return an empty list vs. returning null).

Indeed, what is generally accepted as a best practice response when the id of the product does not match any stored products? In the first case it seems like you could return null or an exception (404 I would assume), but the second case you would also have the option of returning an empty list (similar to what would happen for the first endpoint if there were no products at all).

Is there guidelines on best practices here? I'm mostly ignoring the wrapper aspect (eg. wrapping the data in another json object and putting the data itself in a property), but if that's pertinent to this decision I'm fine with exploring it.

Best Answer

For endpoints denoting a single resource, such as /products/{productId} it's best to return this resource, not a list. If it does not exist, a 404 error is appropriate.

If you'd access the resource using a query parameter /products?id={productId} you've got a different situation. In this case a one-element or empty list would be the right result.

(Edit:) As @BryanBoettcher rightfully pointed out, this endpoint might return some enumerable structure that you can use to navigate through pages of results, so the actual JSON might look like

{
    "total":1,
    "first_index":0,
    "next_index":1,
    "items":[
        {...}
    ]
}

Note that some people might prefer a 404 error in that case, too, but IMHO the result "we have no product matching this query" is not an error and should be returned as just an empty list.