Designing API error codes and responses

Joanna Suau
UX Collective
Published in
5 min readNov 13, 2022

--

Photo by Markus Spiske on Unsplash

What is an error code and a status response?

For each API request there is an API response. A status code that you get as part of a response indicates whether the request you’ve just sent has been successfully completed. In turn, an error code lets you know that your request has failed.

Why is it important to return a status code in the API?

Error and status codes are extremely valuable to all parties involved. They allow the API creators to communicate with the API users in a short and efficient way, as the codes are always returned in every response.

In a way, this is the first stage of direct communication even before a support ticket is raised. If an error code includes a message that’s descriptive enough or is well documented there’s a big possibility that no ticket will be needed and the user will be able to troubleshoot the issue on their own.

If an API uses standard HTTP response status codes, this may be the first indication to the API user where the problem occurred and how to rectify it. And so for instance all 5xx errors point at some issue with a server whereas 3xx suggests a URL-related problem.

Successful status codes are just as important as error codes. Without them, it would be very difficult for an API user to know whether his request to update or delete a resource has been successful.

In the official HTTP protocol guidelines all status codes are organized into classes for easy API governance. And so, if you have just sent a POST or a PUT request, you’ll likely get a 201 Createdresponse as a standard indication that your request was successful and a resource has been created/updated as a result. These types of responses belong to the successful response group. You can also get information or redirection messages, all stemming out of a standard API behavior.

When it comes to error codes, as mentioned above, you’ll typically have either client or server errors returned. This is a great initial indication of where the issue is coming from, an external system to which you’re sending a request (server) or your own environment (client).

The underrated value of an error code

Error codes can be incredibly useful when displayed or documented properly. The ones returned in the response stage of an API data transfer are the first gateway to direct communication developers can establish with an end user (aka a fellow developer who will end up implementing their API).

Error codes notify the user of a certain failure, but well-thought error messages can also jump-start the process of troubleshooting by giving the user ideas on what to do when such an error occurs, or who to contact in case all else fails.

An API consumer doesn’t choose the error, but the API creator does! And they can use this to their advantage. Don’t treat errors as necessary evil, treat them as a means of communication.

Right at the beginning, a standard error code will let you know where the error occurred and what the circumstances were. For instance, the standard error 401 Unauthorized will tell you immediately that whatever resource you’re trying to request, you don’t have valid authentication credentials.

If said message additionally included a short message like, Pass valid token, you could also learn a bit more about that particular API and what’s its expected behavior. You’d learn that it requires a token that must be passed as part of the request.

For the minimal word count of such an error message, this adds a tremendous amount of value to the API consumer.

What makes a good error code

Granted, oftentimes the error code you use is not as descriptive in its entirety as the 401 Unauthorized or 404 Not Found. So how can you make it more human friendly and empower a developer to troubleshoot the issue on their own?

Most important aspect of an error code is to give you context. That context will typically be passed in the response body that you could add.

While GET requests are quite self-explanatory, you either get the resource or not. PUT and POST requests are a bit more complicated since you’re changing data contained in the resource. Because of that, it’s natural that they will trigger more complex possible errors.

Adding a bit of a context to the error body response will go a long way. Let’s say that our standard 400 Bad Request could additionally provide some more information. We already know that the request has been malformed on a client side, but instead of scratching their head and squinting at the screen to decipher what went wrong, a developer can additionally be informed what the issue was.

The context goes a long way, and it needs to be valuable. Instead of writing what can’t be done, sometimes it’s more valuable to write what can be done instead. For instance, instead of writing a message:

Invalid file type

you could specify which file type should be used instead:

Only supports csv file types.

Error codes should be treated as documentation and should be maintained and updated as such, as part of your API governance process. Every time you change your API, consider whether the error code changes or evolves with it.

With that in mind, that same error code could be written with a maintenance hurdle in mind and instead say:

Only supports the following file types: csv.

That way, any time you add support for another family type, you could just add it to the list, as opposed to rewriting the entire error message.

Be short and sweet or refer to docs

It is important to remember a rule of thumb that you should not include too much information in an error code not to overwhelm a user.

One sentence is enough, and if you feel like adding more to it, refer your users to documentation where you can add more information. A good example is Stripe API reference where they include links to their error codes when describing what’s returned in a response, or Infobip API where there’s a link to the status and error code documentation within the response body, which I find more useful to an API consumer. What I find missing is the same practice with possible error messages.

Summing up

It is challenging to design a good error messaging practice that covers all possible scenarios, all devices, and all audiences. It’s important to use already standardized practices that already convey a lot of information, so for starters don’t hesitate to make use of the HTTP code groups.

Be open-minded about the user experience when thinking about error codes, they are an important part of it, and as mentioned before, a first way of opening a communication with your users.

--

--