It’s vital that you create a seamless customer experience for your APIs or platform when your customers are your developers
Background and Context
Integral has partnered with a number of companies to help develop APIs and SDKs as well as consume those APIs on behalf of their partners. As our clients develop new partnerships that consume their APIs, there is a more urgent need for a developer experience that is both cohesive and also scales with the growth of the partner ecosystem.
In this document, the Integral team has collected our opinions on the characteristics of an ideal developer ecosystem. These are our suggestions about what makes the developer experience in engaging with an API or SDK positive, productive, and rewarding. We provide these with the understanding that no one solution to API design is going to be perfect for every team, which is reflected in some of the references being contrary to one another.
Opportunity
As more consumer experiences leverage software to differentiate themselves, there is a growing need for developer enablement tools that help companies by providing platforms to enable non-differentiating tasks that allow them to focus on differentiating and getting to market quicker. Companies like AWS and Stripe are great examples of successful businesses that win by focusing heavily on creating an amazing developer experience.
Characteristics of an ideal developer experience
Much of what can make or break a great developer experience starts with the onboarding process. The Integral team considers the experience of getting started with a new API or SDK extremely important for critical to having a positive and productive experience with it. We group concerns around getting started into four main concerns: a narrative from setup to proficiency, quality of documentation, availability of sample code and tests, and explicit and easy-to-understand billing and usage policies.
Narrative
The best onboarding experiences make it easy and clear to understand the purpose of the service (and the APIs) as well as examples of what the API or service is not meant for.
We love it when tools provide an elaborate narrative or journey on the developer’s use of the system,
Examples:
➕Kubernetes’ Tutorials
The first thing you’ll see on the Kubernetes homepage is a button that says “Learn Kubernetes Basics,” which leads to a series of short articles followed by interactive tutorials which progress similarly to how one might expect to use it in production.
➕Twilio’s TwilioQuest
TwilioQuest gamifies the onboarding process. Users earn points as they are guided through exploring Twilio’s features and signing up for services. This makes it extremely easy to know what process is required to get the most value out of using Twilio.
While the thoroughness of Moment’s documentation is fantastic, the documentation provides little in the way of guidance of what functionality might be most useful to someone attempting to use it for the first time.
Documentation
Our engineers have a preference for a combination of
- simple documentation that makes it easy to get started and
- exhaustive documentation that covers any case they might encounter trying to use the software.
When possible, documentation that provides paths to both of these approaches is the best. Often this might take the form of a short tutorial to cover the most-used cases or common draws to working with an API or SDK, as well as access to in-depth technical documentation covering more obscure functionality to use as a reference when there are specific troubleshooting issues to address.
Examples:
➕Moment.js docs
As mentioned above, the Moment.js documentation is extremely thorough. Seemingly every function call with each of its possible parameters is demonstrated. It is also incredibly easy to understand in its presentation, making it a fantastic reference while using the library.
The Rust standard library is almost fully documented. Nearly every public function even includes usage examples, and these can be executed directly in the browser. There is possibly no simpler documentation than a 3-line runnable sample.
The JUnit 5 User Guide kicks off on its 3rd page with a table showing the 19 possible annotations it includes, followed by another page explaining how to combine and compose them. This is quite exhaustive, however, externalizing that table to another source for use as a reference when it is relevant and moving on to the next section showing the standard test setup would make the guide much simpler to understand.
Sample code; Sample Tests
Engineers appreciate code samples that are easy to pull and run themselves. Ideally, these are in multiple languages/platforms (iOS, Android, Python, Javascript, PHP)
Ideally, the sample code allows to get a “hello world” up quickly and is supported by documentation that allows for examples of more complex use cases.
Examples:
➕Android’s Samples Library
It’s probably not surprising that a project as big as Android has a pretty extensive sample project library. Aside from the already ample number of samples shipped with the SDK, the Samples library contains projects demonstrating the major features of the OS that are released with each update. They are searchable and can be filtered by technology and language.
In each of SendGrid’s SDKs, they reimplement the same functionality to cover many of their core features for each language they support. Because of this for many developers adding SendGrid to their dependencies is going to be as simple as copying and pasting.
Again, the Rust standard library provides sample tests for nearly every publically available function. This allows developers to easily compose new tests based on the proven functionality of the tests from the documentation.
Explicit billing and usage policies
Since API/platform consumption can have a significant impact on the company’s bottom line, having intuitive and explicit policies (ideally with examples) on pricing help during evaluation, integration, and operation.
Examples:
➕Stripe’s pricing policies
Stripe’s pricing policies are very easy to understand. Each product’s charges are easily understood in their abbreviated form, and even the detailed descriptions of those charges are straightforward and git on a single page.
The Google Maps Platform pricing is subdivided into a confusing number of categories — particularly the places API. Each call is priced differently, with a variance in how much data the call includes and how many sessions there are. Even if the pricing makes sense to someone using it, this information could be presented in a much more straightforward way.
Test Console/ Sandbox/ Playground
Having a sandbox environment with relevant test data or a “playground” to test out functionality is a highly effective approach to helping engineers with consuming data and interfacing with the APIs or SDKs provided by the platform provider.
Ideally, the test console and the documentation are cohesive experiences that best help the engineers with getting up and running.
Examples:
➕Twilio Homepage
Featured prominently on the Twilio homepage immediately below the hero images is a test console for using Twilio to send SMS messages. A developer can use this to get a sense of how the API works and the ease of integration immediately. This test console is important enough to Twilio that it is presented before the rest of the majority of marketing information on the home page.
➕Mercedes Connected Vehicle API
Mercedes provides a fully functional demo environment for its Connected Vehicle API populated with virtual Mercedes-Benz vehicles. Developers can develop and test against the demo API before ever integrating with a live Connected Vehicle API instance.
Support
Engineers expect responsive support from the service provider. These could range from Slack channels and Github issues to even AMAs on Reddit and other social media channels
Examples:
➕The Android Team
The Android team (and related projects, such as Android Studio) regularly participate in AMAs and other community support and feedback sessions. This kind of availability to the community makes iteration as the API or SDK develops more transparent and build trust that the API or SDK will continue to provide expanded value for developers into the future.
➕Spring Developers’ Gitter Chat
The Spring Developers run a Gitter chat instance where community members can chat directly with those contributing directly to the development of the Spring platform products. This level of support is helpful in providing developers with technical or misunderstanding of documentation issues in short order and can help the project development team get a very short feedback cycle about some of the most common issues involved in using their API or SDK.
Community
Developer community mediums such as live events (conferences, meetups, etc.), slack, and forums make it easy to interface with other partners in the ecosystem and provide a medium for the best partners to become evangelists of the system.
Examples:
➕Android-United Community
The Android United community on Slack provides an alternate slice of the people working with Android. Rather than providing a place for the Android Team to act as stewards of the project, Android United is an unaffiliated community run separately where platform developers and project contributors interact as relative equals.
Google Developer Groups are community groups run by developers who develop Google’s products and platforms. Google provides support for these groups with financial help and access to free content bundles and templates while still allowing the groups to operate independently as they see fit.
API Design
The API design is important not only in making an API at the bare minimum understandable and consumable but even more so in maintaining a positive developer experience. In our experience, the following characteristics of API design and technical architecture were observed to be most impactful to the developer experience:
1.) Consistent Design
- SDKs work similarly across languages (ex. RapidAPI)
- Domain Objects and Language reflected uniformly in code (Ubiquitous Language)
2.) Configure away from Code
- Design authentication and configuration to discourage committing secrets (ex. AWS)
3.) Minimize extended and control headers (like these)
4.) Discoverable
- Provide annotations of functions/endpoints and their models (such as Swagger)
- Provide references or locations to objects not uniquely identified
5.) Dependencies
- Make your SDK available where devs expect to find it: npm, maven, and other dependency management systems.
- Vendor your dependencies together in a single download or install
6.) Minimize the number of operations to get to the most functionality