I am designing a Create/Read/Update/Delete public web API endpoint, using RESTful patterns over HTTP with JSON payloads, and am wondering about a design issue that must be extremely common, yet I'm finding a hard time finding guidance for.
Let's focus only on the "Read" and "Update" part of the API. I am a bit confused about the current "proper" REST best practices when it comes to handling IDs. Here's what I mean:
"Reading" employees over HTTP GET returns one or more "widget" JSON object (for example, I have a way to retrieve all widgets that meet a certain criteria). Each widget object has an ID field which is a GUID.
I see several design options for the "Update widget" endpoint:
- HTTP PUT to /api/widgets/{widget-id} of the entire widget object. The API will fail if the "ID" field in the object is present. (I don't like this approach because data from the "Read" endpoint cannot be round-tripped to the "Update" endpoint without modification)
- HTTP PUT to /api/widgets/{widget-id} of the entire widget object. The API will ignore the "ID" field in the object, if present. (I think it's better than the above, but the ID supplied can be incorrect, and I think it's wrong to silently ignore bad data)
- HTTP PUT to /api/widgets/{widget-id} of the entire widget object. The API will verify that the ID field in the object must match the ID in the URI, and will fail otherwise. (I think this is even better, but data is still duplicated between the URI and message body)
- HTTP PUT to /api/widgets/{widget-id} of the entire widget object. The API will verify that the ID field in the object must be either absent or must match the ID in the URI, and will fail otherwise. (This is the approach I'm leaning towards)
- HTTP PUT to /api/widgets of the entire widget object, including the ID field - i.e. ID of the object to update will come from the message body instead of the URI.
- Same as #5 but with HTTP POST - perhaps with "Update" semantics if the ID is specified, and "Create" semantics if it isn't.
I can see various tradeoffs here. Option 6 seems particularly elegant to me, but not particularly "RESTful" and may be an unfamiliar pattern to the API's users. Most of the API design guideline documents I've seen seem to recommend the "PUT to /api/widgets/{widget-id}" approach but are silent on the #1/2/3/4 distinction above.
So what is the "RESTfully correct"/best-practies way to do this? (Something that would be most familiar and least confusing to developers using my public API endpoint). And are there any other design options (or design considerations) I'm not thinking of here?