Question

Our POST API takes in an identifier (let's say deviceId) in order to compute the accuracy of the location we have stored for that device in a DB; the result of that compution is then saved in a different table. On a successful call, we return the result with a 200 code.

We call a dependent service, including the deviceId in the request, to get the device's location. If our dependency doesn't return a location because it couldn't find one associated with the device, we can't run our algorithm to compute the accuracy because we don't have one of the required inputs.

Question is, what should be returned to the calling client?

I was thinking a 404 error, but that doesn't 100% fit because the deviceId was correct and found, but required information for that deviceId could not be found.

Another option I was considering was returning an empty/null body with either a 200 or 204 code response. I think a 204 makes more sense in this case. However, I'm not sure if that fits 100% either since we weren't able to complete the computation and therefore weren't able to store the result in our DB.

Any input is appreciated!

Was it helpful?

Solution

If you are creating a web api, I find that it is best to think in terms of documents (see Webber 2011); URI identify documents, and method-tokens identify the operation that we want to apply to a document.

Unsafe operations (POST, PUT, PATCH, DELETE....) are requests that we change the contents of a document. Key idea - when the contents of the document change on the server, we also want to invalidate any cached copies of the old version of the document. RFC 7234 describes the mechanism for this.

But the short version is: when we respond to POST /foo with a non-error status code, that tells general purpose caches that the representation of /foo may have changed, and therefore previously cached copies should be invalidated.

On the other hand, an error response (4xx or 5xx) indicates that the representation has not changed, and therefore the cache can continue to provide the copy of the document it has.


Therefore, based on your description, I would expect that you would be using POST /foo, where /foo identifies a document that includes the result of your calculation (ie, the data in your second table).

On the happy path, where you are able to compute and store the data in your second table, then a 200 response is fine.

For the case where you cannot, because the remote system doesn't have the information you expect... That's trickier. 404 is certainly an option if the identifier is the problem (the fact that the missing data is in a different database really doesn't matter), 403 "I understood the request but I'm not going to do it", 409 "the resource is in the wrong state to do that" is another possibility.

These are all variations of saying "the request was wrong".

The possibility that I think is most interesting is 503 "I understood the request, but I can't fulfill it now. Ask me later." With the appropriate Retry-After headers, you can communicate how long the client should be expected to wait.


It might even be reasonable to use a 200 here; when your document has information in it that says something like "we couldn't find the location information as of [time]", because the failed attempt to look up that data also changes that "as of" time.

200 means that the request was understood and processed correctly - that doesn't necessarily mean that the processing took the "happy path".


In short: "it depends".

OTHER TIPS

Depends on what the semantics of your resource should be, i.e. what the clients would expect.

Is it "normal", that the clients would call with input parameters for which this calculation can not be performed? If yes, code 200 will do, since your service performs as requested. In this case the client must expect the server to not perform the computation sometimes, i.e. it has to implement contingencies probably.

If such an error is unexpected, then returning 500 is more appropriate, i.e. there was a generic error on the server side, because of which the calculation can not be performed. In this case clients would not expect an error to occur under normal circumstances, which makes for an easier implementation.

From a client perspective the request failed.

For the client is does not matter that the handling of the request is done by separate components. The client makes a request, which cannot be completed, so a 2xx answer would not be appropriate imo.

My suggestion would be to return 422 Unprocessable Entity.

The HyperText Transfer Protocol (HTTP) 422 Unprocessable Entity response status code indicates that the server understands the content type of the request entity, and the syntax of the request entity is correct, but it was unable to process the contained instructions.

In addition, the response should contain an explanation and there should be an endpoint for the client to post a location for the device, so the client has an opportunity to fix the error.

If this is a truly exceptional situation that shouldn't occur, I would return a 500 error.

An empty 200 response is just as valid as a 200 response with details.

A 200 response should be just fine. The payload will just have to contain information to tell the client that no location could be found associated with the device. To give an analogy, consider a search for products or something. If you search for a product name, the query can return zero, one or more matches. In all cases you return 200 because the operation was successful. There is no need for a different status code if nothing could be found to match my search term.

If still in doubt, take it by process of elimination (list of HTTP status codes):

  • 1xx informational response – the request was received, continuing process
  • 2xx successful – the request was successfully received, understood, and accepted
  • 3xx redirection – further action needs to be taken in order to complete the request
  • 4xx client error – the request contains bad syntax or cannot be fulfilled
  • 5xx server error – the server failed to fulfil an apparently valid request

5xx doesn't really makes sense because you don't have a server error. 4xx would be weird because the client did nothing wrong. You can use 3xx only if you want to redirect the client some place else for some reason or ask it to do something else. 1xx doesn't really apply. So you are left with the 2xx range, from which only 200 and 204 make sense. But based on what I mentioned above, I believe 200 is more appropriate (with a proper payload response).

Licensed under: CC-BY-SA with attribution
scroll top