HTTP Status: 201 Created vs. 202 Accepted
Continuing my series on HTTP status codes, I’d like to talk today about the use of the 201 Created and 202 Accepted codes.
I should make a point of clarification first, though. When I’m discussing the use of status codes, I have in mind Web services applications with perhaps rich clients that interface with them and not necessarily standard, browser-based Web apps. Browsers should be able to handle these status codes, but they are not necessarily the richest clients to use as an interface to your Web service, so they may not be able to handle the responses as intended.
Moving along…
Recently, while designing an application that uses the Atom Publishing Protocol, I found myself using the 201 Created status code as a response to successful POST requests for creation of new content in the service. In the body of the response, I would return a full representation of the newly created resource, and I would include a Location header with a URI that points to the location of the newly created resource. (Instead of returning a full representation of the created resource, you may return a list of URIs pointing to locations for the resource(s) created.)
In general, this is a good practice, though most of us find ourselves returning the standard 200 OK code. (Using 200 OK is still acceptable, though I’ll have more to say on that in a future post.) However, I ran into a problem when I realized that the resource itself does not yet exist, nor might it ever exist; it all depends on our business rules, which require various processes to occur before we “publish” the content. So, the 201 Created response is misleading to the client because nothing has been created yet, and the representation of the resource is inaccurate since the resource does not yet exist. The resource is really in a pending state.
Enter the 202 Accepted status code.
I decided to use the 202 Accepted status code as the more proper response to these types of requests. 202 Accepted means that the service successfully accepted the request and there are, as of yet, no problems with it (i.e., no immediate data validation problems), but it can’t create the resource until it does further processing. This response does not promise that the resource will be created, though. So, it’s perfect for pending requests, since a pending request could be rejected while it’s being processed.
The HTTP spec says that a 202 Accepted response SHOULD include an indication of the request’s current status. To this end, for our service, I have it return an Atom Entry Document with content that describes what’s going on, i.e., the request succeeded but requires further processing before it can be published. It may also be beneficial to clients to include a Location header with a URI that can be used later to check on the status of the request.
When the client checks the status URI later, if the item is still pending then the status URI might return a 200 OK response with an entity body describing this. If the resource has been created, then perhaps the status URI would return a 201 Created response with a Location header pointing to the location of the new resource. If the item was not created for some reason, then perhaps the status URI would return a 410 Gone response. In this case, you should include an entity body explaining why the resource is gone, i.e., “We were unable to create this resource due to processing errors.” A 404 Not Found response would also be acceptable, but the 410 Gone response implies permanence; the requested resource is gone for good.
The status URI described here is a temporary URI used only for checking on the status of the request. It would eventually be unavailable after the resource has been created or rejected, but the time frame for this is up to you.
7 Comments
Great post. I just developed a ReSTful API for creating and viewing log buckets and log records. When a log record is posted to a particular bucket, it's not yet written to the database. It's first written to a que (which happens to be a text file) where a daemon will run and process each record. Since the log isn't actually created at that moment, i return a 202 accepted. This implies exactly what you said above: it has not been created because there is some further processing to perform, but it was successfully received by the server.
Hi Ben, great couple of posts so far. I know you might get to the answer to this question eventually, but it bears asking now. You mention "using the 201 Created status code as a response to successful POST requests for creation of new content in the service" in here. What's your perspective on the architecture of services when it comes to these verbs? Some folks say to map the HTTP verbs POST, GET, PUT and DELETE explicitly to each letter in CRUD. Others say to be more lenient and in a sense "overload" the POST verb, letting it sometimes be create, sometimes be update, based on the context of the URI. Plus, I know there are issues where some browsers don't support all of those verbs, which would affect Ajax style apps trying to use XmlHttpRequest. So what say ye?
Glen, I will eventually get around to talking specifically about the verbs themselves, but as a short answer, in the AtomPub service I'm building, we equate the verbs directly to CRUD, as the AtomPub spec recommends:
[code]
POST --> Create
GET --> Read
PUT --> Update
DELETE --> Delete
[/code]
However, I can see how you might PUT a new representation of a "collection" that the server would then interpret to add or remove new items to the collection, creating new resources, removing them, or doing both to different resources in the same action. Likewise, you could use POST directly on a resource to do a partial update, whereas a PUT essentially means "replace" and replaces the representation of a resource with a new one. I treat PUT loosely, though, because I don't want people to be able to change certain values in the Atom Entry representation (i.e. atom:id, atom:published, etc.).
As you can probably tell, I have a lot to say about this, so I'll make a full post on it sometime in the future. :-)
Hi,
Since this is a 2years post, I am not sure I will get an answer but here goes...
From reading the articles, my understanding is that the various HTTP status codes can be interchanged, with no affect to the HTTP client code and the only real issue it to respond with the status code that is conceptually closer to the task at hand. Am I correct?
For example in web services, if the service returned a 200 OK with empty content in the SOAP body i.e. inside the envelope or 200 OK with no body at all or 202 Accepted, does it make a difference to the HTTP client of the web service client? Could the web service change the response code to any of the above 3, in any time with no problem? Thanks
What happens when a web browser receives one of these status codes? When it receives 201 with a Location header, does it redirect automatically?
Four years late to the party ..
The only thing that strikes me as odd is using the 200 OK when the resource has not been created yet. I am tempted to keep using the 202 ACCEPTED until the resource has been created and is available. I think the ambiguity is if the reply is talking about the resource or the request for information about the resource. But I don't feel solid ground under me.
4 years and 4 months late to the party but here goes...
I've also been working on some RESTful webservices and sometimes I find it not so easy to decide on which HTTP code to return. E.g. I have a resource being create and if all goes well I return 201, CREATED. Ok, so what should I return if it was not created due to some limit being reached? I.e., not due to a bad request by the client (400) or unauthorized, also not due to a server error (500) but due to some precondition on the RESOURCE (not the server, which maybe could be 412).
In other words, what's the opposite of 201 CREATED? Resource is NOT CREATED.
The closest is possibly the GONE you mentioned (410) but it doesn't feel exactly right because the resource was never created in the first place.
Any thoughts?
Cheers