REST API Best practice: How to accept as input a list of parameter values

We are launching a new REST API and I wanted some community input on best practices around how we should have input parameters formatted:

Right now, our API is very JSON-centric (only returns JSON). The debate of whether we want/need to return XML is a separate issue.

As our API output is JSON centric, we have been going down a path where our inputs are a bit JSON centric and I’ve been thinking that may be convenient for some but weird in general.

For example, to get a few product details where multiple products can be pulled at once we currently have:

http://our.api.com/Product?id=[“101404″,”7267261”]

Should we simplify this as:

http://our.api.com/Product?id=101404,7267261

Or is having JSON input handy? More of a pain?

We may want to accept both styles but does that flexibility actually cause more confusion and head aches (maintainability, documentation, etc.)?

A more complex case is when we want to offer more complex inputs. For example, if we want to allow multiple filters on search:

http://our.api.com/Search?term=pumas&filters={“productType”:[“Clothing”,”Bags”],”color”:[“Black”,”Red”]}

We don’t necessarily want to put the filter types (e.g. productType and color) as request names like this:

http://our.api.com/Search?term=pumas&productType=[“Clothing”,”Bags”]&color=[“Black”,”Red”]

Because we wanted to group all filter input together.

In the end, does this really matter? It may be likely that there are so many JSON utils out there that the input type just doesn’t matter that much.

I know our javascript clients making AJAX calls to the API may appreciate the JSON inputs to make their life easier.

Thanks, Will

REST API best practice – resource as parameter

Just as OO frequently involves methods where the parameters are objects, it seems that REST inevitably leads to needing to pass a resource as a parameter. How is this best done? One way seems to be th

Web API – How to accept comma separated list of parameter values via query string

I have a Web API project I am working on in Visual Studio 2013, and I’d like for my Controllers to accept a comma separated list of values via the query string, similar to this: http://localhost:12345

REST API filter operator best practice

I am building a REST API that uses a filter parameter to control search results. E.g., one could search for a user by calling: GET /users/?filter=name%3Dfoo Now, my API should allow many different fi

How to develop an ASP.NET Web API to accept a list object as GET parameter?

I have read this link: How to develop an ASP.NET Web API to accept a complex object as parameter? And implemented the code just fine. Now I want to convert the ‘firstName’ parameter to accept an IList

REST API Best practices: Where to put parameters?

A REST API can have parameters in at least two ways: As part of the URL-path (i.e. /api/resource/parametervalue ) As a query argument (i.e. /api/resource?parameter=value ) What is the best practice

Create List input checked array for posting REST API

I’ve used .push() to create List input checked array for posting REST API. But it doesn’t seem right. When unchecking, the item in array is not removed automatically. Anybody have a better solution,

Best practice for rate limiting users of a REST API?

I am putting together a REST API and as I’m unsure how it will scale or what the demand for it will be, I’d like to be able to rate limit uses of it as well as to be able to temporarily refuse request

AngularJS best practice REST / CRUD

What is the best practice of doing CRUD operations via REST with AngularJS? Espesially what is the Angular-Way here. By this I mean the way using the least code and the most default angular settings

Best Practice for documenting Symfony2 based REST API

I like to document my API (REST with JSON) which is written in PHP with the Symfony2 Project. This means I would like to write a public API, which I can give out to my clients, without showing them my

how to accept multiple variables in REST API

i am currenty learning how to use rest api for mobile dev’t, i just want to know is there a method for accepting multiple variables in the URL? for example: $app->get(‘/chara/arena/:id’, ‘getArea’)

Answers

The standard way to pass a list of values as URL parameters is to repeat them:

http://our.api.com/Product?id=101404&id=7267261

Most server code will interpret this as a list of values, although many have single value simplifications so you may have to go looking.

Delimited values is also okay.

If you are needing to send JSON to the server, I don’t like seeing it in in the URL (which is a different format). In particular, URLs have a size limitation (in practice if not in theory).

The way I have seen some do a complicated query RESTfully is in two steps:

  1. POST your query requirements, receiving back an ID (essentially creating a search criteria resource)
  2. GET the search, referencing the above ID
  3. optionally DELETE the query requirements if needed, but note that they requirements are available for reuse.

First case:

A normal product lookup would look like this

http://our.api.com/product/1/

So Im thinking that best practice would be for you to do this

http://our.api.com/Product/101404,7267261/

Second Case

Search with querystring parameters – fine like this. I would be tempted to combine terms with AND and OR instead of using [].

PS This can be subjective, so do what you feel comfortable with.

The reason for putting the data in the url is so the link can pasted on a site/ shared between users. If this isnt an issue, by all means use a JSON/ POST instead.

First:

I think you can do it 2 ways

http://our.api.com/Product/<id> : if you just want one record

http://our.api.com/Product : if you want all records

http://our.api.com/Product/<id1>,<id2> :as James suggested can be an option since what comes after the Product tag is a parameter

Or the one I like most is:

You can use the the Hypermedia as the engine of application state (HATEOAS) property of a RestFul WS and do a call http://our.api.com/Product that should return the equivalent urls of http://our.api.com/Product/<id> and call them after this.

Second

When you have to do queries on the url calls. I would suggest using HATEOAS again.

1) Do a get call to http://our.api.com/term/pumas/productType/clothing/color/black

2) Do a get call to http://our.api.com/term/pumas/productType/clothing,bags/color/black,red

3) (Using HATEOAS) Do a get call to `http://our.api.com/term/pumas/productType/ -> receive the urls all clothing possible urls -> call the ones you want (clothing and bags) -> receive the possible color urls -> call the ones you want

You might want to check out this spec. This URI Template spec shows many examples of how urls can contain parameters.

A Step Back

First and foremost, REST describes a URI as a universally unique ID. Far too many people get caught up on the structure of URIs and which URIs are more “restful” than others. This argument is as ludicrous as saying naming someone “Bob” is better than naming him “Joe” – both names get the job of “identifying a person” done. A URI is nothing more than a universally unique name.

So in REST’s eyes arguing about whether ?id=[“101404″,”7267261”] is more restful than ?id=101404,7267261 or /Product/101404,7267261 is somewhat futile.

Now, having said that, many times how URIs are constructed can usually serve as a good indicator for other issues in a RESTful service. There are a couple of red flags in your URIs and question in general.

Suggestions

  1. Multiple URIs for the same resource and Content-Location

    We may want to accept both styles but does that flexibility actually cause more confusion and head aches (maintainability, documentation, etc.)?

    URIs ID resources. Each resource should have one canonical URI. This does not mean that you can’t have two URIs point to the same resource but there are well defined ways to go about doing it. If you do decide to use both the JSON and list based formats (or any other format) you need to decide which of these formats is the main canonical URI. All responses to other URIs that point to the same “resource” should include the Content-Location header.

    Sticking with the name analogy, having multiple URIs is like having nicknames for people. It is perfectly acceptable and often times quite handy, however if I’m using a nickname I still probably want to know their full name – the “official” way to refer to that person. This way when someone mentions someone by their full name, “Nichloas Telsa”, I know they are talking about the same person I refer to as “Nick”.

  2. “Search” in your URI

    A more complex case is when we want to offer more complex inputs. For example, if we want to allow multiple filters on search…

    A general rule of thumb of mine is, if your URI contains a verb, it may be an indication that something is off. URI’s identify a resource, however they should not indicate what we’re doing to that resource. That’s the job of HTTP or in restful terms, our “uniform interface”.

    To beat the name analogy dead, using a verb in a URI is like changing someone’s name when you want to interact with them. If I’m interacting with Bob, Bob’s name doesn’t become “BobHi” when I want to say Hi to him. Similarly, when we want to “search” Products, our URI structure shouldn’t change from “/Product/…” to “/Search/…”.

Answering Your Initial Question

  1. Regarding [“101404″,”7267261”] vs 101404,7267261: My suggestion here is to avoid the JSON syntax for simplicity’s sake (i.e. don’t require your users do URL encoding when you don’t really have to). It will make your API a tad more usable. Better yet, as others have recommended, go with the standard application/x-www-form-urlencoded format as it will probably be most familiar to your end users (e.g. ?id[]=101404&id[]=7267261). It may not be “pretty”, but Pretty URIs does not necessary mean Usable URIs. However, to reiterate my initial point though, ultimately when speaking about REST, it doesn’t matter. Don’t dwell too heavily on it.

  2. Your complex search URI example can be solved in very much the same way as your product example. I would recommend going the application/x-www-form-urlencoded format again as it is already a standard that many are familiar with. Also, I would recommend merging the two.

Your URI…

/Search?term=pumas&filters={"productType":["Clothing","Bags"],"color":["Black","Red"]}    

Your URI after being URI encoded…

/Search?term=pumas&filters=%7B%22productType%22%3A%5B%22Clothing%22%2C%22Bags%22%5D%2C%22color%22%3A%5B%22Black%22%2C%22Red%22%5D%7D

Can be transformed to…

/Product?term=pumas&productType[]=Clothing&productType[]=Bags&color[]=Black&color[]=Red

Aside from avoiding the requirement of URL encoding and making things look a bit more standard, it now homogenizes the API a bit. The user knows that if they want to retrieve a Product or List of Products (both are considered a single “resource” in RESTful terms), they are interested in /Product/… URIs.