400 vs 422 response to POST of data

David S picture David S · Apr 21, 2013 · Viewed 320.3k times · Source

I'm trying to figure out what the correct status code to return on different scenarios with a "REST-like" API that I'm working on. Let's say I have a end point that allows POST'ing purchases in JSON format. It looks like this:

{
    "account_number": 45645511,
    "upc": "00490000486",
    "price": 1.00,
    "tax": 0.08
}

What should I return if the client sends me "sales_tax" (instead of the expected "tax"). Currently, I'm returning a 400. But, I've started questioning myself on this. Should I really be returning a 422? I mean, it's JSON (which is supported) and it's valid JSON, it's just doesn't contain all of the required fields.

Answer

Kristian Glass picture Kristian Glass · Nov 26, 2013

400 Bad Request would now seem to be the best HTTP/1.1 status code for your use case.

At the time of your question (and my original answer), RFC 7231 was not a thing; at which point I objected to 400 Bad Request because RFC 2616 said (with emphasis mine):

The request could not be understood by the server due to malformed syntax.

and the request you describe is syntactically valid JSON encased in syntactically valid HTTP, and thus the server has no issues with the syntax of the request.

However as pointed out by Lee Saferite in the comments, RFC 7231, which obsoletes RFC 2616, does not include that restriction:

The 400 (Bad Request) status code indicates that the server cannot or will not process the request due to something that is perceived to be a client error (e.g., malformed request syntax, invalid request message framing, or deceptive request routing).


However, prior to that re-wording (or if you want to quibble about RFC 7231 only being a proposed standard right now), 422 Unprocessable Entity does not seem an incorrect HTTP status code for your use case, because as the introduction to RFC 4918 says:

While the status codes provided by HTTP/1.1 are sufficient to describe most error conditions encountered by WebDAV methods, there are some errors that do not fall neatly into the existing categories. This specification defines extra status codes developed for WebDAV methods (Section 11)

And the description of 422 says:

The 422 (Unprocessable Entity) status code means the server understands the content type of the request entity (hence a 415(Unsupported Media Type) status code is inappropriate), and the syntax of the request entity is correct (thus a 400 (Bad Request) status code is inappropriate) but was unable to process the contained instructions.

(Note the reference to syntax; I suspect 7231 partly obsoletes 4918 too)

This sounds exactly like your situation, but just in case there was any doubt, it goes on to say:

For example, this error condition may occur if an XML request body contains well-formed (i.e., syntactically correct), but semantically erroneous, XML instructions.

(Replace "XML" with "JSON" and I think we can agree that's your situation)

Now, some will object that RFC 4918 is about "HTTP Extensions for Web Distributed Authoring and Versioning (WebDAV)" and that you (presumably) are doing nothing involving WebDAV so shouldn't use things from it.

Given the choice between using an error code in the original standard that explicitly doesn't cover the situation, and one from an extension that describes the situation exactly, I would choose the latter.

Furthermore, RFC 4918 Section 21.4 refers to the IANA Hypertext Transfer Protocol (HTTP) Status Code Registry, where 422 can be found.

I propose that it is totally reasonable for an HTTP client or server to use any status code from that registry, so long as they do so correctly.


But as of HTTP/1.1, RFC 7231 has traction, so just use 400 Bad Request!