Identify item by either an ID or a slug in a RESTful API

Go To StackoverFlow.com

21

I'm currently designing an API and I came a cross a little problem: How should a URL of a RESTful API look like when you should be able to identify an item by either an ID or a slug?

I could think of three options:

GET /items/<id>
GET /items/<slug>

This requires that the slug and the ID are distinguishable, which is not necessarily given in this case. I can't think of a clean solution for this problem, except you do something like this:

GET /items/id/<id>
GET /items/slug/<slug>

This would work fine, however this is not the only place I want to identify items by either a slug or an ID and it would soon get very ugly when one wants to implement the same approach for the other actions. It's just not very extendable, which leads us to this approach:

GET /items?id=<id>
GET /items?slug=<slug>

This seems to be a good solution, but I don't know if it is what one would expect and thus it could lead to frustrating errors due to incorrect use. Also, it's not so easy - or let's say clean - to implement the routing for this one. However, it would be easily extendable and would look very similar to the method for getting multiple items:

GET /items?ids=<id:1>,<id:2>,<id:3>
GET /items?slugs=<slug:1>,<slug:2>,<slug:3>

But this has also a downside: What if someone wants to identify some of the items he want to fetch with IDs, but the others with a slug? Mixing these identifiers wouldn't be easy to achieve with this.

What is the best and most widely-accepted solution for these problems? In general, what matters while designing such an API?

2012-04-04 19:39
by Claudio Albertin
Question within a question, what's a slug - Spencer Kormos 2012-04-04 20:00
Wikipedia says: "a user- and SEO-friendly short text used in a URL to identify and describe a resource" or something similar - Claudio Albertin 2012-04-04 20:02
Based on examples in that Wikipedia article and in the Wordpress glossary (http://codex.wordpress.org/Glossary#Slug) it seems like a slug is part of an already hierarchical url. So in your case maybe items is for ids, but items// (as an example) is for slug - Spencer Kormos 2012-04-04 20:17
I think you can also define it as a user-friendly identifier. At least that's what I meant - Claudio Albertin 2012-04-04 20:21


10

Of the three I prefer the third option, it's not uncommon to see that syntax; e.g. parts of Twitter's API allow that syntax: https://dev.twitter.com/rest/reference/get/statuses/show/id

A fourth option is a hybrid approach, where you pick one (say, ID) as the typical access method for single items, but also allow queries based on the slug. E.g.:

GET /items/<id>
GET /items?slug=<slug>
GET /items?id=<id>

Your routing will obvious map /items/id to /items?id=

Extensible to multiple ids/slugs, but still meets the REST paradigm of matching URIs to the underlying data model.

2012-04-04 19:55
by Mike
"the REST paradigm of matching URIs to the underlying data model." is what I'm worried about. But I guess I'll go with this - Claudio Albertin 2012-04-04 20:06
That's almost a Coke/Pepsi question these days. :)

I would say you should support /items/ to be RESTful-certified, but also allowing a query string that searches based on id or slug is will within the paradigm.

And I prefer Coke - Mike 2012-04-04 20:21

As I'll have some query parameters more for searching the items which all return an array, would it be smart to return here an array as well? You could search for slugs, but not clearly identify items by them, so it seems logical to return an array - Claudio Albertin 2012-04-04 20:29
Presumably each complete slug uniquely identifies a resource, so if you enable partial matching on slug searches then I agree an array makes sense. From the perspective of someone consuming RESTful APIs, I'd like to write as little parsing code as possible: even for ID, where you know one match only is returned, I'd be fine with you returning an array. It's arguably not "pure" to return an array when you know it will only ever have one item, but it saves me effort so you'd be forgiven - Mike 2012-04-05 05:22
I'll return an object for GET /items/<id> but an array for all query params, including slug and allow partial matching. This makes the most sense, because a fronted can easily display suggestions to auto-complete a slug, or a name. Slugs and names are for users, IDs for the application - Claudio Albertin 2012-04-05 10:48
Looking at something similar right now. I feel like having the partial matching/array return option be served under URLs with 'search' in them might make more sense, and just have direct resource mapping when only the object noun is used. e.g. /items/search?slug= returns an array of matches, /items?slug= attempts a direct match - jasonmcclurg 2013-12-16 01:51
Ads