Follow @bissell
Michael's blog
Michael's resume


The API Contract
Default Formats
General API Management
Error Standards
Response Codes
Collections
Filters
Cherry Picking
Conveniences
Change Logs

Default Response Codes

We know to return a 200 OK when things are good, but there are some differences of opinions as to when to return other HTTP codes.

200 OK

A 200 OK should come back when a collection or a resource responds as expected

200 OK - Empty Collection

A query like /collection?filter=something that returns no records should still return a 200 OK - the collection exists, which is OK, but the response should indicate that there are no elements.

{ "content": [], "last": true, "totalElements": 0, "totalPages": 0, "numberOfElements": 0, "first": true, "sort": null, "size": 20, "number": 0 }

We use this rather than a 204 No Content to provide a consistent experience to the App developer and to allow the API to return meta data if necessary about why no content was returned.

201 Created - Successful POST/PUT request

The body response of a 201 Created should be the same as the response of a GET - if there is any orchestration involved in the GET response (such as calculated fields or a a mashup of two resources to give a more detailed response) that same orchestration should be performed on the 201 Created response to a POST or PUT as it would be performed on a 200 OK GET response.

303 See Other

If you move an item, or merge it with another, the response should use 303 See other (as opposed to 301 Moved Permanently or 302 Found). The payload should then contain information about where to find the new content.

HTTP/1.1 303 See Other Content-Type: application/json;charset=UTF-8 Date: Mon, 01 Jan 2018 18:40:26 GMT Server: Apache-Coyote/1.1 { "timestamp" : 1514832028, "status" : 303, "error" : "See Other", "exception" : "org.myco.profile.SeeOtherPersonException", "message" : "See Other - 0f52e80c-4fc5-11e8-9c2d-fa7ae01bbebc", "path" : "/people/myuername@somedomain.ext" }

400 Bad Request - Unknown Query Parameter

Say I get confused and I look for itemIdentifier instead of itemId, you should return an error message, 400 Bad Request because the handler doesn't know anything about itemIdentifier

GET /items?itemIdentifier=123456 { "timestamp": 1487368656934, "status": 400, "error": "Bad Request", "exception": "org.springframework.web.HttpRequestUknownParam", "message": "query parameter itemIdentifier is not recognized", "path": "/items?itemIdentifier=123456" }

If you can get as detailed as to actually say what wasn't recognized, great, but at a minimum, throw the 400 and "one or more query parameters is not recognized"


401 Unauthorized vs 403 Forbidden

Technically, if bad credentials are offered, you should return a 401 Unauthorized but when valid credentials are presented for a resource that you aren't allowed to access, you should return a 403 Forbidden. This makes it easier for the application developer to understand why they are getting the error (bad keys vs bad request).

If you are unable to return a contextual 401 vs 403, you should default to the 403.

404 Object or Collection Not Found

The 404 response should be presented when the resource simply does not exist. This allows the consumer of the API to differentiate between trying to access something they aren't allowed to see (403) versus having simply misspelled something.

409 Conflict

If the API requires the consumer to submit a unique identifier (such as an email address in a User Store) and that identifier exists, the response should be 409 Conflict as in

{ "timestamp": 1485728730258, "status": 409, "error": "Conflict", "exception": "org.myco.profile.web.exceptions.EmailExistException", "message": "This email address already exist: testing201607071543@test.com", "path": "/people" }


Be sure to see my blog over at Cloudenity. This week's topic: Identity Isn't Just for Users Anymore