Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

REST - put IDs in body or not?

Tags:

rest

People also ask

Should REST API return ID?

It doesn't matter if the resource returns an ID field. It is up to the client to keep a map of where it was obtained from. In a + b, the server would create a new resource.

Should Put request have ID in URL?

As far as having an ID in the url is concerned, I think you should always have it as it is a standard practice to identify a resource. Even the Stripe API works that way. You can use a PATCH request to update a resource on the server with ID to identify it but do not update the actual ID.

Does Put need ID?

No. PUT means "create or update", and should come with an explicit ID. POST is suitable for creating something new.

Can we use Put instead of POST in rest?

If you want to use POST, then you would do that to a list of questions. If you want to use PUT, then you would do that to a particular question. Great, both can be used, so which one should I use in my RESTful design: You do not need to support both PUT and POST.


There is nothing wrong in having different read/write models: the client can write one resource representation where after the server can return another representation with added/calculated elements in it (or even a completely different representation - there is nothing in any spec against that, the only requirement is that PUT should create or replace the resource).

So I would go for the asymmetric solution in (2) and avoid the "nasty duplication check" on the server side when writing:

PUT /person/UUID {"name": "Jimmy"}

GET /person/UUID returns {"id": <UUID>, "name": "Jimmy"}

If it is a public API you should be conservative when you reply, but accept liberally.

By that I mean, you should support both 1 and 2. I agree that 3 doesn't make sense.

The way to support both 1 and 2 is to get the id from the url if none is supplied in the request body, and if it is in the request body, then validate that it matches the id in the url. If the two do not match, then return a 400 Bad Request response.

When returning a person resource be conservative and always include the id in the json, even though it is optional in the put.


One solution to this issue involves the somewhat confusing concept of "Hypertext As The Engine Of Application State," or "HATEOAS." This means that a REST response contains the available resources or actions to be performed as hyperlinks. Using this method, which was part of the original conception of REST, the unique identifiers/IDs of resources are themselves hyperlinks. So, for example, you could have something like:

GET /person/<UUID> {"person": {"location": "/person/<UUID>", "data": { "name": "Jimmy"}}}

Then, if you want to update that resource, you could do (pseudocode):

updatedPerson = person.data
updatedPerson.name = "Timmy"
PUT(URI: response.resource, data: updatedPerson)

One advantage of this is that the client doesn't have to have any idea about the server's internal representation of User IDs. The IDs could change, and even the URLs themselves could change, as long as the client has a way to discover them. For example, when getting a collection of people, you could return a response like this:

GET /people
{ "people": [
    "/person/1",
    "/person/2"
  ]
}

(You could, of course, also return the full person object for each person, depending on the needs of the application).

With this method, you think of your objects more in terms of resources and locations, and less in terms of ID. The internal representation of unique identifier is thus decoupled from your client logic. This was the original impetus behind REST: to create client-server architectures that are more loosely coupled than the RPC systems that existed before, by using the features of HTTP. For more information on HATEOAS, look at the Wikipedia article as well as this short article.


In an insert you do not need to add the id in the URL. This way if you send an ID in a PUT you may interpreted as an UPDATE to change the primary key.

  1. INSERT:

    PUT /persons/ 
      {"id": 1, "name": "Jimmy"}
    HTTP/1.1 201 Created     
      {"id": 1, "name": "Jimmy", "other_field"="filled_by_server"}
    
    GET /persons/1
    
    HTTP/1.1 200 OK
      {"id": 1, "name": "Jimmy", "other_field"="filled_by_server"}  
    
  2. UPDATE

    PUT /persons/1 
         {"id": "2", "name": "Jimmy Jr"} - 
    HTTP/1.1 200 OK
         {"id": "2", "name": "Jimmy Jr", "other_field"="filled_by_server"}
    
    GET /persons/2 
    
    HTTP/1.1 200 OK
         {"id": "2", "name": "Jimmy Jr", "other_field"="updated_by_server"}
    

The JSON API uses this standard and solves some issues returning the inserted or updated object with a link to the new object. Some updates or inserts may include some business logic that will change additional fields

You will also see that you can avoid the get after the insert and update.


Just FYI, the answers here are wrong.

See:

https://restfulapi.net/rest-api-design-tutorial-with-example/

https://restfulapi.net/rest-put-vs-post/

https://restfulapi.net/http-methods/#patch

PUT

Use PUT APIs primarily to update existing resource (if the resource does not exist, then API may decide to create a new resource or not). If a new resource has been created by the PUT API, the origin server MUST inform the user agent via the HTTP response code 201 (Created) response and if an existing resource is modified, either the 200 (OK) or 204 (No Content) response codes SHOULD be sent to indicate successful completion of the request.

If the request passes through a cache and the Request-URI identifies one or more currently cached entities, those entries SHOULD be treated as stale. Responses to this method are not cacheable.

Use PUT when you want to modify a singular resource which is already a part of resources collection. PUT replaces the resource in its entirety. Use PATCH if request updates part of the resource.

PATCH

HTTP PATCH requests are to make partial update on a resource. If you see PUT requests also modify a resource entity so to make more clear – PATCH method is the correct choice for partially updating an existing resource and PUT should only be used if you’re replacing a resource in its entirety.

So you should use it in this way:

POST    /device-management/devices      : Create a new device
PUT     /device-management/devices/{id} : Update the device information identified by "id"
PATCH   /device-management/devices/{id} : Partial-update the device information identified by "id"

RESTful practices indicate that it shouldn't matter what you PUT at /{id}--the content of the record should be updated to the one provided by the payload--but GET /{id} should still link to the same resource.

In other words, PUT /3 may update to payload id to 4, but GET /3 should still link to the same payload (and return the one with id set to 4).

If you are deciding that your API requires the same identifier in the URI and the payload, it's your job to make sure it matches, but definitely use PATCH instead of PUT if you are excluding the id in the payload that should be there in its entirety. This is where the accepted answer got it wrong. PUT must replace the entire resource, where-as patch may be partial.


While it's Ok to have different representations for different operations, a general recommendation for PUT is to contain the WHOLE payload. That means that id should be there as well. Otherwise, you should use PATCH.

Having said that, I think PUT should mostly be utilised for updates and the id should always be passed in the URL as well. As a result of that, using PUT to update the resource identifier is a bad idea. It leaves us in an undesirable situation when id in the URL can be different from the id in the body.

So, how do we resolve such a conflict? We basically have 2 options:

  • throw a 4XX exception
  • add a Warning(X-API-Warn etc) header.

That's as close as I can get to answering this question because the topic in general is a matter of opinion.