Creating usable APIs
Usability is about the balance between exposing too many controls and too few. This is a very tricky thing to get right. On the extremes, it is obvious when things are out of balance. For example, the Metropolitan Museum of Art has an API that gives you information about various art objects in their possession. If all the API did was provide one call that gave you back all that data, it would be providing too few controls. You would need to do so much work after getting the information that you might as well not use the API at all. However, if, on the other hand, the API gave you a separate endpoint for every piece of metadata in the system, you would have trouble finding the endpoint that gave you the particular information you wanted. You would need to comprehend too much in order to use the system.
You need to think carefully about this if you want to get the balance right. Make sure your API is providing users with specific enough data for the things they need (this is where knowing the purpose comes in handy) without overwhelming them. In other words, keep it as simple as possible.
Usable API structure
One thing that can help create a usable API is to use only nouns as endpoints. If you want users to be able to understand your API, structure it according to the objects in your system. For example, if you want to let API users get information about the students in a learning system, don’t create an endpoint called /getAllStudents
. Create one called /students
and call it with the GET
method. One of the reasons for doing this has to do with creating new students. If your endpoint is called /students
, you can easily call it with a POST
method to create a new student. However, if you had named it /getAllStudents
, it would feel very unnatural to call that with a method to create new items. You can think about it in terms of saying it out loud. Saying “I want to create a new student object” sounds natural, but saying “I want to create a get all student object” does not.
Creating endpoints based on nouns will also help you more naturally structure your data. For example, if you have /students
as an endpoint, you can easily add an endpoint for each student at /students/{studentId}
. This kind of categorization structure is another helpful API design principle to keep in mind.
Creating a structure like this maps the layout of the API to the kinds of things that the API user needs information about. This makes it much easier to know where to find the relevant information.
A structure like this works nicely, but does it really match up with how users will interact with the API? If I am looking for information about a student, am I going to know what their ID is in the API? Perhaps, but more likely I will know something like their name. So, should we modify the structure to have an additional endpoint like /students/name
? But what if we are looking at all the students of a certain age? Should we add another endpoint, /students/age
? You can see where I am going with this. It can get messy quickly.
This is where query parameters are helpful. A query parameter is a way of getting some subset of the category based on a property that it has. So, in the examples that I gave earlier, instead of making “name” and “age” endpoints under the “students” category, we could just create query parameters. We would call /students?name='JimJones'
or /students?age=25
. Query parameters help keep the endpoints simple and logical but still give the users the flexibility to get the information they are interested in effectively.
Good error messages
A usable API helps the users when they make mistakes. This means that you give them the correct HTTP codes when responding to a call. If the request is badly formatted, the API should return a 400 error code. I won’t list all the HTTP codes here as they are easily searchable online, but ensuring that your API is returning codes that make sense for the kind of response you are getting is an important quality consideration.
In addition to the HTTP codes, some APIs may return messages that let you know what possible steps you can take to correct this issue. This can be very helpful, although you will want to be careful that you don’t reveal too much information to those who might be bad actors.