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.