8

I'm designing a REST API for the first time, so I have what I consider a quite basic question about its design.

I would like the files collection to return an ID (or a link) of all available file resources instead of retrieving the full representation because it would be too much data.

GET /files        # return the full representation of a collection of resources
GET /files/{id}   # return the full representation of a single resource 

I don't know if it is better to split it in two different resources:

GET /fileids      # return only IDs
GET /files/{id}   # return the full representation of a single resource

What would be your approach?

cassiomolin
  • 124,154
  • 35
  • 280
  • 359

2 Answers2

8

Custom media type

You could have a custom media type for the full representation of the resource and a custom media type for the identifiers of the files.

For example, you could use one of the following (or both) media types to retrieve a full representation of a collection of files:

GET /api/files HTTP/1.1
Host: example.com
Accept: application/json
GET /api/files HTTP/1.1
Host: example.com
Accept: application/vnd.company+json

And the following media type to retrieve only the identifiers of the files:

GET /api/files HTTP/1.1
Host: example.com
Accept: application/vnd.company.id+json

Query string parameter

Alternatively, you could support selecting the fields to be retrieved with a query string parameter.

Use the following to retrieve the full representation of a collection of files:

GET /api/files HTTP/1.1
Host: example.com
Accept: application/json

And the following to retrieve only the identifiers of the files:

GET /api/files?fields=id HTTP/1.1
Host: example.com
Accept: application/json

The field query parameter could support a list of values separated by commas, allowing the selection of multiple fields/properties:

GET /api/files?fields=id,name,author HTTP/1.1
Host: example.com
Accept: application/json
cassiomolin
  • 124,154
  • 35
  • 280
  • 359
  • 1
    Using `Accept` is even better. Reason: It is still the same *resource*, a different *representation* is requested. Using different URIs for the same resource is a little unRESTful. –  May 26 '16 at 10:58
  • I understand that this is the best solution but I think that I am going to main the interface simpler even not-so-RESTful –  May 26 '16 at 17:38
  • I think easier to implement/understand the query string solution, however, if I only support the retrieval of specific fields, in other words, I only shall provide "id" fields. What should answer in case of a "GET /api/files" or "GET /api/files?fields=id,name,author"? 400 Error? –  May 26 '16 at 17:41
  • 1
    @chrpinedo Yes, a `400` is fine. Just remember providing a good description of the error in the response payload. – cassiomolin May 26 '16 at 17:50
  • And how this fits with RAML? I think "queryParameters" of RAML are more related to get an specific list of resources instead of changing the fields of the resource. So, I don't know if it is possible to define different JSON Schemas taking into account the "queryParameters". –  May 26 '16 at 17:59
  • 1
    @chrpinedo Sorry, unfortunately I have no experience with RAML. But, if you ask a new question, I'm sure someone will be able to help you with it. – cassiomolin May 26 '16 at 18:05
0

Just do it.

I would call it a standard RESTful API design pattern to have an abbreviated resource representation in your collections resource and the full representation only on your entity resource.

So /files would return something like:

[
  {
    name: "foo",
    url: "example.org/files/3321"
  },
  {
    name: "bar",
    url: "example.org/files/3192910"
  }
]

While /files/3321 returns the full file representation

{
  name: "foo",
  self: "example.org/files/3321"
  encoding: "UTF-8",
  type: "xml-document"
}
Johannes Thorn
  • 902
  • 6
  • 13
  • Providing a partial representation of a resource when performing a `GET` to collection resource is an interesting approach. However, I would let the client select which fields they want. Consider, for example, you provide only the `name` attribute but the client actually needs the `name` and `type`. In this situation, the client would need to perform a request to the collection resource and then perform one request for each item of the collection to return further details of the resource. Summing up, there will be *n+1* requests while only one would be enough. So, I understand it's a non-go. – cassiomolin May 26 '16 at 13:39
  • Yeah that would be a problem I once implemented a mixture of both worlds. The service provided a good default fieldset, which the client could overwrite for specific patial representations. – Johannes Thorn May 26 '16 at 14:20