Build Consistent and Delightful SDKs for Your APIs

Developer Advocate Lorna Mitchell shares her thoughts on what it takes to generate SDKs that developers will love.

As a Developer Advocate for an API provider, I am passionate about improving the Developer Experience for anyone that wants to use our APIs. One excellent way to make it easier for any developer to integrate your API into their platforms is to provide an SDK (Software Development Kit) for their tech stack.

An SDK is an installable library (ours are open-source) that any developer can use in their application. By providing a tech-stack-appropriate library, it becomes much simpler for a developer to integrate your API in ways that are familiar and well-integrated with their existing toolchain. For example, it may use conventions already common practice in a particular tech stack or integrate well with the mainstream tools to provide autocomplete or other conveniences.

Read more about the difference between an API and an SDK in this article: What is the Difference Between an API and an SDK?

Good SDKs save both time and cognitive effort when integrating with a provider’s API. Great APIs are consistent throughout and a delight to use, offering value beyond simply calling API endpoints from the desired tech stack. So, how do we inspire consistent, delightful SDKs?

Watch Lorna Mitchell speak on this topic at ASC 2020:

Achieving Consistency

Creating a consistent, reliable experience in an SDK takes many forms. It’s crucial to have common patterns across the different functions so that, for example, authentication is always handled the same way, or data is always returned in a predictable fashion. It’s also important that the relationship to the API is as tight as it can be. Every API parameter and response field should be included so that the API integration is accurate and complete. Few things are more annoying than finding some fields, but not the one you need at that moment.

At Vonage, we are greatly assisted by having not just detailed and accurate documentation for all our APIs, but also by having OpenAPI definitions for each one. In fact, those detailed and accurate API descriptions drive the detailed and accurate API documentation.

OpenAPI is designed to be readable by machines; it’s a very descriptive and somewhat verbose (JSON or YAML) format. Each endpoint is described, along with the data it expects to receive, and the responses that might be returned. Each field in the request and response has information about its desired type and format, which is useful. The magic is really in the description and especially the examples that apply to each field and to whole requests and responses. When I look at an OpenAPI description, I can clearly imagine the API behind it. It’s no wonder why so many organizations gravitate toward OpenAPI as a source format for API documentation.

What’s descriptive enough for excellent API documentation is also a pretty good starting point for a code generator tool. A code generator can understand how to use an API and output a decent interface in the chosen tech stack. There are many auto-generation tools around that support different tech stacks to different extents, but I’ve been using OpenAPI generator, and it has worked perfectly well. The generator accepts the OpenAPI description as input and outputs a whole library. The best part? The README includes an example of how to use what was generated!

Generating code produces accurate and precise integration points for the API. If the API changes, perhaps because a new feature is added, the code can be regenerated to include the update. This sounds great, right? Well… code written by machines ends up looking exactly like you would expect — it’s not much fun to use at all.

Inspiring Delight

To give developers value beyond what they could achieve by generating the code themselves, we need to think beyond what a machine can do with an OpenAPI file. (aside: you are publishing your OpenAPI definitions publicly for your developer communities, right?). Like when developing any other type of software, an excellent starting point is to put yourself in the user’s shoes.

What is the context of that individual? What is their goal, and what is the most helpful way to assist them toward it? I often rely on the “principle of least surprise” at this stage as well. There is no point in creating a genuinely innovative approach to initialization if every developer that comes to use it tries, fails, and goes in search of either your documentation or your competitor.

Delight is very much in the eye of the beholder, or at least in their completed work tasks. By producing an intentional and thoughtful developer experience in your SDKs, developers will be pleasantly surprised at their progress — that positive buzz stays with them.

Where Machine-Generated Code and Developer Experiences Collide

So far I’ve talked about the clinically accurate but joyless generated code, and about delightful user experiences where a developer can instinctively find their way through the task at hand. These two things are not like one another, and you may be wondering if bringing them together is going to be a monumental task.

My experience is that with clear architecture, the two pieces of this particular puzzle can work together in harmony. By keeping the generated code isolated and unchanged, we ensure its future-proofing since we can regenerate and replace it at any time. The isolation is also in the interest of our soon-to-be-delighted humans, who won’t be encountering the sharp edges of code written by a machine.

In a separate user-facing layer, we can quickly structure that ideal user interface that we had in mind and then add some lightweight “glue” code to call through to the back end that handles all the integration detail.

Sometimes, this setup will require extra work to get things lined up to cover the quirks of the API and provide a quality Developer Experience. When I get tangled up in those intensive sections, I think about whether I would rather solve this knotty problem myself, or require every developer to work around this themselves. When you put it like that, I’m positively pleased to be solving this problem once, right now.

Build Delightful SDKs

A robust and consistent API is a strong enabler for developer communities, especially if designed appropriately for the tech stack and predictable in the way it installs and operates. An SDK is more than a set of API-calling wrapper code, where each endpoint does work, but may not take too much notice of the other features in the same library. By taking an approach that comes in from both sides — accurate API-driven integrations at one side and user-centric interface design on the other — you will create delightful SDKs that your developers will recommend to their peers and return to time and time again.