REST API Endpoint naming for specific sub-categories of data - rest

Say I have an API that (along with other entities) deals with tasks. My endpoints would look something like
GET /api/tasks //List all tasks
POST /api/tasks //Create a new task
GET /api/task/1 //Fetch a single task
PUT /api/task/1 //Update a single Tasks
GET /api/task/1/comments //Get the comments of task 1
I also need a few subsets of Task data which has an entirely different formats:
user-tasks, tasks for a user but shaped according to schedule.
sync-data, all tasks that need to be sent to an external system with special references
I can see the user data could exist off the user hierarchy such as
GET /api/user/1/tasks //tasks for this user with dedicated
But what of sync-data? Should this fall under the tasks heirarchy or under the system it's intended for such as
GET /api/ExternalSystemA/tasks //tasks for synchronization

REST doesn't care what spelling conventions you use for your URI. Any spellings that are consistent with the production rules in RFC 3986 are fine.
Relative resolution provides a standardized mechanism for computing a new URI from a context and a relative reference. Designing your hierarchy so that you can take advantage of that is, in some cases, a really good idea.
Otherwise, it is a lot like choosing a variable name - the machine doesn't care, so you just want to choose spellings that are satisfactory for other human beings; in other words, making sure that you are consistent with local conventions.

Related

Sub-resource creation url

Lets assume we have some main-resource and a related sub-resource with 1-n relation;
User of the API can:
list main-resources so GET /main-resources endpoint.
list sub-resources so GET /sub-resources endpoint.
list sub-resources of a main-resource so one or both of;
GET /main-resources/{main-id}/sub-resources
GET /sub-resouces?main={main-id}
create a sub-resource under a main-resource
POST /main-resource/{main-id}/sub-resouces: Which has the benefit of hierarchy, but in order to support this one needs to provide another set of endpoints(list, create, update, delete).
POST /sub-resouces?main={main-id}: Which has the benefit of having embedded id inside URL. A middleware can handle and inject provided values into request itself.
create a sub-resource with all parameters in body POST /sub-resources
Is providing a URI with main={main-id} query parameter embedded a good way to solve this or should I go with the route of hierarchical URI?
In a true REST environment the spelling of URIs is not of importance as long as the characters used in the URI adhere to the URI specification. While RFC 3986 states that
The path component contains data, usually organized in hierarchical form, that, along with data in the non-hierarchical query component (Section 3.4), serves to identify a resource within the scope of the URI's scheme and naming authority (if any). The path is terminated by the first question mark ("?") and number sign ("#") character, or by the end of the URI. (Source)
it does not state that a URI has to have a hierarchical structure assigned to it. A URI as a whole is a pointer to a resource and as such a combination of various URIs may give the impression of some hierarchy involved. The actual information of whether URIs have some hierarchical structure to it should though stem from link relations that are attached to URIs. These can be registered names like up, fist, last, next, prev and the like or Web linking extensions such as https://acme.org/rel/parent which acts more like a predicate in a Semantic Web relation basically stating that the URI at hand is a parent to the current resource. Don't confuse rel-URIs for real URIs though. Such rel-URIs do not necessarily need to point to an actual resource or even to a documentation. Such link relation extensions though my be defined by media-types or certain profiles.
In a perfect world the URI though is only used to send the request to the actual server. A client won't parse or try to extract some knowledge off an URI as it will use accompanying link relation names to determine whether the URI is of relevance to the task at hand or not. REST is full of such "indirection" mechanism in order to help decoupling clients from servers.
I.e. what is the difference between a URI like https://acme.org/api/users/1 and https://acme.org/api/3f067d90-8b55-4b60-befc-1ce124b4e080? Developers in the first case might be tempted to create a user object representing the data returned by the URI invoked. Over time the response format might break as stuff is renamed, removed and replaced by other stuff. This is what Fielding called typed resources which REST shouldn't have.
The second URI doesn't give you a clue on what content it returns, and you might start questioning on what benefit it brings then. While you might not be aware of what actual content the service returns for such URIs, you know at least that your client is able to process the data somehow as otherwise the service would have responded with a 406 Not Acceptable response. So, content-type negotiation ensures that your client will with high certainty receive data it is able to process. Maintaining interoperability in a domain that is likely to change over time is one of RESTs strong benefits and selling points. Depending on the capabilities of your client and the service, you might receive a tailored response-format, which is only applicable to that particular service, or receive a more general-purpose one, like HTML i.e.. Your client basically needs a mapping to translate the received representation format into something your application then can use. As mentioned, REST is probably all about introducing indirections for the purpose of decoupling clients from servers. The benefit for going this indirection however is that once you have it working it will work with responses issued not only from that server but for any other service that also supports returning that media type format. And just think a minute what options your client has when it supports a couple of general-purpose formats. It then can basically communicate and interoperate with various other services in that ecosystem without a need for you touching it. This is how browsers operate on the Web for decades now.
This is exactly why I think that this phrase of Fielding is probably one of the most important ones but also the one that is ignored and or misinterpreted by most in the domain of REST:
A REST API should spend almost all of its descriptive effort in defining the media type(s) used for representing resources and driving application state, or in defining extended relation names and/or hypertext-enabled mark-up for existing standard media types. (Source)
So, in a true REST environment the form of the URI is unimportant as clients rely on other mechanisms to determine whether to use that URI or not. Even for so called "REST APIs" that do not really care about the true meaning of REST and treat it more like old-school RPC the question at hands is probably very opinionated and there probably isn't that one fits all solution. If your framework supports injecting stuff based on the presence of certain query parameters, use that. If you prefer the more hierarchical structure of URIs, go for those. There isn't a right or wrong in such cases.
According to the URI standard when you have a hierarchical relationship between resources, then better to add it to the path instead of the query. https://datatracker.ietf.org/doc/html/rfc3986#page-22 Sometimes it is better to describe the relation itself, not just the sub-resource, but that happens only if the sub-resource can belong to multiple main resources, which is n:m relationship.

REST resource for checking if a resource has existing subresources

My application provides the following resource:
GET /user/:id/orders
As commonly used, this returns a list of all the user's orders.
Now, a client wants to check if a user has any orders at all without actually getting the complete list.
My current approach looks like this:
GET /user/:id/orders/exist
But it looks kind of odd to me.
Is there a more "standard" way of designing this? In the end, this resource only needs to return the information:
yes, user has orders
no, user doesn't have any orders
What you will see in some API is the notion of a resource that exists (204) or does not exist (404).
But I really don't recommend that: saving a few bytes in your representation of the resource doesn't help very much when you are already sending a response-line and a bunch of HTTP headers.
Your "resource model" can be anything you want.
The REST interface is designed to be efficient for large-grain hypermedia data transfer, optimizing for the common case of the Web, but resulting in an interface that is not optimal for other forms of architectural interaction -- Fielding, 2000
So you can create fine grained resources if you like; but there are can be consequences to that. "Tradeoffs" are a thing.
Resources are generalizations of "documents"; if it makes sense to have a report that is just a count of the number of orders, or a statement that the number of orders is greater than zero, or whatever, then that report can certainly be a resource in your resource model.
If you know what the report is, then you might be able to guess at a name for the report, and from there to a spelling for it.
There's no particular reason that the report identifier has to be part of the /user hierarchy; the machines don't care what spelling conventions you use.
/user/:id/orders/report
/user/:id/orders-report
/user/:id/report
/report/:id
/report?user=:id
/report/user=:id
Those are all fine; choose whichever variation is appropriate to your local conventions.
Note that you want to be aware of caching - when you have information in two different resources, it is easy for the client's locally cached copies to contradict each other (report says that there are orders, but the orders list is empty; or the other way around). As far as REST, and general purpose components are concerned, different resources are different, and vary independently of each other.
In the large grained world, you don't have that problem so often, because you throw the kitchen sink into a single resource; as long as its produced representations are internally consistent, the cached copies will be as well.

How to handle name conflict with action in RESTful API

RESTful API should be focused on resource and not action.
However, when implementing RESTful on HTTP, due to the limited expressiveness of the HTTP methods, people add [action] to the end of the URL.
e.g.:
http://rebilly.github.io/ReDoc/#operation/findPetsByStatus
https://developers.google.com/drive/api/v3/reference/
(DELETE /files/trash and GET /files/generateIds)
For API that the ID is defined by the user, the above design would lead to conflicts.
i.e. user creating a pet findPetsByStatus or a file trash or generateIds.
The API designer cannot prevent this from happening because we cannot foresee the future. i.e. we can't reserves all keywords that might be used as actions because the product evolves and changes over time.
Under this circumstances, how to design an API so we won't run into such problem?
I would like to follow OpenAPI spec but they disallow API with /files?action=<someAction>
Under this circumstances, how to design an API so we won't run into such problem?
Change the stem; restrict the identifiers with user provided spellings to a different part of your endpoint hierarchy than the operations where you would need to worry about reserved words.
That is to say, you treat your URI space as a bunch of partitioned name spaces; you let your users customize the spellings in one name space, you put your api operations in another. Ta-Da.
/b9d97060-d4db-4b20-a654-22bb0653db69/pets
/08f9a7c2-353b-484d-9e87-56acca4e5a57/pets
See? No conflicts.
If somebody insists that all pet endpoints must be located under /pets, then just invert the ordering
/pets/b9d97060-d4db-4b20-a654-22bb0653db69
/pets/08f9a7c2-353b-484d-9e87-56acca4e5a57
Another possibility would be to host pet management on a different host than your pet utilities.
http://search.example.org/pets
http://api.example.org/pets
In a spelling argument, you might be able to find some support in the ubiquitous language of your domain. For example, in a setting where you speak of consumers registering their pets, you could argue
/pets/registry
/pets/forms
separates the documents that describe the registered pets from the forms used to do interesting things with the registered pets.
/pets/registry/findPetsByStatus <-- the dog belonging to [Bobby Tables][1]
/pets/forms/findPetsByStatus <-- the documents used to integrate with the pets service
Don't get too caught up in the spelling debate -- loading a /findPetsByStatusForm and submitting it to get a /findPetsByStatusReport may pass the noun test, but it doesn't improve the quality of the API.

Rest: different representations of a same resource

If entity (e.g person) has data that has to be presented in different representations:
I have a big profile that has different representations but for a small example:
representations1:
GET /profiles/{id}/activity/projection1
returns:
{"actions":["add", "delete", "add"], "dates":[1499865456, 1499861544, 1499863655]}
representations2:
GET /profiles/{id}/activity/projection2
returns:
{add_at:[1499865456, 1499863655], delete_at:[1499861544]}
So the question: how to design such cases?
I have some ideas but don't know which one is better
GET /profiles/{id}/activity/projection1
GET /profiles/{id}/activity/projections/1
GET /profiles/{id}/activities/projection1
GET /profiles/{id}/activities/projections/1
GET /profiles/{id}/activity-actions and GET /profiles/{id}/activity-timestamps
I found only one same question Different RESTful representations of the same resource but it is about filtering data in response not about change model
A couple things to keep in mind
As far as REST is concerned, two things with different identifiers (URI) are different resources. The fact that they have the same source of truth is an implementation detail.
In designing a REST api, your resources are integration points. The representations of your resources will depend on the state of your model at any given time.
For instance, if I look up Clayton Kershaw at Baseball Reference, I am probably directed to this resource
http://www.baseball-reference.com/players/k/kershcl01.shtml
But if I ask to see his "2014 splits", then I'll be directed to this resource instead.
http://www.baseball-reference.com/players/split.fcgi?id=kershcl01&year=2014&t=p
There's no particular reason that every resource identifier related to kershcl01 has to be under the same root in the hierarchy.
You may want to review Cool URIs don't change; stable URI over time is a good goal for a design, in which case you'll want to make sure that temporary implementation details don't leak into the URI space.
Jim Webber's observation was that REST resources are part of your integration domain; "Resources adapt your domain model for the web."
So your design guidance should probably come from asking what properties are important to your consumers, and what constraints will ensure that those properties are present (outside in), rather than starting from your (current) implementation.

RESTful POSTS, do you POST objects to the singular or plural Uri?

Which one of these URIs would be more 'fit' for receiving POSTs (adding product(s))? Are there any best practices available or is it just personal preference?
/product/ (singular)
or
/products/ (plural)
Currently we use /products/?query=blah for searching and /product/{productId}/ for GETs PUTs & DELETEs of a single product.
Since POST is an "append" operation, it might be more Englishy to POST to /products, as you'd be appending a new product to the existing list of products.
As long as you've standardized on something within your API, I think that's good enough.
Since REST APIs should be hypertext-driven, the URI is relatively inconsequential anyway. Clients should be pulling URIs from returned documents and using those in subsequent requests; typically applications and people aren't going to need to guess or visually interpret URIs, since the application will be explicitly instructing clients what resources and URIs are available.
Typically you use POST to create a resource when you don't know the identifier of the resource in advance, and PUT when you do. So you'd POST to /products, or PUT to /products/{new-id}.
With both of these you'll return 201 Created, and with the POST additionally return a Location header containing the URL of the newly created resource (assuming it was successfully created).
In RESTful design, there are a few patterns around creating new resources. The pattern that you choose largely depends on who is responsible for choosing the URL for the newly created resource.
If the client is responsible for choosing the URL, then the client should PUT to the URL for the resource. In contrast, if the server is responsible for the URL for the resource then the client should POST to a "factory" resource. Typically the factory resource is the parent resource of the resource being created and is usually a collection which is pluralized.
So, in your case I would recommend using /products
You POST or GET a single thing: a single PRODUCT.
Sometimes you GET with no specific product (or with query criteria). But you still say it in the singular.
You rarely work plural forms of names. If you have a collection (a Catalog of products), it's one Catalog.
I would only post to the singular /product. It's just too easy to mix up the two URL-s and get confused or make mistakes.
As many said, you can probably choose any style you like as long as you are consistent, however I'd like to point out some arguments on both sides; I'm personally biased towards singular
In favor of plural resource names:
simplicity of the URL scheme as you know the resource name is always at plural
many consider this convention similar to how databases tables are addressed and consider this an advantage
seems to be more widely adopted
In favor of singular resource names (this doesn't exclude plurals when working on multiple resources)
the URL scheme is more complex but you gain more expressivity
you always know when you are dealing with one or more resources based on the resource name, as opposed to check whether the resource has an additional Id path component
plural is sometimes harder for non-native speakers (when is not simply an "s")
the URL is longer
the "s" seems to be a redundant from a programmers' standpoint
is just awkward to consider the path parameter as a sub-resource of the collection as opposed to consider it for what it is: simply an ID of the resource it identifies
you can apply the filtering parameters only where they are needed (endpoint with plural resource name)
you could use the same url for all of them and use the MessageContext to determine what type of action the caller of the web service wanted to perform.
No language was specified but in Java you can do something like this.
WebServiceContext ws_ctx;
MessageContext ctx = ws_ctx.getMessageContext();
String action = (String)ctx.get(MessageContext.HTTP_REQUEST_METHOD);
if(action.equals("GET")
// do something
else if(action.equals("POST")
// do something
That way you can check the type of request that was sent to the web service and perform the appropriate action based upon the request method.