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.
This example is borrowed from another question about syntax type issues in the body, but my question assumes valid syntax throughout.
Let's say I have an endpoint that allows POST'ing purchases in JSON format. It looks like this:
{
"account_number": 45645511,
"upc": "00490000486",
"price": 1.00,
"tax": 0.08
}
What is the appropriate status code if:
the account number does not exist
the account is closed or the
account identified is not the right kind of account
These are all firmly business layer issues that prevent "processing" from occuring, however, one scenario involves something that in a GET would be a 404.
Note that the account number is not in the URL, so is 404 misleading?
Let's take these one at a time. Each of these codes is a signal to your client that the server is functioning correctly, and that something must be changed in the request before it can be successfully carried out.
HTTP 400
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).
400 typically indicates a syntax error; as a user, I should look at the structure of the request before trying again.
HTTP 404
The server has not found anything matching the Request-URI. No indication is given of whether the condition is temporary or permanent. The 410 (Gone) status code SHOULD be used if the server knows, through some internally configurable mechanism, that an old resource is permanently unavailable and has no forwarding address. This status code is commonly used when the server does not wish to reveal exactly why the request has been refused, or when no other response is applicable.
404 is the standard code used when a web server can't match a url path to anything. As a client, I should look at the URL of the request before trying again.
HTTP 422
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.
422 is generally used for content violations. As a user, I should look at the content of my request before trying again.
Now in your case, account number is an identifying number, but is not included in the URL. A 404 would signal to your user that the URL is wrong, not the payload. Stated another way, suppose your url is:
http://www.myservice.net/endpoint
A 404 would indicate to me that no service exists at /endpoint, instead of no account number. No matter what content I submit, the server will not process my request. The fix I should make then would be to look for an error in the URL, instead of the data payload. So to me a 422 would point me in the right direction, unless you begin to include the account number in the URL.
Ultimately these are design preferences, just make sure you communicate them clearly to your users.
If you consider the accounts to be part of the state of the resource (though indirectly) then you might also consider 409 since that state is in conflict with the semantics of the request.
However, 422 is gaining popularity via Ruby on Rails and Dropwizard where it is used to indicate non-syntactic issues with the body. That growing tendency represents a strong signal to a developer using the API that they need to exclude syntax and focus on the body. Developer time is usually the single largest cost your customers will ever incur, so by directing the attention of their developers you will keep them happy.
So 409 is a possible answer, though rather novel, and 422 is the more conventional approach, although obviously RoR and DropWizard are both rather new so these conventions can be said to be changing fast!
I'd say 422 is adequate in your case, but 400 isn't bad if it's consistent with the rest of your API. It's a common convention to use 400 as an umbrella error code when there's something wrong on the client side, but either the error doesn't fit a particular error code, or you don't want to use too many of them.
A 404 is definitely wrong if there's something wrong with the POST payload.
Case 1 : Account number doesn't exist.
This is a standard case for 404.
Case 2 : Account is closed.
This has do with the logic if you keep the account details when you close it.
If you donot keep the account details when the account is closed, you can give 404.
If you keep the account details after it is closed, you must be marking it (like raising some flag) (or whatever logic you have). In this case, Status code 400 with a proper message of why it is failed and possibly remediation will do.
Case 3 : Account identified is not the right kind of account.
403, as the account is not authorised for completing any purchases makes sense to me. If there is no concept like authorised account, 400 with a explanatory message will do. But I would insist to go with 403 in this case.
Actually, in this case 404 sounds good to me.
Related
What is the appropriate HTTP response code when a client tries to PUT to an entity that is currently read only by nature?
A toy example is a product shipment. Before the shipment is sent, the details (address, products, quantities) can be changed (e.g. with a PUT request). However, as soon as the shipment is sent, any PUT should fail, even if the request format and syntax are correct.
It's possible that the client doesn't know that the shipment has been sent, so it's not a "careless" error on the client side.
400 doesn't seem appropriate, because the input is well formed and the syntax is correct.
405 seems like a good fit. Is this a common response in this case?
403 seems to imply authorization has been revoked, which could be misleading.
422 seems to fit well, but its use seems discouraged if you don't provide WebDAV capabilities (which we don't).
500 makes it sound like someone tripped over a cable, though I hear some developers/frameworks use this status in this case.
Is there a standard practice for this case? What is least likely to cause confusion for the API user (developer) and the end user (person using the UI)?
I would look at 405 Method Not Allowed. It is defined like this:
The 405 (Method Not Allowed) status code indicates that the method
received in the request-line is known by the origin server but not
supported by the target resource. The origin server MUST generate an
Allow header field in a 405 response containing a list of the target
resource's currently supported methods.
Your server understands the request perfectly, but it no longer supports writing. In addition, the requirement to return the client the list of supported methods sounds clean.
As an added bonus, the 405 response is cacheable by default, which could make sense in your case.
Another viable alternative is 409 Conflict:
The 409 (Conflict) status code indicates that the request could not be
completed due to a conflict with the current state of the target
resource.
Arguably the order changed state, in such a way modifying it is no longer possible. Note however that:
This code is used in situations where the user might be
able to resolve the conflict and resubmit the request.
…so I would tend toward the other one.
We have POST API that gives particular user's contact details in response. But as this is confidential data, to access this detail, anyone accessing it needs to put verified mobile number.
The request looks like:
POST /api/userdetails
{
"userid": 123,
"mobile": "+1394839843"
}
What should be status code if "mobile" number is not a verified number in our database?
What should be status code if "mobile" number is not a verified number in our database?
From a very high level: think about what you would expect a plain old web site to do if a user submitted a form with a "not verified number" and do that.
The charts in Michael Kropat's Stop Making It Hard breaks the process down into more specific questions.
Is there a problem with the request? That's clearly a yes, here, so we know immediately that you'll want to use some code from the 4xx class.
From there, it's just a matter of looking through the semantics of each code and seeing which one best fits.
400 Bad Request is the generic client error, so you use that if you can't find a better match.
403 Forbidden is roughly "I understand your request, but decline to act upon it." This is most commonly associated with authentication and ACLs, but the standard doesn't actually require that. Given your description, it's not a bad match.
422 Unprocessable Entity from WebDav, is another possibility. I'd reject it, on the grounds that the schema of the message body is perfectly correct, the problem is that the specified value isn't aligned with the current state of the server. You might want to review a previous discussion about 400 vs 422
I am performing a POST to a resource URI. But the success of this operation depends on the responsiveness or accessibility of another related object. If that object is not responsive or inaccessible, the operation needs to return failure. What HTTP code should I choose in this case?
I am currently brainstorming on the following codes, but could not arrive at the right one:
404 NOT FOUND - This represents "not found" for the resource URI, and not a related inaccessible entity.
412 PRECONDITION FAILED - Applicable only for conditional requests with one or more header fields indicating a precondition - I dont need to provide any.
I am not able to find or zero onto a specific HTTP code.
https://greenbytes.de/tech/webdav/rfc7231.html#status.409:
"6.5.8 409 Conflict
The 409 (Conflict) status code indicates that the request could not be completed due to a conflict with the current state of the target resource. This code is used in situations where the user might be able to resolve the conflict and resubmit the request. The server SHOULD generate a payload that includes enough information for a user to recognize the source of the conflict."
Lets check the candidates:
404: always an option but as the same request will sometimes fail or success this will create a flickering behavior which is not what a client would expect when getting 404.
412: RFC 2616 says: "The precondition given in one or more of the request-header fields" - this is not the reason for the failure.
417: similar to 412: "The expectation given in an Expect request-header field could not be met by this server"
503: "The server is currently unable to handle the request due to a temporary overloading or maintenance of the server."
Nothing seems to be perfect but I would choose 503 as it represents the temporary problem best and guides the client to do a retry.
Picking the right status code is always tricky. If you return a status code like 404 for example, debugging can become derailed because someone may not be sure if it's because the URL actually doesn't exist or if it's because of some other reason internally.
Usually the caller only needs to know a few things:
Did the endpoint exist? If not, 404 NOT FOUND
Was my request properly formed and did it pass validation? If not, 400 BAD REQUEST
Was my request denied because of improper authentication? If not, 401 or 403 depending on the context (there is a subtle difference)
Did my request fail because of something out of my control? If so, 500 INTERNAL ERROR
Typically I try to separate the response from the service's logic. If you want to be more specific as to exactly what happened (in your example a dependency is not responsive), returning a bit of JSON that describes in more detail what the problem was is would be a more appropriate place for that as opposed to using the http status code to describe a specific error on the service side.
So in your case, I think 500 is the most appropriate. The caller just knows that something went wrong and there's nothing it can do about it, and it can handle that condition however it needs to. If the caller needs to know more about what happened, use a JSON response to convey that.
List of HTTP status codes
1xx Informational
2xx Success
3xx Redirection
4xx Client Error
5xx Server Error
Refer wiki :
103 Checkpoint
Used in the resumable requests proposal to resume aborted PUT or POST requests.
420 Method Failure (Spring Framework)
A deprecated response used by the Spring Framework when a method has failed.
420 Enhance Your Calm (Twitter)
Returned by version 1 of the Twitter Search and Trends API when the client is being rate limited; versions 1.1 and later use the 429 Too Many Requests response code instead.
450 Blocked by Windows Parental Controls (Microsoft)
A Microsoft extension. This error is given when Windows Parental Controls are turned on and are blocking access to the given webpage.
498 Invalid Token (Esri)
Returned by ArcGIS for Server. A code of 498 indicates an expired or otherwise invalid token.
499 Token Required (Esri)
Returned by ArcGIS for Server. A code of 499 indicates that a token is required but was not submitted.
499 Request has been forbidden by antivirus
Produced by some programs such as Wget when a malicious site is intercepted.
509 Bandwidth Limit Exceeded (Apache Web Server/cPanel)
The server has exceeded the bandwidth specified by the server administrator; > this is often used by shared hosting providers to limit the bandwidth of customers.
530 Site is frozen
Used by the Pantheon web platform to indicate a site that has been frozen due to inactivity.
My payment endpoint which accepts a POST should deny requests when the user does not have any payment methods configured. What is the correct HTTP status code in this case?
What is the correct HTTP status code to be raised when the system itself cannot reach the state asked for by the request and another request (creating a payment method) must be completed first?
I looked at 428 Precondition Required, but that seems to have more to do with the headers than the state of the system.
I would go simply with 400 Bad Request. If you need more specific instructions or hints in the response, you can return a body, which will indicate the exact nature of the error.
You don't need to assign a specific HTTP error code to all your internal business-related error cases. Indeed this is probably not possible anyway.
The specification on 400: https://www.rfc-editor.org/rfc/rfc7231#section-6.5.1
Relevant quotes from there:
indicates that the server cannot or will not process the request due to something that is perceived to be a client error
And about the 4xx codes in general:
the server SHOULD send a representation containing an explanation of the error situation, and whether it is a temporary or permanent condition
Did you look into error 424 Failed_Dependency? I think this could bethe one you want.
See
http://www.restpatterns.org/HTTP_Status_Codes/424_-_Failed_Dependency
I'm building an API which operates on a noun Foo. When a caller creates an instance of Foo with a POST request, they are required to provide an ID to a second noun, Bar. If the ID they provided is of the right type but there is no Bar with that ID, is 404 the right response?
I think it depends on whether the ID is in the URL or not. The URL is the address for a resource, if the ID is in the URL and no item with this ID exists, or you don't provide it at all, then the URL is invalid, so no resource could be found, so that's a 404.
However, if the ID is not in the URL but in the data from the POST request, and the URL is a valid address to a resource, then a 400 Bad Request should be returned.
I would suggest using HTTP 400 (Bad Request).
See http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.1. One could interpret 400 as a generic indication that the client did not form the request correctly.
One could also make a case for returning a 500 response. If the client believes that the Bar reference is valid, then the server's failure to process this request could be viewed as exceptional. This could happen for example if the reference is valid, but the a different client deletes it. In this scenario, the first client is not doing anything wrong.
In short: No. Your API should be "user-friendly" meaning, if there is an error it should return it in a way that the user can figure out what the problem was. Returning 404 is like saying that the service was not found which is not true. The response should be 403 - cause it could be that the resource with the ID that the client tries to approach belong to a different client!
In addition, the response should contain an error message/code (in the body) which can be parsed and analyzed by the client.
This is a bit grey area.
Although the 500 response code looks like a good fit because of its broader context, the 404 response code could also be considered.
The reason that I am not sure about the 404 code is the main purpose of your request. The request is sent to create a new resource. It is not for retrieving an existing resource. Though the root cause is the "Not Found" resource, the intention of the request is for a new entity. Getting the 404 response code might cause ambiguity for the client. Therefore, the 500 with a good explanation looks like a better option.
I can clearly state that the 400 response code is not convenient for this case because there is nothing wrong with the request syntax.
The following definitions from MDN Web Docs - HTTP response status codes might help to make a decision.
400 Bad Request:
The server could not understand the request due to invalid syntax.
404 Not Found:
The server can not find the requested resource. In the browser, this
means the URL is not recognized. In an API, this can also mean that
the endpoint is valid but the resource itself does not exist. Servers
may also send this response instead of 403 to hide the existence of a
resource from an unauthorized client. This response code is probably
the most famous one due to its frequent occurrence on the web.
500 Internal Server Error:
The server has encountered a situation it doesn't know how to handle.
4xx is entitled "Client Error" in the standard
5xx is entitled "Server Error"
If the server is 100% sure that the reference to Bar could not be correct (that id is totally invalid format or couldn't have existed) then that's a straight up 400 Bad Request.
If the server allowed someone to delete that Bar where such deletion should not be allowed (Foo should go down with it) then that's a 500 Internal Server Error.
Here the client is creating a Foo with a dangling reference to a Bar (since it's a POST, if it were updating a Foo it would be a PUT). The client got a reference to the referenced Bar somehow and can presumably find an appropriate existing Bar if it tried again. In that case, the server returns 409 Conflict to signal that the request, while valid, is in conflict with the state of the server and needs to be dropped or reconstructed so that it is consistent with the state of the server. The 409 response should specify that the problem is that the referenced Bar does not exist.