3

How would you design a REST interface that triggers a status change of an object, but requires additional properties in that moment? For example, the deliverer of a package needs to change the status of the package from in transport to delivered, but also specify how it was delivered (letterbox or in person).

I see two possibilities:

  • POST /packages/:id/deliver with deliveredTo as request body
  • PATCH /packages/:id with status=delivered&deliveredTo=... as request body

It is generally considered best practice to use the methods POST, PUT or PATCH to update the state of resources in a RESTful API. RPC-style Actions should be avoided.

The problem I see with the second approach is that validation is hard. The initial POST /packages must not accept the deliveredTo field, but the PATCH request that includes status=delivered requires it. This is not only cumbersome to implement (as the frameworks do not usually support it), but also makes for a complicated API.

So is this a case where custom actions are appropriate?

3
  • 3
    I would solve with a seperate Delivery object.
    – Ewan
    Commented Jun 30, 2015 at 13:25
  • Do you mean having a resource packages/:id/delivery that can be created via PUT and retrieved via GET, acting in a 1-to-1 relation?
    – Yogu
    Commented Jun 30, 2015 at 13:32
  • Something along those lines, might be many to one though if you think about failed deliveries/returns/pickup from depot etc
    – Ewan
    Commented Jun 30, 2015 at 15:36

2 Answers 2

1

Would it help you to have more resources?

  • /packages/12345/status
  • /packages/12345/status/latest
  • /packages/12345/status/versions/7
  • /packages/12345/status?at=20150630T1138-0600
  • /packages/12345/history/delivery/status
  • /packages/12345/history/latest/status
  • /paclages/12345/history/20150630/updates/2

Ceci n'est-pas un package. Different use cases can use different identifiers to manipulate "the same" data.

Put another way, it's a uniform resource identifier, not a uniform domain entity identifier. Having many resources that represent a single entity offers you a lot of flexibility.

References

The specification of PUT in RFC 2616 support the notion that a single resource can by represented by more than one URI

A single resource MAY be identified by many different URIs. For example, an article might have a URI for identifying "the current version" which is separate from the URI identifying each particular version. In this case, a PUT request on a general URI might result in several other URIs being defined by the origin server.

This language is substantially changed in RFC 7231

A PUT request applied to the target resource can have side effects on other resources. For example, an article might have a URI for identifying "the current version" (a resource) that is separate from the URIs identifying each particular version (different resources that at one point shared the same state as the current version resource). A successful PUT request on "the current version" URI might therefore create a new version resource in addition to changing the state of the target resource, and might also cause links to be added between the related resources.

Fielding's thesis has this to say

For example, the “authors’ preferred version” of an academic paper is a mapping whose value changes over time, whereas a mapping to “the paper published in the proceedings of conference X” is static. These are two distinct resources, even if they both map to the same value at some point in time. The distinction is necessary so that both resources can be identified and referenced independently.

2
  • That's an interesting and heplful way to put it, thanks!
    – Yogu
    Commented Jan 15, 2016 at 19:23
  • @VoiceOfUnreason "Ceci n'est pas" different resources ;) It's the same resource that can be accessed through different URIs depending on its state. Commented Jan 19, 2016 at 13:05
0

REST affects a single resource, it does not mean you can only update a single property on that resource.

Some RESTful interfaces (eg SMTP) have a single property putting system, where you repeatedly call a custom verb with a single property until your resource is fully populated with all your data. Others send a blob of data in a single packet (XML, query string, form data, doesn't matter which) to update all properties in one go.

I think the distinction of which to use depends on the latency of your communication channel - so calling a REST interface over http is quite slow, so you'd send all properties in a single message.

2
  • 1
    Sorry, I don't quite get how this is related to my question. In my second example, I would set two properties at once, status and deliveredTo. But which solution would you propose?
    – Yogu
    Commented Jun 30, 2015 at 13:34
  • I'm not sure I understand, are you just asking for semantics of your request? Send both properties at once, in the initial POST, the status in the URI and the additional deliveredTo as request body. I'd POST just the package ID and put all properties to set in the body, but I guess your framework is restricting you.
    – gbjbaanb
    Commented Jun 30, 2015 at 14:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.