Use HTTP error handling in APIs, instead of adding your own error-handling layer on top of HTTP, to provide a better developer experience (DX) for people who use your API. In particular, use the correct HTTP status codes, and correctly separate client and server errors.
|404 Not Found
|URL paths that don’t match a back-end action
|404 Not Found
|URL paths that include an invalid ID
|405 Method Not Allowed
|valid URLs but an unsupported HTTP method
|415 Unsupported Media Type
Content-type request header
|406 Not Acceptable
Accept request headers for content types you cannot serve
|400 Bad Request
|application-specific non-HTTP errors
|400 Bad Request
|only client errors that don’t have a more specific status code
Use this checklist for client errors, to identify how to improve your API’s DX. Prioritise statuses in this order: use 404 rather than another status, if it applies, and use 400 as your last choice.
404 Not Found
People’s mistakes in command lines and configuration can lead to sending a request to the wrong URL. You can improve DX by specifying the first part of the URL that caused, in the response.
404 Not Foundfor URL paths that don’t match a back-end action
404 Not Foundfor URL paths that include an invalid ID
Beware of servers and frameworks that treat URLs that don’t map to server-side code as a server error.
You improve DX when you recognise that from the client’s perspective, a misconfigured URL mapping still results in a URL that doesn’t work.
You also get better DX by using
404 Not Found for API URLs that include a unique identifier, such as a database primary key or a UUID, when the ID doesn’t correspond to an available resource.
Proritise this status over other 4xx error statuses.
405 Method Not Allowed
It helps to think of an HTTP API as exposing HTTP resources identified by URLs. Even if the client gets the URL right, not every resource supports every HTTP method.
405 Method Not Allowedfor valid URLs but an unsupported HTTP method
You could help the API user by indicating whether the API never allows this method, such as a
DELETE /login request, or whether the API allows it depending on context, such as updates for a possibly read-only resource.
The response body could even summarise the resource’s allowed HTTP methods and what they do, although I’ve never seen this in practice.
Prioritise this status second, after
404 Not Found.
415 Unsupported Media Type
Media types allow HTTP APIs to explicit identify what kind of image or document, or whatever, a request or response body contains. For web sites, it helps that web browsers do their best to make everything Just Work, but APIs deliver better DX with more explicit behaviour.
415 Unsupported Media Typewhen the API doesn’t support the request’s
This might happen when someone sends an XML request body for an API that only understands JSON. Good DX depends on understanding why someone might do this.
Someone exploring which types the API supports by guessing, instead of reading the docs, needs different error details than someone who sent the right data to the wrong API, because they mixed up their URLs.
406 Not Acceptable
406 Not Acceptablefor requests whose
Acceptheaders require only types you cannot serve.
This might happen when a client sends a request that specifies that the client only understands XML, while the server that only serves JSON. Serving JSON anyway makes it pretty clear that the API doesn’t care about DX, and requires the client developer to recognise the errors an XML parser reports when it tries to parse JSON.
Beware of servers and frameworks that return HTML error pages instead of the content type the API client can parse. Similarly, watch out for misconfigured servers that send a redirect to a log-in web page when authentication fails.
Using an API that doesn’t implement content negotiation properly, including the
406 Not Acceptable status, requires extra work to check each response’s content type before attempting to parse the response.
400 Bad Request
‘Bad request’ doesn’t tell clients anything about what they did wrong, so this status code relies on application-specific error details in the HTTP response. Failing to separate application-level errors from standard HTTP errors leads to the same poor experience as failing to separate server and client errors.
400 Bad Requestfor application-specific non-HTTP errors
- Only use
400 Bad Requestfor client errors that don’t have a more specific status code.
For example, a request might fail due to a missing required parameter. In general, HTTP doesn’t have any way to specify application data. Schemas belong in another layer.