156

I am building a REST API for my project. The API for getting a given user's INFO is:

api.com/users/[USER-ID]

I would like to also allow the client to pass in a list of user IDs. How can I construct the API so that it is RESTful and takes in a list of user ID's?

1
  • The most generic answer is given by @Shuja, cause other answers from postman didn't work and are dependent on the database backend. However, you can have an API end-point to request for multiple id's. Commented Jan 22, 2019 at 12:50

6 Answers 6

124

If you are passing all your parameters on the URL, then probably comma separated values would be the best choice. Then you would have an URL template like the following:

api.com/users?id=id1,id2,id3,id4,id5
Sign up to request clarification or add additional context in comments.

15 Comments

@uclajatt, REST is an architectural model and not a protocol and if you study the major REST APIs available today, you will see that there are multiple ways of implementing it. The approach that I am suggesting is probably one of the closest to the concept since it accomplishes all the constraints described here: en.wikipedia.org/wiki/…. You would only use CSV to represent arrays in requests, while the service responses should be serialized using XML or JSON. Are there any particular reasons why you don't consider my approach to be REST?
Why not this? api.com/users?id=id1&id=id2&id=id3&id=id4&id=id5
@senfo, I prefer id=id1,id2,id3 because it makes the URI shorter and easier to read (by a human, during a debugging operation for example). Individual parameters for each value would make the URI especially harder to follow if there are other parameters between ids: api.com/users?id=id1&id=id2&joined-after=2013-01-01&id=id3
However, most web servers support the URL length of about 2,000 bytes. How to make my API support up to 5,000 ids?
@senfo In URLs like …?id=1&id=2&id=3, there is no guarantee that duplicate query parameters will be combined into an array. With the above query string, PHP happens to tell you that id equals [1, 2, 3], but Ruby on Rails tells you it equals 3, and other frameworks may also act differently, e.g. saying id equals 1. URLs like …?id=1,2,3 avoid this potential for confusion.
|
47
 api.com/users?id=id1,id2,id3,id4,id5
 api.com/users?ids[]=id1&ids[]=id2&ids[]=id3&ids[]=id4&ids[]=id5

IMO, above calls does not looks RESTful, however these are quick and efficient workaround (y). But length of the URL is limited by webserver, eg tomcat.

RESTful attempt:

POST http://example.com/api/batchtask

   [
    {
      method : "GET",
      headers : [..],
      url : "/users/id1"
    },
    {
      method : "GET",
      headers : [..],
      url : "/users/id2"
    }
   ]

Server will reply URI of newly created batchtask resource.

201 Created
Location: "http://example.com/api/batchtask/1254"

Now client can fetch batch response or task progress by polling

GET http://example.com/api/batchtask/1254


This is how others attempted to solve this issue:

8 Comments

POST request to get multiple results is not RESTful. Your example shows creating a resource, where it is appropriate to POST, but that is a totally different case to the original question
Creating temporary resource is RESTful, isnt it? And I am getting resources using GET, its again RESTful.
yes, but none of that was in the original question, which just asks about getting info for multiple user ids
Thanks @Anentropic for pointing out. I read the question again it asks How to construct a REST API that takes an array of id's for the resources ? and I agree, my answer is different. Sorry for not getting your point.
It might violate Cacheability REST principle. Caching such requests is difficult. If we cache responses to such batch requests then invalidating is difficult.
|
27

I find another way of doing the same thing by using @PathParam. Here is the code sample.

@GET
@Path("data/xml/{Ids}")
@Produces("application/xml")
public Object getData(@PathParam("zrssIds") String Ids)
{
  System.out.println("zrssIds = " + Ids);
  //Here you need to use String tokenizer to make the array from the string.
}

Call the service by using following url.

http://localhost:8080/MyServices/resources/cm/data/xml/12,13,56,76

where

http://localhost:8080/[War File Name]/[Servlet Mapping]/[Class Path]/data/xml/12,13,56,76

2 Comments

I like this one because the GET is consistent. You can use one number or many in this example. And it is not really a search (parameters), as you are giving the back end the exact ids you want.
I see the most upvoted answer doesn't work and your answer is probably the most generic one. Should be accepted as the answer.
24

As much as I prefer this approach:-

    api.com/users?id=id1,id2,id3,id4,id5

The correct way is

    api.com/users?ids[]=id1&ids[]=id2&ids[]=id3&ids[]=id4&ids[]=id5

or

    api.com/users?ids=id1&ids=id2&ids=id3&ids=id4&ids=id5

This is how rack does it. This is how php does it. This is how node does it as well...

3 Comments

I'm not sure that referencing PHP standards as a guideline to follow is the best advice. eev.ee/blog/2012/04/09/php-a-fractal-of-bad-design
This is not how Flask does it.
why bother with the querysting, just put it in the path and split on the comma
0

There seems to be a few ways to achieve this. I'd like to offer how I solve it:

GET /users/<id>[,id,...]

It does have limitation on the amount of ids that can be specified because of URI-length limits - which I find a good thing as to avoid abuse of the endpoint.

I prefer to use path parameters for IDs and keep querystring params dedicated to filters. It maintains RESTful-ness by ensuring the document responding at the URI can still be considered a resource and could still be cached (although there are some hoops to jump to cache it effectively).

I'm interested in comments in my hunt for the ideal solution to this form :)

Comments

-4

You can build a Rest API or a restful project using ASP.NET MVC and return data as a JSON. An example controller function would be:

        public JsonpResult GetUsers(string userIds)
        {
           var values = JsonConvert.DeserializeObject<List<int>>(userIds);

            var users = _userRepository.GetAllUsersByIds(userIds);

            var collection = users.Select(user => new { id = user.Id, fullname = user.FirstName +" "+ user.LastName });
            var result = new { users = collection };

            return this.Jsonp(result);
        }
        public IQueryable<User> GetAllUsersByIds(List<int> ids)
        {
            return _db.Users.Where(c=> ids.Contains(c.Id));
        }

Then you just call the GetUsers function via a regular AJAX function supplying the array of Ids(in this case I am using jQuery stringify to send the array as string and dematerialize it back in the controller but you can just send the array of ints and receive it as an array of int's in the controller). I've build an entire Restful API using ASP.NET MVC that returns the data as cross domain json and that can be used from any app. That of course if you can use ASP.NET MVC.

function GetUsers()
    {
           var link = '<%= ResolveUrl("~")%>users?callback=?';
           var userIds = [];
            $('#multiselect :selected').each(function (i, selected) {
                userIds[i] = $(selected).val();
            });

            $.ajax({
                url: link,
                traditional: true,
                data: { 'userIds': JSON.stringify(userIds) },
                dataType: "jsonp",
                jsonpCallback: "refreshUsers"
            });
    }

4 Comments

Sorry, I wasnt' asking for how to implement the API. I was just asking of how to construct the API URI so that the client can access info about an array of users. I can pass id's via query parameters, but I believe that wont' be very restful.
@uclajatt Why do you think that is not RESTful?
I believe passing id's or any other values via query parameters is indeed a restful approach of interacting with a system. How you construct you Uri it's up to you. Being it users/all, users/array, array/users or any other naming convention you feel that makes sense. Taking in consideration how the MVC framework works its very easy to use it for building a restful API as you can organize and build you Uris just as you need them.Once you have your Uris, you can pass you parameters using AJAX as one string, or as multiple values if your are using a form and doing a post to an MVC action.
@uclajatt Thats twice now you've been asked on this post why you think passing a comma seperated list in a query parameter is not RESTful and you don't even bother to answer it, let alone accept any of these very plausible solutions !?! Not cool.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.