2

I'm designing a REST API that returns a collection of elements that can contain some verbose metadata, similar to one that might return books from a library.

Is there a REST API design pattern to offer two different responses to a /books GET query, one which returns a full listing of books and metadata (title, author, publisher, page count, etc.), and one that just returns summary information (title and author)? I've considered using a query parameter, like "?summary", and this implementation is not difficult.

Then the other side of this is, using "?summary", I get a very different JSON structure than without.

Is a query parameter a good approach? And how do I reconcile this requirement with returning a consistent response for all queries to this endpoint? (I don't want to use separate /books and /books_summary endpoints.)

3
  • why dont you want to use different endpoints?
    – Ewan
    Aug 20 at 18:47
  • I see REST endpoints as corresponding to resources, and it is the same collection of resources, just different format output
    – PaulMcG
    Aug 20 at 20:06
  • you are returning a different type, rather than a different format (json/xml). The simple common answer is that is a different "resource"
    – Ewan
    Aug 21 at 8:44
3

I've seen two main patterns:

  • Having something like a fields parameter that lets the user query for exactly the fields they want, providing a default set if not specified.
  • Returning summary data in a list endpoint, but detailed data in individual resource endpoints. e.g. /books contains summary data, but /book/1 contains detailed data.

Your summary idea is not terrible. Could also call it verbose. The main drawback I see is that different people have different ideas of what belongs in a summary, so if you're not careful, you might end up with that creeping larger over time.

1

It usually involves either dividing out the endpoint further:

e.g. into /books/verbose and /books/summary,

or else adding a flag (as you describe):

.../books?output-format=verbose

or

.../books?output-format=summary

This is the way it is usually done, although the method you choose should be the one that best suits the context. If you write out the pros & cons of each and compare, one of them will almost always show itself as the better option.

There are other ways of achieving the same, but none that are more appealing to the general use case.

1

As with most things, the useful heuristic is "how would I do this on the web?"

The first question to address is your resource model: are the full listing and the summary two different resources? or are they two different representations of the same resource?

In the case where the different representations are different resources, then they have different identifiers. You can use any convention you like for distinguishing the two identifiers. Using a query parameter is fine. Using a path parameter is fine. There are technical trade offs (HTML form support vs relative referencing) in addition to the aesthetics (which spelling looks nicer in the log file) but the machines don't care which spelling you decide on.

If they are two different representations of the same resource, then you are probably going to end up leaning into proactive negotiation, and helping general purpose caches do the right thing with the Vary header.


Some things to consider: if the rich representation and the summary representation have the same identifier, then it becomes that much more difficult to share links to a particular representation. The negotiation initially performed by a general purpose client is likely to include the same headers that it sends to every other resource on the web. "Please send me an HTML representation if you have one, in my human's preferred language". So which ever of the two representations you choose as the "default" is the one that people are going to end up with most of the time.


Also, it's probably worth noting that Fielding 2006 would likely discourage you from considering these two representations variations of the same resource

We encourage resource owners to only use true content negotiation (without redirects) when the only difference between formats is mechanical in nature.


Finally, note that REST doesn't constraint your implementation at all. It's perfectly reasonable to have two different resources implemented using the same controller, and it is of course in bounds to choose identifier spellings that make your implementation easier to maintain (ie: by conforming to the conventions of your server framework).


Then the other side of this is, using "?summary", I get a very different JSON structure than without.

Yup - perfectly reasonable as far as REST is concerned. You'll need some sort of metadata to identify the schema of the representation that is being used. That might end up being a hint in Content-Type header, or it might be communicated using Web Linking.

1
  • I like the Content-Type header hint. But I'm getting major push in my team to go with a different endpoint, so that is probably the way it will go. In my next life I'll try the query parameter.
    – PaulMcG
    Aug 24 at 17:21
1

I've considered using a query parameter, like "?summary", and this implementation is not difficult.

This is a strong indication that you are talking about different resources. A query parameter is simply a more flexible way of designing a URI scheme when you don't now the exact input, but the whole string is still its own URI pointing to a unique resource

For example

https://www.google.com/search?q=rest

and

https://www.google.com/search?q=rest_introduction

are pointing to two different unique resources, even though they use the search URI with a query parameter. 'Search' is not the resource, the resources is the search results for the specific query.

So if you are using query strings you by definition have multiple resources

/books

and

/books?summary

are different resources. Make life easy for yourself and have /books and /books_summary or /books/summary

If you really really insist on not doing that you could also have one URI /books and pass different Content-Types to the server, one saying you want the books in normal format and one in summary format.

Something like

application/vnd.mycompany.book_collection

and

application/vnd.mycompany.book_collection_summary

Since you are changing a lot of data in the result based on Content Type I would recommend against this though, I would make your life simple and just use two different resources

1
  • A big part of this is to make the API easily accessible from a browser using simple GETs - there is no UI, so I just need to serve up pretty JSON. I could make up a SwaggerUI, and that should let me use the Content-Types header. My object modeling brain really wants to say this is not a different resource. But for the sake of humanity (i.e., future maintainers of my code), I'll probably go with that.
    – PaulMcG
    Aug 24 at 17:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.