REST API Design – Include Resource ID in Payload or Derive from URI?

resourcesrest

Designing an API, we've come up against the question of whether a PUT payload should contain the ID of the resource being updated.

This is what we currently have:

PUT /users/123 Payload: {name: "Adrian"}

Our route code extracts the ID from the URI and continues on with the update.

The first users of our API are questioning why we don't allow ID in the payload:

PUT /users/123 Payload: {id: 123, name: "Adrian"}

The reason we didn't allow it is because the ID is duplicated, in the payload and URI.

Thinking about this some more, we are coupling the resource to the URI.

If the URI doesn't have the ID, the payload will need to be amended:

PUT /no/id/here Payload: {name: "Adrian"} < What user???

Are there any reasons not to?

Best Answer

You are supposed to couple the Uniform Resource Identifier to the resource.

When REST is implemented with HTTP, you use GET to retrieve the current value of the resource and PUT to set a new value. The GET does not have a payload, so the resource has to be identified by the URI. And the PUT is logically done to the same URI and the payload should look exactly as what you want the next GET to return.

You can use POST to different URI, but it would only make less sense as it would be unnecessarily asymmetrical to the GET. POST to common URI could only make sense for creating new resources (POST /users/new, payload: {name: "Adrian"}, response {id: 345, name: "Adrian"}), but that's not idempotent and therefore should be avoided if you are striving for REST¹. Instead you should reserve ID with one call and then use PUT to set the new ID; that is fault-tolerant, because if the first request fails, the ID reservation can time out eventually and the PUT is idempotent. Or use client-generated UUID.


¹ The definition of REST does not say anything about idempotence, so I can't really claim it is not REST if you have non-idempotent operations. That does not change the fact that sticking to idempotent requests makes things more reliable without complicating them and is therefore recommended.

Related Topic