I have a question about how I should implement a new action for a resource on my API layer.
I have a Timesheet
which is used by people to let us know how many hours they worked on a job. This timesheet has a status:
- Open (Still in progress)
- Submitted (Will be reviewed by a department)
- Rejected (Rejected by the department, the user has to fix the Timesheet and submit it again)
- Approved (Approved by the department)
- ...some others that would make this entire thing too complicated
Our API CURRENTLY has the option to change the status, which is used by our front-end by the press of a button (Not that it matters, its just to sketch a picture).
The current endpoint is POST (website)/api/timesheets/{id}/submit
where the ID is the id of the timesheet. The API is smart enough to check if the timesheet cán be submitted and to which status it should be changed (there are some more statuses that are not mentioned here).
When it's done, our current API returns the entire timesheet model with the updated status and the SubmittedDate
.
I have been working on creating a v2 of the API and now I am thinking if I should still use a POST
and what I should return from the API call.
Reasons I doubt POST
:
- It does not create a new resource
PATCH
would be a better fit since we are updating an existing resource, but we are not sending a request body to the API.
Reasons I doubt my return value:
- Returning NOTHING (
200 OK
or204 No content
)POST
can (by guidelines) return200 OK
or204 No content
if the resource can not be found with a URI. My resource can so this doesnt make sense?- At the other hand, we are not really following guidelines if I have a
submit
endpoint since the status changes. But I also don't want to let the caller decide what the new status should be since the API decides it itself and also has some follow up actions.
- At the other hand, we are not really following guidelines if I have a
- My front-end would now have to do a call to
GET api/timesheets/{id}
to get new data, which is maybe a bit of a waste?
- Returning the new status and rejected date
- This would mean my API's return value is made specifically for our front-end, and other clients that use my API would not need this specific return value.
- Returning the entire model
- Waste of space since a couple properties need to be used.
- On StackOverflow I found a thread where they mention that using POST and a return value could lead to caching issues. We use a new version of Angular and someone on my team said that even if someone leaves the page and enters it again, the
GET
will always be executed. I can't say if this is 100% true.
Can someone help me decide what HTTP action should be used (with some reasons why) and what should be returned :)?
Thank you very much!
.../submit
is only for the user changing the status from Open, Rejected, etc. to Submitted?(website)/api/timesheets/{id}
without submit. What happens to the resource at that URL will be the responsibility of the HTTP Verb, so if you were to use PUT, it will change the status of the specified resource (or update other properties). What should it return, well it should return whatever the REST guidelines suggest; in some cases returning a 200 ok with a url of the resource is good enough. If you wanted to delete, you would call the same URL but the HTTP verb would be DELETE.Submitted
and you try to submit it again, it will throw an errorPUT /api/timesheets/id
endpoint where we then send the new status (and other properties) by putting them in our request body? First of all, PUT is idempotent and changing the status to submitted when the timesheet is already submitted IS NOT POSSIBLE. This would violate the PUT guidelines. Next, this would mean that the client should know how to change the status of a timesheet. This is not good since then the API and client should know how this works. It's not as easy to go from 1 to 2 to 3, it is role dependent etc..