126

I'm designing a RESTful web service using WebApi and was wondering what HTTP responses and response bodies to return when updating / creating objects.

For example I can use the POST method to send some JSON to the web service and then create an object. Is it best practice to then set the HTTP status to created (201) or ok (200) and simply return a message such as "New Employee added", or return the object that was sent originally?

The same goes for the PUT method. Which HTTP status is best to use and do I need to return the object that was created or just a message? Considering the fact that the user knows what object they are trying to create / update anyway.

Any thoughts?

Example:

Add new Employee:

POST /api/employee HTTP/1.1
Host: localhost:8000
Content-Type: application/json

{ "Employee": { "Name" : "Joe Bloggs", "Department" : "Finance" } }

Update existing employee:

PUT /api/employee HTTP/1.1
Host: localhost:8000
Content-Type: application/json

{ "Employee": { "Id" : 1 "Name" : "Joe Bloggs", "Department" : "IT" } }

Responses:

Response with object created / updated

HTTP/1.1 201 Created
Content-Length: 39
Content-Type: application/json; charset=utf-8
Date: Mon, 28 Mar 2016 14:32:39 GMT

{ "Employee": { "Id" : 1 "Name" : "Joe Bloggs", "Department" : "IT" } }

Response with just message:

HTTP/1.1 200 OK
Content-Length: 39
Content-Type: application/json; charset=utf-8
Date: Mon, 28 Mar 2016 14:32:39 GMT

{ "Message": "Employee updated" }

Response with just status code:

HTTP/1.1 204 No Content
Content-Length: 39
Date: Mon, 28 Mar 2016 14:32:39 GMT
mqqx
  • 5
  • 2
iswinky
  • 1,363
  • 2
  • 9
  • 8

8 Answers8

85

As with most things, it depends. Your tradeoff is ease of use versus network size. It can be very helpful for clients to see the created resource. It may include fields populated by the server, such as last-creation-time. Since you appear to be including the id instead of using hateoas, clients will probably want to see the id for the resource they just POSTed.

If you don't include the created resource, please do not create an arbitrary message. The 2xx and Location fields are enough information for clients to be confident that their request was properly handled.

Eric Stein
  • 3,602
29

I would always send back the payload in case of both POST and PUT.

In case of POST you might create the entity with an internal ID or a UUID. Hence it makes sense to send back the payload.

Similarly in case of PUT, you might ignore some fields of the user (immutable values, say), or in case of a PATCH, the data might have been changed by other users as well.

Sending the data back as it was persisted is always a good idea and definitely doesn't harm. If the caller has no need for this returned data, then he/she won't process it but will just consume the statusCode. Else they can use this data as something to update the UI with.

It's only in case of a DELETE that I wouldn't send back the payload and would do either a 200 with a response content, or a 204 with no response content.

Edit: Thanks to some comments from below, I am rewording my answer. I still stand by the way I design my APIs and send back responses but I think it makes sense to qualify some of my design thoughts.

a) When I say send back the payload, I actually meant to say send back the data of the resource, not the same payload that came in the request. Ex: if you send a create payload, I may in the backend create other entities such as UUID and (maybe) timestamps and some (graph) connections even. I would send all this back in the response (not just the request payload as is - which is pointless).

b) I wouldn't send back responses in case the payload is very large. I've discussed this in the comments, but what I would like to caveat is that I would try my best to design my APIs or my resources such that it doesn't have to have very large payloads. I would try to break down the resources into smaller and manageable entities such that each resource is defined by 15-20 JSON attributes and not larger.

In the case that the object is very large or the parent object is being updated, then I would send back the nested structures as hrefs.

Bottom line is I would definitely try to send back the data that makes sense for the consumer / UI to process immediately and be done with an atomic API action rather than have to go and fetch 2-5 more API just to update the UI post the creation / update of the data.

Server to server APIs might think differently about this. I am focusing on APIs that drive a user experience.

devuxer
  • 676
  • 6
  • 13
ksprashu
  • 411
26

Personally, I always return only 200 OK.

To quote your question

Considering the fact that the user knows what object they are trying to create / update anyway.

Why add extra bandwidth (which might have to be paid for) to tell the client what it already knows?

Mawg
  • 4,298
26

Referencing to the link RFC standards, you should return 201(created) status on successfully storing the request resource using Post. In most of the applications the id of the resource is generated by the server itself, so it is good practice to return the id of the created resource. Returning the whole object is the overhead for Post request. Ideal practice is to return the URL location of the newly created resource.

For example you can refer to the following example that saves the Employee Object into the database and returns the URL of the newly created resource object as a response.

@RequestMapping(path = "/employees", method = RequestMethod.POST)
public ResponseEntity<Object> saveEmployee(@RequestBody Employee employee) {
    int id = employeeService.saveEmployee(employee);
    URI uri = ServletUriComponentsBuilder.fromCurrentRequest().path("/{id}").buildAndExpand(id).toUri();
    return ResponseEntity.created(uri).build();
}

This rest endpoint will return the response as:

Status 201 - CREATED

Header Location →http://localhost:8080/employees/1

mqqx
  • 5
  • 2
4

I would make a payload in the return body conditional to a HTTP parameter.

More often than not it is best to return some sort of content back to the API consumer to avoid unnecessary round trips (one of the reasons why GraphQL exists.)

As a matter of fact, as our applications become more data-intensive and distributed, I try observe this guideline:

My Guideline:

Any time there's a use case that demands a GET immediately after a POST or PUT, that is a case where it might be best to simply return something in the POST/PUT response.

How this is done, and what type of content to return back out of a PUT or POST, that's application specific. Now, it would be interesting if the application could parameterize the type of "content" in the response body (do we want just the location of the new object, or some of the fields, or the entire object, etc.)

An application could define a set of parameters a POST/PUT can receive to control the type of of "content" to return in the response body. Or it could encode some sort of GraphQL query as a parameter (I can see this being useful but also become a maintenance nightmare.)

Either way, it seems to me that:

  1. It is OK (and most likely desirable) to return something in a POST/PUT response body.
  2. How this is done is application-specific and almost impossible to generalize.
  3. You do not want to return large-size "context" by default (traffic-noise that defeats the whole reason of moving away from POST-followed-by-GETs.)

So, 1) do it, but 2) keep it simple.

Another option I've seen is people creating alternative end points (say, /customers for POST/PUT that return nothing in the body and /customer_with_details for POST/PUT to /customers, but that return something in the response body.)

I would avoid this approach, though. What happens when you legitimately need to return different type of content? One endpoint per content type? Not scalable or maintainable.

luis.espinal
  • 2,620
0

Allow the POST endpoint to receive a config setting in the payload returnCreatedResource and accept a true/false value of your preference. If true return the created resource, else don't.

Then the client can decide based on their scenario. Most of the time it's the client's application which is the determining factor of needing the resource or not.

You can't possibly know a client's requirements, no matter how your API or App is configured or what scenario you think may be a time to return the resource or not. Yes ok there will be some scenarios where for some reason created resource must be or must not be returned, etc. But for most APIs, the client being able to choose is by far the best option.

James
  • 283
0

It's easy: when you have created an object (on the server), simply return a "handle" (or "id") to the object that you have just created. The client can refer to this "handle" to request whatever future information is needed.

And of course, since the possibility exists that this "handle" will never again be referred to, provide some sort of "drop-dead timestamp" and a "garbage collection sweeper."

0

Just returning the object is pointless. The caller has the object already. What you should do is return a status 200 or 201 for “created”, and any information that you have created new on the server. Typically that would be some Id. It could also be any information that wasn’t given and was filled with default values, or data that was corrected (or were limitations of the server were applied, for example if a database doesn’t support full Unicode and Mrs. Zoë was “corrected” to “Zoe”.

gnasher729
  • 49,096