Search code examples
restapirestful-url

Alternatives of using verbs and adjectives in RESTful URL


I want to add actions to my REST API that would move 'resources' between different 'stores'.

For instance, suppose my resources are normally accessed by the following URL:

/resources
/resources/{resourceId}

Now suppose I want to 'deactivate' some resource, i.e. conceptually move it to another sub-folder. The most straightforward way to allow this would be as followed.

  1. 'Deactivate' the resource, i.e. cause it to be unavailable under /resources. Conceptually, it 'moves' the object to the '/resources/deactivated/' subfolder:

    POST /resources/{resourceId}/deactivate   
    

    Or alternatively:

    POST /resources/deactivated/{resourceId}
    
  2. Get all the deactivated objects:

    GET /resources/deactivated      
    
  3. Reverse the 'deactivate' action, i.e. conceptually move the object from the '/resources/deactivated/' subfolder back to the main one ('/resources').

    Either

    POST /resources/{resourceId}/reactivate    
    

    Or

    POST /resources/deactivated/{resourceId}/restore     
    

    This API seems rather intuitive for me. But it seems to violate the 'prefer nouns' rules that I have seen in many best practices-articles on REST API: I use verbs and adjectives instead of nouns!

Note that I might have parameters for all the endpoints, e.g. GET /resources/deactivated?createdBefore=01022017

Are there any better alternatives for my REST API? I.e. more RESTful, but not less intuitive ones?

Good resources that I could find on the topic:


Solution

  • First of all, remember that REST stands for Representational State Transfer.

    It is all about resources and their state. Operations such as activate, deactivate and move are all about replacing the current state of the resource with a new representation and you don't need verbs in the URL to express such operations.


    For example, to replace a status of a resource, you can send a new representation of the resource in the payload of a PUT request:

    PUT /api/resources/[id]/status HTTP/1.1
    Host: example.org
    Content-Type: application/json
    
    { "status" : "active" }
    

    It can be understood as replace the status of the resource identified by [id] with the one sent in the request payload.


    Then you could have the following to get the resources with a particular status:

    GET /api/resources?status=active HTTP/1.1
    Host: example.org
    Accept: application/json
    

    It can be understood as give me a representation of all resources with the status active.


    To move a resource to another folder, for example, you could have:

    PUT /api/resources/[id]/folder HTTP/1.1
    Host: example.org
    Content-Type: application/json
    
    { "target" : "draft" }
    

    It can be understood as replace the folder of the resource identified by [id] with the one sent in the request payload.