I'll try to make this as simple as possible, it may be sort of dumb question.
I'm rewriting an 7 years old web application (help desk software). It is required to make it a REST API to be consumed by different clients web browser and mobile app. Also required to keep the business logic as close as possible to the original which for now have been working well.
The current struggle about REST:
What I need is to update the a resource lets say /tickets/47321
If the status_id
of the this resource is changed a record of this change need to be saved, both in the same DB transaction because it need to be all-or-nothing. this is how the original application worked and we would like to keep this behavior.
So question is:
Can I PUT
to tickets/47321
the whole resource or partial state representation to update the resource residing in server and create the new record of the history change (if status_id
is different) and return them both back to client as JSON:
{
ticket: {}, // new ticket state
history: {} // the new created record of history change
}
This way the client can update the ticket
and add the history to a list of history changes if there is any being return?
Technically, yes, you can do this. However, it might not be as straightforward as simply returning 2 objects, side by side; looking at the Richardson Maturity Model (Level 1), one would expect to receive the same type of resource after calling (PUT) an api endpoint.
That being said, you could either embed the additional resource (append a history change to a ticket, following the Hypertext Application Language (HAL) proposed draft specification), or better yet (if you're aiming towards REST level 3), provide a link relationship, in conformity with the "Target IRI" defined in Web Linking specification (RFC 5988) from the ticket:
/api:history?ticketId=47321
would return all the history records belonging to that ticket, paged and sorted by created date, for example (and you can just select the latest)/api:history?id=123
you would do some work on the server to ensure this points straight to the latest history record (related to that ticket id)Regarding the partial update, looking at the RFC 6902 (which defines the Patch standard), from the client's perspective the API could be called like
PATCH /ticket/47321
[
{ "op": "replace", "path": "/author", "value": "David"},
{ "op": "replace", "path": "/statusId", "value": "1"}
]
More examples can be found here.