API design - Optional body in client request - Status code to return if validation fails - rest

In our API, one of the endpoint will expect clients to provide body/payload only in certain scenario.
If the API is unable to generate a payload for given request based on the origin of the client then, we want our API to provide response with the right status code to the client, so that they know they have to provide additional information. Once the client fulfills the request with body/payload then the api will process the request as normal.
I just wanted to know is there any standard, predefined status code or procedure to implement this kind of endpoint in API design or do we have to just reject the request with some custom status code and then ask the client to implement a logic based on custom code?.
Thanks,
Vinoth

HTTP Status codes don't, nor are they intended to, map precisely against every real world error. They represent categories of error.
For example, a 404 means that the resource couldn't be found, but if your path is /customers/11/animals/5 then there are several things which could be wrong with the path. customer 11 may not have an animal 5 for example, or there may be no customer 11. There is no http response for "animal not found". Or your API may not have any calls with that pattern of URL to begin with.
You should return a status code which represents what "category" of error you have (in this case, something was not found), and the response body should contain more specific details about the error. To make things simpler, I find it helpful if the data structure is the same for a success and error (it makes parsing much easier) with a "data" field which varies per response.
Here is one example:
status code: 404 not found
body: {
"messageDetailCode" :"CustomerNotFound",
"messageDetail" : "Customer not found",
"data" : null
}
Further reading:
What's an appropriate HTTP status code to return by a REST API service for a validation failure?

Related

REST API design issue

I am calling a REST API for a list of resources and getting the json response as below if atleast one resource is there.
{
"value": [
"res1_id",
"res2_id",
"res3_id"
]
}
and the HTTP response code is 200.
But when no resource is there the server is returning HTTP response code as 404.
My doubt it why it is designed that way(it is an enterprise product).
I was expecting a empty list as below and HTTP response code 200:
{
"value": []
}
I am not able to understand what design decision has been taken into consideration to return 404 instead of an empty json.
Please help me to understand the reasoning behind it.
What I am reading here is that you have a 'collection' resource. This collection resource contains a list of sub-resources.
There's two possible interpretations for this case.
The collection resource is 0-length.
The collection resource doesn't exist.
Most API's will treat a 0-length collection as a resource that still exists, with a 200 OK. An empty coffee cup is still a coffee cup. The coffee cup itself did not disappear after the last drop is gone.
There are cases where it might be desirable for a collection resource to 404. For example, if you want to indicate that a collection never existed or never has been created.
One way to think about this is the difference between an empty directory or a directory not existing. Both cases can 'tell' the developer something else.
You're trying to access a resource which does not exist. That's the reason for 404.
As a simple google search says
The HTTP 404, 404 Not Found, and 404 error message is a Hypertext
Transfer Protocol (HTTP) standard response code, in computer network
communications, to indicate that the client was able to communicate
with a given server, but the server could not find what was requested.
For your case
{
"value": []
}
This can be a status code 200 which means the resource is accessed and data is returned which is an empty array or you can customize it to a 404. But for that you've mentioned best is to return 200.
A status code of 404 is the correct response for when there is no resource to return based on a request you made. You asked for data and there is no data. It returns an empty response. They're relying on you to base your interpretation of the results on the status code.
https://en.wikipedia.org/wiki/HTTP_404
Some companies prefer making their errors known instead of hiding them. I know where I work we shy away from try catch blocks because we want our applications to blow up during testing so we can fix the problem. Not hide it. So it's possible that the dev that created the API wants you to use the status code of the response as a way of telling if the service was successful.

API rest response code for not handle endpoint

I have
/rest/drink/categories?alcohol=true
which is return 200 status code with list of drink categories that have alcohol in it, e.g.
200 ['wine','beer']
I wonder what status code should I use, if a user hit a none handled path like below
/rest/drink
or
/rest/drink?alcohol=true
404 - Not found if the URL does not exist,
400 - Bad request if the URL exists but the request parameter is invalid.
Http has status for such conditions.
4XX defines the error is from client side and needs a change.
Wiki says
The 4xx class of status code is intended for situations in which the client seems to have erred. Except when responding to a HEAD request, the server should include an entity containing an explanation of the error situation, and whether it is a temporary or permanent condition. These status codes are applicable to any request method. User agents should display any included entity to the user.[31]
For the condition where it is mentioned, its ideal to use 404 - Not Found or 400 - Bad Request
This gives list of all the status codes and appropriate explanation.
W3Org
defined the specifications for these.

REST API & HTTP Status Code

I have a bunch of PUT operations which execute actions on the input resource.
Let's make an example: I have a payment operation in my API which state that a credit card must be charged by a specific Amount.
In my code I first verify if there is sufficient credit on the card and then execute the operation. If there is'nt sufficient amount I simply return 400 but I am not sure it is correct.
Which is the correct HTTP Status Code in cases like this?
I can, of course send a response with HTTP 200 and attach a payload with further details explaining the error. I can also send back an HTTP 400 Bad Request or even better an HTTP 412 Precondition Failed.
Which is the correct code to send in the response in scenario like this where the validation failed? Is there any resource that I can read to understand the rationale behind HTTP Status Codes and HTTP Verbs?
Use 422 Unprocessable Entity.
The 422 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.
Failing that, simply use 400 for any error having to do with your business domain. As of June 2004, the description for error 400 was amended to read:
The server cannot or will not process the request due to something that is perceived to be a client error
If the operation failed because of data sent by the user (it seems to be the case), you should use status codes 400 (general) or 422 (more precise but coming from the WebDAV spec). You can return back additional hints about the error within the payload (the structure is up to you) like:
{
error: {
"field": "amount",
"message": "The amount isn't correct - Sufficient credit."
}
}
I think that code 412 doesn't apply here since it must be returned when your server doesn't meet a condition specified by the client (see headers If-* like If-Match, If-Modified-Since, ...).
Hope it helps you,
Thierry
IMO: I would stick with 200 and then parse out the response and deal with that. HTTP status codes are protocol status code, not something that you should use for dealing with application logic.
{
"error": {
"field": "amount",
"message": "The amount isn't correct - Sufficient credit."
}
}
In case of the above code, the service call worked fine warranting a return code 200. However, you application logic now needs to deal with the error reported.
If we are using a HTTP status code to indicate error, we will start to get flagged in our logs etc. even though there was no technical error.

HTTP Status codes confusion

So, I am trying to display meaningful and accurate HTTP status codes and I'm getting confused even after going through the examples online. Here's my situation:
In the URL which accepts the query param:
#POST query
Sample URL: /putRecord?Name=A&Age=25&house=permanent
what status code do i return when one of the params is missing? (All 3 are mandatory) - from what I've read, I am guessing it is a 400: Bad request. But this seems too general. Is there a way for me to say that the query was malformed? Source:here
Assuming I validate the name for duplicates against the DB, if I get a duplicate, what status code do I return?
So, if there's a duplicate entry available already, I can't add the record. Do I display 304 (Not modified) or just the error code from 2?
Clarification: For 3, another possibility is when I can't actually commit to the DB and I rollback(possibly). What status code will it be now?
Thanks so much!
Ad 1. You can return, besides the code itself (400) also a short message with explanation. So, instead of returing "400 Bad Request" you could respond with "400 Query param name required" or something similar. This message is called "reason phrase" and is defined in 6.1 in RFC 2616. Or, if you need more flexibility, you could return document with the explanation.
Ad 2. I would consider using 422 Unprocessable entity. From the RFC 4918:
The 422 (Unprocessable Entity) status code means the server understands the content type of the request entity, 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.
Ad 3. I would return 422, but it really depends whether this situation is considered an error in your logic, or is it a regular, expected situation.
Edit: As #War10ck suggested in the comment, HTTP 409 (in place of HTTP 422) might make sense as well.
Note on handling duplicates: it seems (correct me if I'm wrong) that you consider new entity being a duplicate if it's name is already in the database. If so, that you could maybe consider using a HTTP PUT instead of HTTP POST?
You could define the following resource:
HTTP PUT /record/:name
So, "name" would be a part of the URI. Then, in case there is a second PUT to the same resource (same "name"), it'd be elegant to respond with 409/422.
If you're using different key for unique constraint, modify the URI appropriately.
As a rule of thumb, POST is for situations where you can have multiple instances of a given resource, i.e.
HTTP POST /log ;; Because we have many logs
And PUT for situations where each resource is unique:
HTTP PUT /person/:name (or /person/:tax-number if :name isn't unique)
Also, note that I've renamed your resource from "putRecord" to "record" - PUT is a HTTP method, no reason to have it in URI as well.

What should a RESTful API POST/DELETE return in the body?

To follow and unfollow a person via a RESTful API, I have
POST /person/bob/follow
DELETE /person/bob/follow
What should these return in the body?
A collection of everyone you follow
The person you just followed / unfollowed
A status like { status: "ok" }
Nothing.
If you respond on errors using a HTTP server status, the status code does not say anything. If you respond with a 404 Not Found if there is no user Bob, or a 500 Internal Server Error if the database is broken, the only successful response you will ever get is OK. Users do not have to check the status code, they only have to check the HTTP status code.
I suggest you return nothing, and the fact that it is a successful response (i.e. 200 OK or 204 No Content) indicates that the operation was successful.
It all depends on your app/API design and the contract you are gonna define with the client/callers. But generally, in all the cases you should return status code to make your client aware of the result.
Like: respond(ResponseCode::OK, ...)
For POST: I'd return 'bob' object containing all of his followers + status code
For DELETE: I'd only return the status code.
Generally, for an API, I'm apologist to use the HTTP status codes instead of always OK with a code defined status.
This means that you can follow the existing standards for answers, and anyone who gets an error code will know roughly what happened/what they have to do.
Take a look at the wiki article http status codes for a usable reference manual.
Also, together with the error code, and because is an API we are talking about, it is useful to have a more descriptive message about the error. Something meaningful like error: "Auth token missing", or whatever standard you might come up with.
When it comes to creating resources, I generally answer back with 201 (Created) and the resource just created. Keep in mind that you might want to exclude some attributes from the resource (e.g. You're creating a user, you shouldn't return sensitive info such as the encrypted password)
Regarding the deletion of resources, generally return with either 200 (Ok) or 202 (Accepted) and no extra info.
Nevertheless, As #yek mentioned, it highly depends on the commitment with the API consumer. The most important thing is that you document the API decently and explain what should be the expectations.