Search code examples
spring-bootapiresthttpresponse

REST API - Which Http status codes to use for a booking API?


I'm a little confused about which HTTP status codes to return for the API I am building. The API which allows clients to query a product inventory and make rental bookings.

The question is when to use 400s and when to use 200s in the following similar situations:

  1. The end user makes a valid booking request but the items they've requested are all booked up for the dates they've picked.
  2. The end user makes a valid booking request but the order dates are too soon. KEY INFO: we need at least two days notice to fulfil an order.
  3. The end user tries to call my {orderId}/confirm endpoint a day after first reserving it. KEY INFO: You have to confirm an order within 15 minutes of reservation or it will timeout.

The requests are correctly formed and the resources they refer to all exist, so can we really call it an error on the client's side? And if not then is it appropriate to return 400 codes?

Which HTTPStatus would you use in these cases? Something in the 200s or something in the 400s?


Solution

  • Which Http status codes to use for a booking API?

    HTTP status codes belong to the transfer of documents over a network domain. So you use them exactly the same way every other server on the world wide web uses them.

    The status-code element is a 3-digit integer code describing the result of the server's attempt to understand and satisfy the client's corresponding request. The rest of the response message is to be interpreted in light of the semantics defined for that status code.

    The semantics that are specific to your domain don't belong in the HTTP headers, but instead in the message body of the response.

    A useful heuristic in abiding the REST architectural constraints: how would you do it on the web? Typically, the information you intend for the human being - the client that understands the context of the domain - belongs in the HTML, which is to say the body of the HTTP response. The metadata (status codes, headers) provide semantic hints to general purpose components (browsers, caches, web-crawlers) that aren't interested in the contents of the documents.

    The question is when to use 400s and when to use 200s in the following similar situations

    It may help to consider the rules for cache-invalidation. The TL;DR being that if you send a error status code (4xx or 5xx), then the cache knows that the response body is a representation of an error, and previously cached copies of the resource should still be considered valid.

    A 2xx code, on the other hand, reports that the request did successfully change the resource, and therefore the previously cached copies of the resource can be invalidated.

    POST /orders/12345 HTTP/1.1
    Content-Type: application/x-www-form-urlencoded
    
    confirm=yes
    

    If this message changes the /orders/12345 resource, then you should be biased toward returning a 2xx response, even if the change to the document doesn't reflect the "happy path" in your domain. On the other hand, if the resource doesn't change, then a 4xx code is more appropriate.

    The status code registry documents where the semantics of each status code are currently defined. You could dig through each of the standards to understand the different meanings and implications of each.

    But the short version is that there are two 4xx codes that stand out:

    • 403, which indicates that the server understood the request but declines to fulfill it.
    • 409, which indicates that the server cannot fulfill the request because of the current state of the resource.

    I haven't found anything in the standards where these two codes are treated differently.

    I think you can make an argument that 409 invites the client to fetch a new copy of the resource, merge the changes, and then resubmit -- in much the same way that 401 invites the client to resubmit the request with authorization credentials. But I've never heard of a general purpose component that does that. It's a bit of a reach, perhaps.