What does it really mean to design a ‘consistent’ API?

Tanay Agrawal
Product Coalition
Published in
4 min readOct 30, 2021

--

The API economy is booming and more and more companies are launching API first platforms rather than products. With that comes the need to design API that is consistent, reliable, well-documented, and easy to understand. All of these words are overloaded and packed with a lot of meaning. In this blog article, I want to unpack the word consistent and dive deeper into what it really takes to build a consistent API experience.

Consistency is an important part of interface design — changing the rules for how something works is an unpleasant surprise and can lead to frustration. The cost of interface inconsistency is especially high in the API design space, where every inconsistency leads to more code being written to handle those one-off edge cases. This type of usability bug can really hurt the API developer experience.

Learning how to use an API really means learning the rules for using the interface. That includes every part of the API, from the message format and query parameters of the interface to the presentation style of the documentation. Every API design decision that you make establishes a rule that your users will learn.

Let’s jump right in!

#1 Consistent API Vocabulary

Resources, parameters, requests, responses, and their properties shape an API. So, a consistent API design should have a consistent vocabulary. For example, if you were building a user management module where accounts would be owned by a user, the accounts resource might contain a userId . If there is another resource in the API which owned by the same user, the reference of that user should be denoted by userId as well and not something like ownerId , user , memberId , owner , etc.

The same piece of information in different contexts must be represented with the same vocabulary.

You have to help the developers make the connection between them easily.

#2 Consistent Documentation

While interfacing with APIs in the past, I have seen instances where the error codes/messages might not have been documented, runtime behavior of the API is different from the documented behavior due to lagging updates, models and data structures in the API are inconsistent with the documentation. This happens when the engineering updates are not in sync with the API updates.

It is important to roll out updates to the API and the developer documentation in tandem.

The best way to achieve this is to automate parts of documentation generation with code releases.

#3 Predictable Data Types

I’ll use the same example as above where accounts have a number associated with them and denoted by an API field accountNumber . Ensure that the value of this field is passed as a Number/Integer instead of a String i.e. "accountNumber":8765423 and not "accountNumber":"8765423" .

And this pattern should be consistently followed across all fields of the API for all data types.

The developer should not have to rely on the documentation for every single thing while using the API.

Predictability in the API design helps improve the experience of integrating with the API for the developer.

#4 Predictable Data Structures

Let’s take an example — If there is an API field which is denoted by a plural field name and contains array or list as its value, for example:

"accounts": []

The expectation of the developer now would be to see an array or list for every field name that is plural.

Predictable data structures help reduce the number of errors that a developer has to encounter during integration.

If the pattern is not followed consistently, the developer will consistently encounter errors while parsing the API response and will lead to a frustrating integration experience.

#5 Consistent URL Pattern

Do not add extra layers hierarchy to your endpoint URLs and keep them consistent with all the other endpoint URLs.

For example: The /accounts/{id} and /accounts/blocked/{id} URLs don’t have the same organization. The /accounts/blocked/{id} URL introduces an unexpected level between the collection name and resource ID, making the URL harder to understand. You could potentially use /accounts/{id}?status=blocked as a filter or introduce a new API endpoint such as /blocked_accounts/{id}.

#6 Consistent Query Controls

Controls for querying, filtering, and pagination should be consistent across all API endpoints.

If there is an endpoint which lets you query an account based on its status like

GET /accounts?status=[active,inactive,blocked]

Then any other API endpoint which queries a resource based on multiple values of a field should be queried in the same way. Inconsistencies with things like query controls arise when incremental improvements are made to different API endpoints to support additional features but similar updates are not applied across all API endpoints.

#7 Consistent API Methods

Your API should use similar methods to perform similar type of operations.

If there is an endpoint that uses the POST method to create and update resources then all endpoints should follow the similar pattern. Similarly, if an endpoint uses POST method to create a resource and PUT method to update a resource, then all endpoints should follow that pattern.

#8 Consistent Error Codes and Messages

Does your API throw the same error code and messages for similar behavior for different endpoints? For example, if you are throwing an error for Invalid Request Parameters , which is one of the most common API errors, then you must not only use the same error code but also the same message across all endpoints.

Do not assume how a developer will consume the API.

There can be developers who are using error messages to parse the error even though it might not be the best coding practice.

What are some of the other best practices that you have seen in the API design that lead to consistency? Feel free to comment it below to share it with the broader audience.

--

--