12

I have a resource (project) which can be activated and deactivated.
What's the most RESTful URL endpoint for this purpose?

Right now I'm thinking about /projects/:id/activate and /projects/:id/deactivate, but I don't think that's very RESTful.
In addition, I'm not certain what HTTP method to use.

Can you provide some pointers?
Thanks!

Neta
  • 871
  • 5
  • 14
  • 30
  • GitHub enables the API consumers to do this by a PUT request, documentation may be seen at [here](https://developer.github.com/v3/activity/starring/#star-a-repository). – ozanmuyes Dec 25 '18 at 07:44

3 Answers3

13

The most conventional way to do this is via POST to /projects/:id, with parameters indicating whether you want to activate or deactivate or something else (always leave room for something else).

note that RESTful URLs should refer to things (like projects), not actions. Then the common methods have clear meanings:

  • PUT: create or replace the thing
  • PATCH: set properties of the thing
  • POST: perform an operation on the thing
  • GET: retrieve the thing
  • DELETE: delete the thing
Matt Timmermans
  • 53,709
  • 3
  • 46
  • 87
12

Your can send your requests just to projects/{id} and use PATCH (as you're updating existing object) verb, e.g.

PATCH /projects/123

[
    { "op": "activate|deactivate", ... }
]

Read more: REST API - PUT vs PATCH with real life examples

Community
  • 1
  • 1
Kristian Vitozev
  • 5,791
  • 6
  • 36
  • 56
  • 1
    I think I'll use `PATCH`, just because I'm already using `POST` for this resource and I don't want to have a huge route (using Node.js & Express). Thanks! – Neta Jan 14 '16 at 13:42
  • A small follow up question: what HTTP code to return if the project isn't ready to be activated? – Neta Jan 14 '16 at 13:56
  • 1
    `202 - Accepted`, which means "request has been accepted for processing, but processing is not completed yet" – Kristian Vitozev Jan 14 '16 at 13:57
  • That's good, but if I want to express to the client: "The project isn't ready because you haven't updated it yet"? – Neta Jan 14 '16 at 13:59
7

I know I am a bit late but maybe this might be useful for others.

You can create a noun from your operation and use it as sub-resource: activate -> activation

Now you can use POST and DELETE on this sub-resource.

For example:

POST /projects/:id/activation       <-- activate project
DELETE /projects/:id/activation     <-- deleting the activation = deactivate

This pattern can work quite well for operations that toggle between on/off state of something.

micha
  • 47,774
  • 16
  • 73
  • 80
  • 1
    We have also successfully used this in multiple APIs. – Morten Haraldsen Feb 14 '21 at 08:53
  • @MortenHaraldsen how do you manage PUT / POST without body ? (I think PUT is more appropriate as we are modifying state and its always will be idempotent ) – Jigar Shah Aug 10 '21 at 22:15
  • @JigarShah - I do not understand the issue. There is no _requirement_ for a body when using any HTTP verb. The URL could carry all the needed information if need be. – Morten Haraldsen Aug 11 '21 at 06:20
  • 1
    @MortenHaraldsen https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PUT ...It says BODY is required. Its not that empty wont work. But its issue with tooling for example, OpenAPI spec expects body in PUT. – Jigar Shah Aug 11 '21 at 08:13
  • A content-length of 0 is allowed, which means empty body. I have not had any tooling issues with this. Consider an API that is touching (creating) a file with PUT. The file could be empty. – Morten Haraldsen Aug 11 '21 at 12:39
  • @JigarShah Also, OpenAPI 3.0 does not require a body: "Request bodies are optional by default. To mark the body as required, use required: true." - https://swagger.io/docs/specification/describing-request-body/ – Morten Haraldsen Aug 11 '21 at 13:19