34

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
  • 2
    Good question, but using the term "best-practice" is sort of taboo on this site meta.programmers.stackexchange.com/questions/2442/… You might just want to re-word the question. meta.programmers.stackexchange.com/questions/6967/… – Snoop Mar 28 '16 at 14:59
  • 3
    As a bit of a follow-up, would it be a good idea to have a flag in the request so that (for example) a mobile application can get the whole object returned when on WiFi, but only the ID when using cellular data? Is there a header that should be used for that to avoid polluting the JSON? – Andrew Piliser Mar 28 '16 at 20:46
  • @AndrewPiliser Interesting idea, although I personally think it's just best to pick one approach and stick to it. Then as your application develops or becomes more popular, optimise it – iswinky Mar 29 '16 at 7:17
  • @AndrewPiliser your idea is very similar to the Postgresql UPDATE/INSERT ... RETURNING variant for SQL. It's extremely handy, especially as it keeps the submission of new data and request for the updated version atomic. – beldaz Jul 10 '18 at 10:40
30

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.

  • +1 The hateoas objective of not letting the client compose the uri's can also be achieved by by allowing the client to fill in server provided URL templates with specific ID's. Yes, the client "composes" but only in a "fill in the blanks" kind of way. While not pure HATEOAS it achieves the objective and makes working with objects that have a (large) number of "action" uri's a bit less bandwidth sensitive, not to mention when you put those objects in a (largish) list. – Marjan Venema Mar 29 '16 at 11:26
  • 3
    +1 on the "please do not create an arbitrary message" advice – HairOfTheDog Jun 13 '17 at 20:12
  • Does the "no arbitrary message" focus on string messages or any return value that is not the created resource? I'm focusing on cases where we return the id of the created resource (but not the resource itself) and was wondering where this fits in. – Flater Sep 4 at 7:40
12

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?

  • 1
    That's what I was thinking, if it's invalid you can return validation messages, but if it's valid and gets created / updated then check the HTTP status code and show the user a message e.g "Hooray" based on that – iswinky Mar 29 '16 at 11:29
  • 3
    See stackoverflow.com/a/827045/290182 regarding 200/204 No Content to avoid confusing jQuery and the like. – beldaz Jul 10 '18 at 10:44
10

@iswinky 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.

  • I can see many situations where sending back the entire payload is a bad idea, when the payload is large. – beldaz Jul 10 '18 at 10:42
  • 2
    @beldaz completely agree. YMMV based on the design of the REST API. I generally avoid very large objects and break it down into a series of sub-resources / PUTs. If the payload is very large there are better ways to do this, and therein you would want to do HATEOAS (like Marjan says above) where you return the reference to the object instead of the object itself. – ksprashu Jul 11 '18 at 11:20
  • @ksprashu: "Hence it makes sense to send back the payload" - I find this is a bad idea, because thus a resource can be obtained in many ways: via GET, as a response of POST, as a response of PUT. It means that client obtains 3 resources with potentially different structure. Where as if you would return only URI (location), without body, then the only way to obtain a resource would be GET. This would make sure that client always obtains consistent responses. – mentallurg Sep 3 at 0:31
  • @mentallurg I realize I may not have worded this right. Thanks for pointing it out. I've edited my answer. Let me know if this makes more sense. – ksprashu Sep 4 at 4:43
  • As long as you implement a service for your home work, it does not really matter. Do it as you like. Save your time. – mentallurg Sep 4 at 20:49
9

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

  • Nice and clean - gonna follow this from now and beyond – Hassan Tareq Aug 23 at 15:56
0

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.

protected by gnat Oct 23 '18 at 9:17

Thank you for your interest in this question. Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).

Would you like to answer one of these unanswered questions instead?

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