REST API – How to Design for Non-CRUD Operations

api-designrestweb servicesweb-api

I'm trying to convert a set of SOAP-based services to a RESTful API.

I started by identifying resources by analyzing operation names and I got the resource Subscription.

When I need to update the state of the subscription, I cannot simply send a POST request to the server, because I don't have direct access to the resources, but I need to call some RPC-style operations to update their properties. Additionally, only and only if I'm changing the state of the subscription to "active", an additional call to an external service is required.

In these cases, what is the best practice to handle underlying operations?

The solution I came up with is to use query parameters, so that if I need to call activation service, I can use something like:

POST /subscriptions/{subscriptionid}/?activate=true

Considering that I cannot directly update my Subscription object fields, is there any best practice to handle this kind of conversion?

Update 1:

I can put in the body of my POST request some values, for instance
"state":"active"

and check inside my service the proper operations to be triggered.

Best Answer

You need to watch this talk by Jim Webber.

When I need to update the state of the subscription, I cannot simply send a POST request to the server, because I don't have direct access to the resources, but I need to call some RPC-style operations to update their properties. Additionally, only and only if I'm changing the state of the subscription to "active", an additional call to an external service is required.

Think "messaging"; send a message to your domain, describing what you want to have happen. The side effect of the message is that your domain model actually changes its state. The "resource" is the message queue.

POST /subscriptions/{subscriptionid}/?activate=true

The spelling of the resource name doesn't matter to the machines; but people tend to get fussy when the identifiers you use break from the convention that resources are "nouns".

Also, we're talking about a resource that is subordinate to /subscriptions/{subscriptionid} , so convention (see RFC 3986) calls for expressing that relationship with a path segment, rather than using the query part.

So these spellings might be reasonable

POST /subscriptions/{subscriptionid}/messages
POST /subscriptions/{subscriptionid}/activations