The dummies guide to API design


We write APIs all the time. Ever since the first programmer moved past hello world, she probably wrote a function to divvy up her program.

From functions within programs, COM/DCOM, CORBA, RPC, binary messages within a protocol, to rest APIs and finally back to things like gRPC, APIS change names, move to different programming languages, work across process, machine, and network boundaries, yet some principles remain the same.

Here are some guidelines that we learnt the hard way and apply along the way. All of them are obvious, but it is worthwhile to recollect each of them as we begin yet another API.

It's all about the caller

The purpose of an API is to do some task for an external part of the same program, or a different program. It should be easy for the caller to understand the functionality provided by the API, the correct way to invoke it, the type of exceptions returned and how to handle them, and any trade-offs in terms of performance, design etc

Remember, the time spent on the API is multiplied by the number of users of the API. If a million users use your API, and you can shave off one hour from the learning of it, that is one million hours saved!


Document and specify it well

The documentation should be more detailed as the circle of users widen. If an API is being used in the same team, a simple swagger documentation may be sufficient. When it is going to be used by external teams, or even by other companies, then the document should be detailed and intricate.

It should be possible to traverse the document in multiple ways. An experienced programmer or one evaluating the suitability for a project would like an overview of the possibilities, the aim, design, performance etc of the API

A person who is going to implement a solution using the API would be more interested in the individual API calls, the input, output parameters etc

Some other people may be interested in the design decisions, the architecture etc. Others in the viablity of the company behind it, the support, longevity etc.

Write accordingly!

Address all cases - happy paths and edge cases

Many a time, APIs address only the obvious happy case. Instead the API should address all the possible use cases. Each use case is the result of a combination of the input parameters.

Look at all the permutations and combinations.

It is not as easy as it seems. Take an imaginary example of a ticket booking system. Suppose an infant has to accompanied by adults. In this case, check for the presence of an infant in all API calls. What if there is another rule that a pet cannot be in the same booking as an infant? What if drinks are not available on a weekday? Different charges for happy hours?

This also leads us to the next rule.

Minimize the number of parameters

What is the least number of parameters with which the job can be done? It sounds a simple and obvious thing to do, but it is surprising how many times it is omitted.

As a thumb rule, first prepare a comprehensive list. Then start removing parameters and see if the api can still work. If it does, it can be removed.

Sometimes an API call is a subsequent call. For example, consider a ticket booking system. An updateBooking API is a subsequent call and will operate on a booking that has been created by an earlier API call to createBooking.

In this case, only the initial booking id, and the changed parameters are required (say the name of the passenger). There is no need to expect, the date of the booking, the amount paid etc. It is already with us.

Sometimes people let these remain. It is dangerous. What if the date sent by the caller is different from what is present locally? What if the amount is different? What should the API do?

Where possible accept and return integer parameters instead of strings

It is always better to accept an input parameter as an integer rather than a string. Not just for consumption of less storage space, it is also easier for validations.

Take timezone as example. It can be sent as an integer offset, or as a string. It is easier to compare and validate an integer offset. The integer does not change based on the language/locale settings of the caller. But, on the other hand a single offset may correspond to different geographies. So, choose the trade offs wisely.

Choose the signature wisely

- The name is important, it tells us what the API does

- The parameters to the API tell us what it does, so choose those wisely

- Do not expect as parameters, what can be obtained locally or internally

Choose the result structure wisely

- Always include an integer code. Document what each code means

- Do not define all codes in a single file. This becomes large and unweildy.

- An extra error message can be good but do not expect that the caller will use it. What if they are running a different language?

Do very meticulous checking of input parameters

- First validate all the input parameters. If any of them are not in expected format, raise a very specific error message

- Based on some rules, some combination of values may be invalid. Raise an error with a specific error code if this happens. An example could be end date cannot be earlier than start date for a ticket booking.

- Only if validation succeeds should the api proceed with its work

Granularity of APIs

- We could give a single API to do everything, or make separate APIs for each sub-task

- For example, in a ticket booking system, we could give a single API called booking, and have a type parameter to distinguish between, creating a booking, cancelling a booking, or updating a booking. Alternatively, we can have apis called createBooking, cancelBooking, updateBooking.

- I prefer the second style. It is auto-documenting, allowing the api reader to immediately understand the different functionalities the API provides, we can have a narrower set of paramenters and validations, and hopefully reduce the code base and causes for exceptions too

Provide a simple API to chain common multiple complex flows.

This is similar to the Facade design pattern. In cases where a common use case involves invoking multiple APIs one after the other, it may be simpler to provide a simple API that performs these apis/actions in sequence and then returns an appropriate value

Long running operations. Many a time, an API may be performing a long task. In such cases, it is advisable to return an ACCEPTED message immediately , and then email the results of the API or invoke a callback webhook.

Version the APIS

This is very important and allows you to do the next point

Lastly, leave room for evolution


要查看或添加评论,请登录

MetaDesign Software Services Pvt Ltd的更多文章

社区洞察

其他会员也浏览了