Speakeasy Logo
Skip to Content

Returning informative API Errors

When building an API it’s natural to put most of the focus into building a beautiful “happy path” where nothing goes wrong. Developers often don’t like to consider the failure cases, because of course everything is going to work out just fine, so errors are often not designed with the same care as the rest of the API.

Errors in an API are not just an edge-case, they are a crucial part of the functionality, and should be treated like a core feature to be proudly shared and documented with users. Failing clearly and concisely is arguably more important than any other aspect of API design.

Errors should:

  • Be as detailed as possible.
  • Provide context as to exactly what went wrong, and why.
  • Help humans find out more information about the problem.
  • Help computers decide what to do next.
  • Be consistent across the API.

HTTP Status Codes

The journey to great errors starts with status codes. Status code conventions exist to specify what category of error has occurred, and they are a great way to help developers make decisions automatically based on the status code, like automatically refreshing access tokens on a 403, or retrying the request on a 500.

Learn more about HTTP Status Codes, and how to use them effectively.

Application Errors

HTTP status codes only set the scene for the category of issue that has occurred. An error like 400 Bad Request is generally used as a vague catch-all error that covers a whole range of potential issues.

More information will be required to help developers understand what went wrong, and how to fix it, without having to dig through logs or contact the support team.

Error details are useful for:

  1. humans - so that the developer building the integration can understand the issue.
  2. software - so that client applications can automatically handle more situations correctly.

Imagine building a carpooling app, where the user plans a trip between two locations. What happens if the user inputs coordinates that which are not possible to drive between, say England and Iceland? Below is a series of responses from the API with increasing precision:

HTTP/1.1 400 Bad Request

A not very helpful error response, the user will have no idea what they did incorrectly.

HTTP/1.1 400 Bad Request "error": { "message": "Trip is not possible, please check start/stop coordinates and try again." }

This message could be passed back to the user which will allow them to figure out how to address the issue, but it would be very difficult for an application to programmatically determine what issue occurred and how to respond.

HTTP/1.1 400 Bad Request "error": { "code": "trip_not_possible", "message": "Trip is not possible, please check start/stop coordinates and try again." }

Now this includes data that can help our users know what’s going on, as well as an error code which let’s them handle the error programmatically if they would like to.

So, we should always include both API error messages, as well as API error codes. Let’s take a closer look at the best practices for each of these.

API error messages

API error messages should be clear, concise, and actionable. They should provide enough information for the developer to understand what went wrong, and how to fix it.

Here are a few best practices for API error messages:

  • Be Specific: The error message should clearly explain what went wrong.
  • Be Human-Readable: The error message should be easy to understand.
  • Be Actionable: The error message should provide guidance on how to fix the issue.
  • Be Consistent: Error messages should follow a consistent format across the API.

API error codes

The use of an error code is well established in the API ecosystem. However, unlike status codes, error codes are specific to an API or organization. That said, there are conventions to follow to give error codes a predictable format.