I am trying to design a REST API endpoint that has 2 dynamic path parameters whose values can have similar lengths. Example shown below where the base path is /retry.
/retry/<param1> and
/retry/<param2>
param1 can take UTF-8 strings of size 10 while param2 can take UTF-8 of size 10 as well.So as a result there is no structural distinction between param1 and param2.
I am looking for the most elegant way to design the endpoint that has these params as a part of the dynamic URL path and the URLs in both cases can be distinguished from each other.
Some ideas I came across are something like this
/retry/param1-<value of param1> and
/retry/param2-<value of param2>
But I have never seen this approach been undertaken before in API design and to my view it makes the endpoint slightly messy and hard to manage.
I could have added these params as a query parameter instead, but the requirements need me to specify these as path parameters.
Are there better ways to achieve this design requirement?
Reminder: REST doesn't care what spelling conventions you use for your resource identifiers.
Which is good: it means that we can use the extra degrees of freedom to choose a spelling convention that human beings can stand.
A good reference when looking for URI design inspiration is RFC 6570, because if you see a design there that you like, it is likely that your implementation language of choice will have a library that does the general purpose work for you.
So: as noted by Rotem, you might be able to distinguish identifiers because they have a difference sequence of segments.
/retry/param1/x
/retry/param2/y
If the extra segment is unacceptable, then we need to look for alternatives that allow us to distinguish two segments.
URI level 3 template support includes path style parameter expansion which includes a mechanism for expanding key-value pairs.
/retry/param;1=x
/retry/param;2=y
Of course, you could also just describe the two different identifier schemes using two different templates and simple variable expansion
/retry/param1=x
/retry/param2=y
I'm designing a REST API and have an entity for "people":
GET http://localhost/api/people
Returns a list of all the people in the system
GET http://localhost/api/people/1
Returns the person with id 1.
GET http://localhost/api/people?forename=john&surname=smith
Returns all the people with matching forenames and surnames but I have a further requirement. What is the cleanest / best practice way of allowing API consumers to retrieve all the people whose forename starts with "jo" for example.
I've seen some APIs do this like:
GET http://localhost/api/people?forename=jo~&surname=smith
where the tilde signifies a "fuzzy" match. On the other hand I've seen it implemented with a totally different criteria e.g.
GET http://localhost/api/people?forename-startswith=jo&surname=smith
which seems a bit cumbersome considering I might have -endswith, -contains, -soundslike (for some sort of soundex match).
Can anyone suggest from experience which works better and also any examples of well designed REST APIs that have similar functionality.
IMHO it does not matter if you have fuzzy matches or have -endswith -contains etc. What matters is if your REST API permits easy parsing of such parameters so that you can define functions to fetch data from your data source (DB or xml file etc.) accordingly
If you are using PHP...from my experience, SlimFramework is a great light weight, easy-to-get-started solution.
I would recommend you the OData protocol which provides a Query String Options. What you did is ok and follows REST conventions.
But, the OData protocol describes a $expand parameter and even a $filter parameter. This $ prefix denotes "System Query Options" and you will be interested in the last one because it allows you to write the following URI:
http://services.odata.org/Northwind/Northwind.svc/Customers?$filter=tolower(CompanyName) eq 'foobar' &select=FirstName,LastName&$orderby=Name desc
It allows you to pass SQL like data, it can be a nice alternative to what you described (both solutions are fine, it's just a matter of taste).
AFAIK, none of above are quite RESTful. Both of them rely on a priory knowledge on the client's part on how to invoke queries (in the first case, query pattern and on the second one a query DSL). In the second example, in fact, the API is reduced mere to a wrapper around the data store. As such, API does not define a server domain - it is a data provider. This is in contrast to the client-server constraint of REST.
If you need to expose a full-blown data store with all various querying capabilities, you had better stick to known standards which we have OData. OData has been sold as REST but many REST-heads have problems with it. Anyhow, at the end of the day it works and REST discussions can commonly lead to analysis-paralysis.
If I was doing this, I would probably constraint the API to a common use-case, so something more like the second one without defining a query DSL (hence forenameStartsWith rather than forename-startswith).
Having said that, if you need to query based on many fields and various conditions, I would use OData.
Both examples use query parameters for filtering. I don't think it matters what these query parameters are called or if some wildcard syntax is used.
Both approaches are equally RESTFul.
I am in the process of creating a RESTful API. I read
http://microformats.org/wiki/rest/urls
but this site doesn't give me enough "good" practice on designing my API.
Specifically I will write an API (only GET methods that far) which will provide functions to convert geo-coordinates.
Example:
A geohash is a single value representation of a coordinate, thus
/convert/geohash/u09tvkx0.json?outputformat=latlong
makes sense. On the other hand
/convert/latlong.xml?lat=65&long=13&outputformat=UTC requires two input values.
See my "question"? What makes a good API which requires more than one input parameter?
(Tried to "identify" good practice by "analysing" twitter & FF but failed)
In terms of being considered a "technically" correct REST URI, there is no difference between using query string parameters or not. In RFC 3986, it states:
The query component contains non-hierarchical data that, along with data in the path component (Section 3.3), serves to identify a resource
That's why you're having a difficult time finding a definitive "best practice". Having said that, many REST APIs do embed multiple parameters in the URI without using query strings. For exammple, to identify the make and model of a car, you'll see websites with URI's like this: cars.com/honda/civic. In that case it's very obvious the relationship between the 2 and so having everything in the URI is "hackable". It's also much easier to stick with a non-query string approach when you only have one parameter which is uniquely identifying the resource; but if it's something like a search query, then I'd probably keep it in the query string. This SO question has an interesting discussion about the different approaches as well.
In your example above, I would stick with the query string parameters. Although REST typically has more intuitive URLs, that's really not what REST is about. REST is more about hypermedia and HATEOAS.
There are few REST best practices to be followed when designing a REST API
Abstract vs Concrete
CRUD Operations
Error Handling
API Versioning
Filtering
Security
Analytics
Documentation
Stability and Consistency
URL Structure
Read More
Closed. This question needs to be more focused. It is not currently accepting answers.
Closed 7 years ago.
Locked. This question and its answers are locked because the question is off-topic but has historical significance. It is not currently accepting new answers or interactions.
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 here? Are there any general guidelines when to use 1 and when to use 2?
Real world example: Twitter uses query parameters for specifying intervals. (http://api.twitter.com/1/statuses/home_timeline.json?since_id=12345&max_id=54321)
Would it be considered better design to put these parameters in the URL path?
If there are documented best practices, I have not found them yet. However, here are a few guidelines I use when determining where to put parameters in an url:
Optional parameters tend to be easier to put in the query string.
If you want to return a 404 error when the parameter value does not correspond to an existing resource then I would tend towards a path segment parameter. e.g. /customer/232 where 232 is not a valid customer id.
If however you want to return an empty list then when the parameter is not found then I suggest using query string parameters. e.g. /contacts?name=dave
If a parameter affects an entire subtree of your URI space then use a path segment. e.g. a language parameter /en/document/foo.txt versus /document/foo.txt?language=en
I prefer unique identifiers to be in a path segment rather than a query parameter.
The official rules for URIs are found in this RFC spec here. There is also another very useful RFC spec here that defines rules for parameterizing URIs.
Late answer but I'll add some additional insight to what has been shared, namely that there are several types of "parameters" to a request, and you should take this into account.
Locators - E.g. resource identifiers such as IDs or action/view
Filters - E.g. parameters that provide a search for, sorting or narrow down the set of results.
State - E.g. session identification, api keys, whatevs.
Content - E.g. data to be stored.
Now let's look at the different places where these parameters could go.
Request headers & cookies
URL query string ("GET" vars)
URL paths
Body query string/multipart ("POST" vars)
Generally you want State to be set in headers or cookies, depending on what type of state information it is. I think we can all agree on this. Use custom http headers (X-My-Header) if you need to.
Similarly, Content only has one place to belong, which is in the request body, either as query strings or as http multipart and/or JSON content. This is consistent with what you receive from the server when it sends you content. So you shouldn't be rude and do it differently.
Locators such as "id=5" or "action=refresh" or "page=2" would make sense to have as a URL path, such as mysite.com/article/5/page=2 where partly you know what each part is supposed to mean (the basics such as article and 5 obviously mean get me the data of type article with id 5) and additional parameters are specified as part of the URI. They can be in the form of page=2, or page/2 if you know that after a certain point in the URI the "folders" are paired key-values.
Filters always go in the query string, because while they are a part of finding the right data, they are only there to return a subset or modification of what the Locators return alone. The search in mysite.com/article/?query=Obama (subset) is a filter, and so is /article/5?order=backwards (modification). Think about what it does, not just what it's called!
If "view" determines output format, then it is a filter (mysite.com/article/5?view=pdf) because it returns a modification of the found resource rather than homing in on which resource we want. If it instead decides which specific part of the article we get to see (mysite.com/article/5/view=summary) then it is a locator.
Remember, narrowing down a set of resources is filtering. Locating something specific within a resource is locating... duh. Subset filtering may return any number of results (even 0). Locating will always find that specific instance of something (if it exists). Modification filtering will return the same data as the locator, except modified (if such a modification is allowed).
Hope this helped give people some eureka moments if they've been lost about where to put stuff!
It depends on a design. There are no rules for URIs at REST over HTTP (main thing is that they are unique). Often it comes to the matter of taste and intuition...
I take following approach:
url path-element: The resource and its path-element forms a directory traversal and a subresource (e.g. /items/{id} , /users/items). When unsure ask your colleagues, if they think that traversal and they think in "another directory" most likely path-element is the right choice
url parameter: when there is no traversal really (search resources with multiple query parameters are a very nice example for that)
IMO the parameters should be better as query arguments. The url is used to identify the resource, while the added query parameters to specify which part of the resource you want, any state the resource should have, etc.
As per the REST Implementation,
1) Path variables are used for the direct action on the resources, like a contact or a song
ex..
GET etc /api/resource/{songid} or
GET etc /api/resource/{contactid} will return respective data.
2) Query perms/argument are used for the in-direct resources like metadata of a song
ex..,
GET /api/resource/{songid}?metadata=genres it will return the genres data for that particular song.
"Pack" and POST your data against the "context" that universe-resource-locator provides, which means #1 for the sake of the locator.
Mind the limitations with #2. I prefer POSTs to #1.
note: limitations are discussed for
POST in Is there a max size for POST parameter content?
GET in Is there a limit to the length of a GET request? and Max size of URL parameters in _GET
p.s. these limits are based on the client capabilities (browser) and server(configuration).
According to the URI standard the path is for hierarchical parameters and the query is for non-hierarchical parameters. Ofc. it can be very subjective what is hierarchical for you.
In situations where multiple URIs are assigned to the same resource I like to put the parameters - necessary for identification - into the path and the parameters - necessary to build the representation - into the query. (For me this way it is easier to route.)
For example:
/users/123 and /users/123?fields="name, age"
/users and /users?name="John"&age=30
For map reduce I like to use the following approaches:
/users?name="John"&age=30
/users/name:John/age:30
So it is really up to you (and your server side router) how you construct your URIs.
note: Just to mention these parameters are query parameters. So what you are really doing is defining a simple query language. By complex queries (which contain operators like and, or, greater than, etc.) I suggest you to use an already existing query language. The capabilities of URI templates are very limited...
As a programmer often on the client-end, I prefer the query argument. Also, for me, it separates the URL path from the parameters, adds to clarity, and offers more extensibility. It also allows me to have separate logic between the URL/URI building and the parameter builder.
I do like what manuel aldana said about the other option if there's some sort of tree involved. I can see user-specific parts being treed off like that.
There are no hard and fast rules, but the rule of thumb from a purely conceptual standpoint that I like to use can briefly be summed up like this: a URI path (by definition) represents a resource and query parameters are essentially modifiers on that resource. So far that likely doesn't help... With a REST API you have the major methods of acting upon a single resource using GET, PUT, and DELETE . Therefore whether something should be represented in the path or as a parameter can be reduced to whether those methods make sense for the representation in question. Would you reasonably PUT something at that path and would it be semantically sound to do so? You could of course PUT something just about anywhere and bend the back-end to handle it, but you should be PUTing what amounts to a representation of the actual resource and not some needlessly contextualized version of it. For collections the same can be done with POST. If you wanted to add to a particular collection what would be a URL that makes sense to POST to.
This still leaves some gray areas as some paths could point to what amount to children of parent resources which is somewhat discretionary and dependent on their use. The one hard line that this draws is that any type of transitive representation should be done using a query parameter, since it would not have an underlying resource.
In response to the real world example given in the original question (Twitter's API), the parameters represent a transitive query that filters on the state of the resources (rather than a hierarchy). In that particular example it would be entirely unreasonable to add to the collection represented by those constraints, and further that query would not be able to be represented as a path that would make any sense in the terms of an object graph.
The adoption of this type of resource oriented perspective can easily map directly to the object graph of your domain model and drive the logic of your API to the point where everything works very cleanly and in a fairly self-documenting way once it snaps into clarity. The concept can also be made clearer by stepping away from systems that use traditional URL routing mapped on to a normally ill-fitting data model (i.e. an RDBMS). Apache Sling would certainly be a good place to start. The concept of object traversal dispatch in a system like Zope also provides a clearer analog.
Here is my opinion.
Query params are used as meta data to a request. They act as filter or modifier to an existing resource call.
Example:
/calendar/2014-08-08/events
should give calendar events for that day.
If you want events for a specific category
/calendar/2014-08-08/events?category=appointments
or if you need events of longer than 30 mins
/calendar/2014-08-08/events?duration=30
A litmus test would be to check if the request can still be served without an query params.
I generally tend towards #2, As a query argument (i.e. /api/resource?parameter=value ).
A third option is to actually post the parameter=value in the body.
This is because it works better for multi parameter resources and is more extendable for future use.
No matter which one you pick, make sure you only pick one, don't mix and match. That leads towards a confusing API.
One "dimension" of this topic has been left out yet it's very important: there are times when the "best practices" have to come into terms with the plaform we are implementing or augmenting with REST capabilities.
Practical example:
Many web applications nowadays implement the MVC (Model, View, Controller) architecture. They assume a certain standard path is provided, even more so when those web applications come with an "Enable SEO URLs" option.
Just to mention a fairly famous web application: an OpenCart e-commerce shop.
When the admin enables the "SEO URLs" it expects said URLs to come in a quite standard MVC format like:
http://www.domain.tld/special-offers/list-all?limit=25
Where
special-offers is the MVC controller that shall process the URL (showing the special-offers page)
list-all is the controller's action or function name to call. (*)
limit=25 is an option, stating that 25 items will be shown per page.
(*) list-all is a fictious function name I used for clarity. In reality, OpenCart and most MVC frameworks have a default, implied (and usually omitted in the URL) index function that gets called when the user wants a default action to be performed. So the real world URL would be:
http://www.domain.tld/special-offers?limit=25
With a now fairly standard application or frameworkd structure similar to the above, you'll often get a web server that is optimized for it, that rewrites URLs for it (the true "non SEOed URL" would be: http://www.domain.tld/index.php?route=special-offers/list-all&limit=25).
Therefore you, as developer, are faced into dealing with the existing infrastructure and adapt your "best practices", unless you are the system admin, know exactly how to tweak an Apache / NGinx rewrite configuration (the latter can be nasty!) and so on.
So, your REST API would often be much better following the referring web application's standards, both for consistency with it and ease / speed (and thus budget saving).
To get back to the practical example above, a consistent REST API would be something with URLs like:
http://www.domain.tld/api/special-offers-list?from=15&limit=25
or (non SEO URLs)
http://www.domain.tld/index.php?route=api/special-offers-list?from=15&limit=25
with a mix of "paths formed" arguments and "query formed" arguments.
I see a lot of REST APIs that don't handle parameters well. One example that comes up often is when the URI includes personally identifiable information.
http://software.danielwatrous.com/design-principles-for-rest-apis/
I think a corollary question is when a parameter shouldn't be a parameter at all, but should instead be moved to the HEADER or BODY of the request.
It's a very interesting question.
You can use both of them, there's not any strict rule about this subject, but using URI path variables has some advantages:
Cache:
Most of the web cache services on the internet don't cache GET request when they contains query parameters.
They do that because there are a lot of RPC systems using GET requests to change data in the server (fail!! Get must be a safe method)
But if you use path variables, all of this services can cache your GET requests.
Hierarchy:
The path variables can represent hierarchy:
/City/Street/Place
It gives the user more information about the structure of the data.
But if your data doesn't have any hierarchy relation you can still use Path variables, using comma or semi-colon:
/City/longitude,latitude
As a rule, use comma when the ordering of the parameters matter, use semi-colon when the ordering doesn't matter:
/IconGenerator/red;blue;green
Apart of those reasons, there are some cases when it's very common to use query string variables:
When you need the browser to automatically put HTML form variables into the URI
When you are dealing with algorithm. For example the google engine use query strings:
http:// www.google.com/search?q=rest
To sum up, there's not any strong reason to use one of this methods but whenever you can, use URI variables.
I'm currently (I try to) designing a RESTful API for a social network. But I'm not sure if my current approach does still accord to the RESTful principles. I'd be glad if some brighter heads could give me some tips.
Suppose the following URI represents the name field of a user account:
people/{UserID}/profile/fields/name
But there are almost hundred possible fields. So I want the client to create its own field views or use predefined ones. Let's suppose that the following URI represents a predefined field view that includes the fields "name", "age", "gender":
utils/views/field-views/myFieldView
And because field views are kind of higher logic I don't want to mix support for field views into the "people/{UserID}/profile/fields" resource. Instead I want to do the following:
utils/views/field-views/myFieldView/{UserID}
Another example
Suppose we want to perform some quantity operations (hope that this is the right name for it in English). We have the following URIs whereas each of them points to a list of persons -- the friends of them:
GET people/exampleUID-1/relationships/friends
GET people/exampleUID-2/relationships/friends
And now we want to find out which of their friends are also friends of mine. So we do this:
GET people/myUID/relationships/intersections/{Value-1};{Value-2}
Whereas "{Value-1/2}" are the url encoded values of "people/exampleUID-1/friends" and "people/exampleUID-2/friends". And then we get back a representation of all people which are friends of all three persons.
Though Leonard Richardson & Sam Ruby state in their book "RESTful Web Services" that a RESTful design is somehow like an "extreme object oriented" approach, I think that my approach is object oriented and therefore accords to RESTful principles. Or am I wrong?
When not: Are such "object oriented" approaches generally encouraged when used with care and in order to avoid query-based REST-RPC hybrids?
Thanks for your feedback in advance,
peta
I've never worked with REST, but I'd have assumed that GETting a profile resource at '''/people/{UserId}/profile''' would yield a document, in XML or JSON or something, that includes all the fields. Client-side I'd then ignore the fields I'm not interested in. Isn't that much nicer than having to (a) configure a personalised view on the server or (b) make lots of requests to fetch each field?
Hi peta,
I'm still reading through RESTful Web Services myself, but I'd suggest a slightly different approach than the proposed one.
Regarding the first part of your post:
utils/views/field-views/myFieldView/{UserID}
I don't think that this is RESTful, as utils is not a resource. Defining custom views is OK, however these views should be (imho) a natural part of your API's URI scheme. To incorporate the above into your first URI example, I would propose one of the following examples instead of creating a special view for it:
people/{UserID}/profile/fields/name,age,gender/
people/{UserID}/profile/?fields=name,age,gender
The latter example considers fields as an input value for your algorithm. This might be a better approach than having fields in the URI as it is not a resource itself - it just puts constraints on the existing view of people/{UserID}/profile/. Technically, it's very similar as pagination, where you would limit a view by default and allow clients to browse through resources by using ?page=1, ?page=2 and so on.
Regarding the second part of your post:
This is a more difficult one to crack.
First:
Having intersection in the URI breaks your URI scheme a bit. It's not a resource by itself and also it sits on the same level as friends, whereas it would be more suitable one level below or as an input value for your algorithm, i.e.
GET people/{UserID}/relationships/friends/intersections/{Value-1};{Value-2}
GET people/{UserID}/relationships/friends/?intersections={Value-1};{Value-2}
I'm again personally inclined to the latter, because similarly as in the first case, you are just constraining the existing view of people/{UserID}/relationships/friends/
Secondly, regarding:
Whereas "{Value-1/2}" are the url
encoded values of
"people/exampleUID-1/friends" and
"people/exampleUID-2/friends"
If you meant that {Value-1/2} contain the whole encoded response of the mentioned GET requests, then I would avoid that - I don't think that the RESTful way. Since friends is a resource by itself, you may want to expose it and access it directly, i.e.:
GET friends/{UserID-1};{UserID-2};{UserID-3}
One important thing to note here - I've used ; between user IDs in the previous example, whereas I used , in the fields example above. The reasoning is that both represent a different operator. In the first case we needed OR (,) in order to get all three fields, while in the last example above we had to use AND (;) in order to get an intersection.
Usage of two types of operators can over-complicate the API design, but it should provide more flexibility in the end.
thanks for your clarifying answers. They are exactly what I was asking for. Unfortunately I hadn't the time to read "RESTful Web Services" from cover to cover; but I will catch it up as soon as possible. :-)
Regarding the first part of my post:
You're right. I incline to your first example, and without fields. I think that the I don't need it at all. (At the moment) Why do you suggest the use of OR (,) instead of AND (;)? Intuitively I'd use the AND operator because I want all three of them and not just the first one existing. (Like on page 121 the colorpairs example)
Regarding the second part:
With {Value-1/2} I meant only the url-encoded value of the URIs -- not their response data. :) Here I incline with you second example. Here it should be obvious that under the hood an algorithm is involed when calculating intersecting friends. And beside that I'm probably going to add some further operations to it.
peta