I am building an application with a REST-based API and have come to the point where I am specifying status codes for each requests.
What status code should i send for
200,300, 400, 500 are all very generic. If you want generic, 400 is OK.
422 is used by an increasing number of APIs, and is even used by Rails out of the box.
No matter which status code you pick for your API, someone will disagree. But I prefer 422 because I think of '400 + text status' as too generic. Also, you aren't taking advantage of a JSON-ready parser; in contrast, a 422 with a JSON response is very explicit, and a great deal of error information can be conveyed.
Speaking of JSON response, I tend to standardize on the Rails error response for this case, which is:
{
"errors" :
{
"arg1" : ["error msg 1", "error msg 2", ...]
"arg2" : ["error msg 1", "error msg 2", ...]
}
}
This format is perfect for form validation, which I consider the most complex case to support in terms of 'error reporting richness'. If your error structure is this, it will likely handle all your error reporting needs.
200
Ugh... (309, 400, 403, 409, 415, 422)... a lot of answers trying to guess, argue and standardize what is the best return code for a successful HTTP request but a failed REST call.
It is wrong to mix HTTP status codes and REST status codes.
However, I saw many implementations mixing them, and many developers may not agree with me.
HTTP return codes are related to the HTTP Request
itself. A REST call is done using a Hypertext Transfer Protocol request and it works at a lower level than invoked REST method itself. REST is a concept/approach, and its output is a business/logical result, while HTTP result code is a transport one.
For example, returning "404 Not found" when you call /users/ is confuse, because it may mean:
"403 Forbidden/Access Denied" may mean:
And the list may continue with '500 Server error" (an Apache/Nginx HTTP thrown error or a business constraint error in REST) or other HTTP errors etc...
From the code, it's hard to understand what was the failure reason, a HTTP (transport) failure or a REST (logical) failure.
If the HTTP request physically was performed successfully it should always return 200 code, regardless is the record(s) found or not. Because URI resource is found and was handled by the HTTP server. Yes, it may return an empty set. Is it possible to receive an empty web-page with 200 as HTTP result, right?
Instead of this you may return 200 HTTP code with some options:
Also, some internet providers may intercept your requests and return you a 404 HTTP code. This does not means that your data are not found, but it's something wrong at transport level.
From Wiki:
In July 2004, the UK telecom provider BT Group deployed the Cleanfeed content blocking system, which returns a 404 error to any request for content identified as potentially illegal by the Internet Watch Foundation. Other ISPs return a HTTP 403 "forbidden" error in the same circumstances. The practice of employing fake 404 errors as a means to conceal censorship has also been reported in Thailand and Tunisia. In Tunisia, where censorship was severe before the 2011 revolution, people became aware of the nature of the fake 404 errors and created an imaginary character named "Ammar 404" who represents "the invisible censor".
Why not simply answer with something like this?
{
"result": false,
"error": {"code": 102, "message": "Validation failed: Wrong NAME."}
}
Google always returns 200 as status code in their Geocoding API, even if the request logically fails: https://developers.google.com/maps/documentation/geocoding/intro#StatusCodes
Facebook always return 200 for successful HTTP requests, even if REST request fails: https://developers.facebook.com/docs/graph-api/using-graph-api/error-handling
It's simple, HTTP status codes are for HTTP requests. REST API is Your, define Your status codes.
I recommend status code 422, "Unprocessable Entity".
11.2. 422 Unprocessable Entity
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. For example, this error condition may occur if an XML request body contains well-formed (i.e., syntactically correct), but semantically erroneous, XML instructions.
Ember-Data's ActiveRecord adapter expects 422 UNPROCESSABLE ENTITY
to be returned from server. So, if you're client is written in Ember.js you should use 422. Only then DS.Errors will be populated with returned errors. You can of course change 422 to any other code in your adapter.
Status Code 304 Not Modified would also make an acceptable response to a duplicate request. This is similar to processing a header of If-None-Match
using an entity tag.
In my opinion, @Piskvor's answer is the more obvious choice to what I perceive is the intent of the original question, but I have an alternative that is also relevant.
If you want to treat a duplicate request as a warning or notification rather than as an error, a response status code of 304
Not Modified and Content-Location
header identifying the existing resource would be just as valid. When the intent is merely to ensure that a resource exists, a duplicate request would not be an error but a confirmation. The request is not wrong, but is simply redundant, and the client can refer to the existing resource.
In other words, the request is good, but since the resource already exists, the server does not need to perform any further processing.
A duplicate in the database should be a 409 CONFLICT
.
I recommend using 422 UNPROCESSABLE ENTITY
for validation errors.
I give a longer explanation of 4xx codes here.