52

Our service is in 5 cities right now. If someone tries to call our service API from any other city, we want to throw this error Service not available in your area.

The question is, what is the appropriate http code would be for this error?

  • 503: Service Unavailable
  • 403: Forbidden

or something else?

Shaharyar
  • 875

10 Answers10

102

Any HTTP error code would be inappropriate. There is no error or problem of any sort from an HTTP perspective so it should be something in the 200 range. You politely inform some of your users that they will not be serviced by sending back a document that tells them so. And this all goes well.

The user will not be able to use your application. That is a conscious decision made by your business logic, not a mishap. On the HTTP level everything is honky dory.

Edit

It looks like what we are looking at here is a clash of old school versus new school. When HTTP was designed, there were no web services, there was no SOAP, no JSON, no REST principles. As a protocol above TCP this was already considered (close to) application level and many high level status codes were defined. When the web started to be used for richer, high level services and a common means to transport "envelopes" was required, designers hi-jacked HTTP rather than defining a newer and cleaner protocol, just because HTTP was ubiquitous.

So in a modern web service context, HTTP is indeed little more than a dumb transport layer and most of its codes may be considered not applicable or obsolete. Just picking one because it comes close to your application state and happens to be in that list that once meant something may seem harmless, but I think it would send a wrong message. You do not want HTTP to play that regulating role in a web service context.

Martin Maat
  • 18,652
87

5xx errors are server errors - something went wrong on the server. In particular, a 503 indicates that:

the server is currently unable to handle the request due to a temporary overload or scheduled maintenance

4xx errors are client errors - the client is making a request that the server is unable or unwilling to fulfill. In particular, a 403 indicates that

the server understood the request but refuses to authorize it. A server that wishes to make public why the request has been forbidden can describe that reason in the response payload (if any). [..] However, a request might be forbidden for reasons unrelated to the credentials.

I would argue that 503 is clearly incorrect, because this isn't a temporary issue - you don't support requests in that area, period. The argument could be made that you eventually hope to support the area, but the intent of the code is to include a header indicating when the client can try again. "In 6 months" doesn't adhere to the intent.

403 is a better choice because your service simply forbids requests from certain locales.

Eric Stein
  • 3,602
47

Neither of those.

If your API is well-designed, the URL includes the name of the city, e.g.

http://example.com/API/Vienna/HailRide

or

http://example.com/API/HailRide?city=Vienna

since IP geolocation is unreliable, your users might be using VPNs, your users might want hail a ride for someone else, etc. Suggesting a city based on the user's location is the API client's responsibility. Usually, the client has much better resources for determining the user's location anyway (for example, a mobile device's location service).

Once you've done that, the correct answer to

http://example.com/API/SomeUnsupportedCity/HailRide

or

http://example.com/API/HailRide?city=SomeUnsupportedCity

becomes obvious: 404 Not Found: No resource for hailing a ride at SomeUnsupportedCity exists.

Heinzi
  • 9,868
27

This seems like a round hole/square peg question. Why does your only response need to be an HTTP code? HTTP error codes can't possibly cover all use cases.

All of your API calls should have additional messaging that comes back - i.e. a little JSON error message. Give them an 403 (because, truly they don't have the permission to use the API given the location) and return an additional bit of information as you're suggesting.

If you don't do this then next time you'll ask what HTTP error code to return when the user asked for an SUV but only a Prius is available.

stdunbar
  • 457
12

A few make sense.

403 Forbidden, for the reasons that Eric Stein mentions in his answer. You can use various information provided by the request to determine where the client is and who the client is and, based on that request, the server is unable or unwilling to respond.

However, I would also put forward 451 Unavailable for Legal Reasons as a possible return status for some cases. This status does expect you to include (in the headers) a link to the relevant legislation. It's specifically for cases where it is not legal for the client to be accessing your resources, and not a more general case of the client exists in an unsupported region or area.

I would avoid the 5xx series of statuses - these often indicate server side technical issues. It does not appear to be the case here.

Thomas Owens
  • 85,641
  • 18
  • 207
  • 307
6

If the restriction is due to legal reasons, then the appropriate HTTP error code is HTTP 451, "Unavailable due to legal reasons."

This is typically used in the case of material that has been revoked due to DMCA action or lawsuits due to harassment campaigns or the like, but the spirit and letter of the response definition states:

This document specifies a Hypertext Transfer Protocol (HTTP) status code for use when resource access is denied as a consequence of legal demands.

The code itself is a reference to Fahrenheit 451 by Ray Bradbury.

fluffy
  • 410
6

People often forget that HTTP status codes are extensible.

HTTP status codes are extensible. HTTP applications are not required to understand the meaning of all registered status codes, though such understanding is obviously desirable. However, applications MUST understand the class of any status code, as indicated by the first digit, and treat any unrecognized response as being equivalent to the x00 status code of that class, with the exception that an unrecognized response MUST NOT be cached. For example, if an unrecognized status code of 431 is received by the client, it can safely assume that there was something wrong with its request and treat the response as if it had received a 400 status code. In such cases, user agents SHOULD present to the user the entity returned with the response, since that entity is likely to include human- readable information which will explain the unusual status.

https://www.rfc-editor.org/rfc/rfc2616#section-6.1.1

You can always just create your own status code in the 400 range for use by your API and client application.

RubberDuck
  • 9,021
0

At first I thought 503 because the description "service unavailable" seems to align with the issue but looking at the definitions, 503 is really specific to server unavailability. Then thinking more, you are telling the client that there is a problem with the request, not that there is a server side issue.

403 is closer because you are telling the user that you received the message and understand it but that the server is unwilling to satisfy it. This might be confusing so a textual explanation can be added to describe the scenario. Per the RFC, 404 is also a valid substitute for this code.

Unless someone has dreamed up a new code for this, 403 or 404 seem to be the closest.

JimmyJames supports Canada
  • 30,578
  • 3
  • 59
  • 108
0

You should match the description of the error with the code that you are giving:

  • if you say Service not available in your area. then you should give a 404 because you claim that the service is not available.

  • if you say You are not authorized for this service in your area. then you should give a 403 because you claim that the caller is not authorized.

I'd go for the second.

Edoardo
  • 236
0

There's a current Internet-Draft (that will expire on December 31, 2018) that proposes amendments to the HTTP 451 Unavailable for Legal Reasons status. The draft suggests that a 451 response should contain a geo-scope-block header that should "correspond to comma-separated list of alpha-2 country codes defined in [ISO.3166-1]". However, the draft also specifies that the code 451 should not be used "by an operator to deny access to a resource on the basis of a policy specified by the operator (as opposed to a legal demand being placed on the operator)".

So assuming you don't have a legal demand for the geoblock, 451 is not the correct code. What is the correct code then? Well, numerous other answers have already suggested 403 Forbidden, but they all seem to be "opinion based", so let's see what others are doing:

So, there's no one universal solution, you are just going to have to pick one that you feel suits your situation the best. But whichever you choose, be sure to explain the actual issue in the response body.

I'd say there would be nothing wrong in just specifying a custom HTTP status code, like RubberDuck already answered. A custom status code in the 400-range might actually even be a pretty good call, because that will definitely get the developers' attention if they see something like "HTTP status 499". A "403" is too easy to pass as "OK so I got my password wrong, let's try something else instead", and that results in wasted hours.

ZeroOne
  • 956