I want to design my rest endpoint with the appropriate method for the following scenario.
There is a group. Each group has a status. The group can be activated or inactivated by the admin.
Should i design my end point as
PUT /groups/api/v1/groups/{group id}/status/activate
OR
PATCH /groups/api/v1/groups/{group id}
with request body like
{action:activate|deactivate}
The R in REST stands for resource
(Which isn't true, because it stands for Representational, but it's a good trick to remember the importance of Resources in REST).
About
PUT /groups/api/v1/groups/{group id}/status/activate
: you are not updating an "activate". An "activate" is not a thing, it's a verb. Verbs are never good resources. A rule of thumb: if the action, a verb, is in the URL, it probably is not RESTful.What are you doing instead? Either you are "adding", "removing" or "updating" an activation on a Group, or if you prefer: manipulating a "status"-resource on a Group. Personally, I'd use "activations" because they are less ambiguous than the concept "status": creating a status is ambiguous, creating an activation is not.
POST /groups/{group id}/activation
Creates (or requests the creation of) an activation.PATCH /groups/{group id}/activation
Updates some details of an existing activation. Since a group has only one activation, we know what activation-resource we are referring to.PUT /groups/{group id}/activation
Inserts-or-replaces the old activation. Since a group has only one activation, we know what activation-resource we are referring to.DELETE /groups/{group id}/activation
Will cancel, or remove the activation.This pattern is useful when the "activation" of a Group has side-effects, such as payments being made, mails being sent and so on. Only POST and PATCH may have such side-effects. When e.g. a deletion of an activation needs to, say, notify users over mail, DELETE is not the right choice; in that case you probably want to create a deactivation resource:
POST /groups/{group_id}/deactivation
.It is a good idea to follow these guidelines, because this standard contract makes it very clear for your clients, and all the proxies and layers between the client and you, when it is safe to retry, and when not. Let's say the client is somewhere with flaky wifi, and its user clicks on "deactive", which triggers a
DELETE
: If that fails, the client can simply retry, untill it gets a 404, 200 or anything else it can handle. But if it triggers aPOST to deactivation
it knows not to retry: the POST implies this.Any client now has a contract, which, when followed, will protect against sending out 42 emails "your group has been deactivated", simply because its HTTP-library kept retrying the call to the backend.
Updating a single attribute: use PATCH
PATCH /groups/{group id}
In case you wish to update an attribute. E.g. the "status" could be an attribute on Groups that can be set. An attribute such as "status" is often a good candidate to limit to a whitelist of values. Examples use some undefined JSON-scheme:
Replacing the resource, without side-effects use PUT.
PUT /groups/{group id}
In case you wish to replace an entire Group. This does not necessarily mean that the server actually creates a new group and throws the old one out, e.g. the ids might remain the same. But for the clients, this is what PUT can mean: the client should assume he gets an entirely new item, based on the server's response.
The client should, in case of a
PUT
request, always send the entire resource, having all the data that is needed to create a new item: usually the same data as a POST-create would require.A very important requirement is that
PUT
is idempotent: if you require side-effects when updating a Group (or changing an activation), you should usePATCH
. So, when the update results in e.g. sending out a mail, don't usePUT
.I would recommend using PATCH, because your resource 'group' has many properties but in this case, you are updating only the activation field(partial modification)
according to the RFC5789 (https://tools.ietf.org/html/rfc5789)
Also, in more details,
The response code for PATCH is
also refer thttp://restcookbook.com/HTTP%20Methods/patch/
I would generally prefer something a bit simpler, like
activate
/deactivate
sub-resource (linked by aLink
header withrel=service
).or
For the consumer, this interface is dead-simple, and it follows REST principles without bogging you down in conceptualizing "activations" as individual resources.
The
PATCH
method is the correct choice here as you're updating an existing resource - the group ID.PUT
should only be used if you're replacing a resource in it's entirety.Further information on partial resource modification is available in RFC 5789. Specifically, the
PUT
method is described as follows:Since you want to design an API using the REST architectural style you need to think about your use cases to decide which concepts are important enough to expose as resources. Should you decide to expose the status of a group as a sub-resource you could give it the following URI and implement support for both GET and PUT methods:
The downside of this approach over PATCH for modification is that you will not be able to make changes to more than one property of a group atomically and transactionally. If transactional changes are important then use PATCH.
If you do decide to expose the status as a sub-resource of a group it should be a link in the representation of the group. For example if the agent gets group 123 and accepts XML the response body could contain:
A hyperlink is needed to fulfill the hypermedia as the engine of application state condition of the REST architectural style.