Skip to main content

5 posts tagged with "Best Practices"

View All Tags
← Back to the liblab blog

Do you wish to increase the engagement of users with your API? Or are you perhaps afraid that your users will stop using your API because it’s too boring? Too... simple? Too user-friendly?

Well, prepare yourself for a paradigm shift. In this blog post, we will explore how to utilize some well known programming techniques and showcase our skills to make your OpenAPI Spec more exciting.

Tip 1: Ensure your paths and operationIds are unique

It is clear that paths and operationIds must be unique - at all costs.

Luckily, developers have already come up with genius techniques of ensuring uniqueness so it only remains on us to employ these techniques. For paths we can use an auto-increment integer. This means that our first path should be /1, second /2 and so on.

💡 Pro tip: You might be tempted to track the last number used, but isn’t it more exciting for your users to wonder what happened to missing path /5?

And to show how much we know about programming we will use another technique - UUIDs - for operationIds. UUIDs might be long, barely readable strings of characters that are incomprehensible to humans, but what is truly more important - uniqueness or understandability? Although they are very complex, they ensure that no two operationIds are ever the same, thus eliminating any possibility of confusion.

paths:
# Good
/1:
get:
operationId: 018e3981-3250-701c-b27b-1f5db826f2b0
# Bad - possible collisions
/pets:
get:
operationId: listPets

Tip 2: Use consistent status codes

You’ve heard it before - being consistent goes a long way. The hardest choice is what this consistency should be. We should be grateful that this is a very simple choice when it comes to status codes.

In this stressful modern day, nobody will like you if you’re too intense. Instead, relax! Cool people are always OK with whatever happens. Why should your API be any different?

That’s why you should return a 200 status code no matter what happens.

There has been an unexpected error? Don’t panic, say OK. After all, is there any better feeling than when there is something obviously wrong, but when your ask your partner, they say everything is OK?

responses:
- 200:
content:
application/json:
schema:
type: string
enum:
- OK

Tip 3: Increase engagement and security through obscurity

Want to increase the engagement with your API and increase security at the same time in just one simple step?

Why reveal what an endpoint does? If this remains hidden - malicious users can’t harm you - you can’t hack what you don’t know. What data does it return, you ask? Who knows? Who cares? That's the charm of it. The vaguer your descriptions, the more precious hours your fellow developers will spend learning your API - and isn't that what the spirit of programming is all about? They will try out many endpoints in attempt to find what they need instead of calling only the one they need.

Engagement with your API will skyrocket 🚀

# Good
description: Returns data
# Bad - too revealing
description: Gets a Pet by ID

Tip 4: Use query parameters

In the intricate dance of confusion that is your Open API, one must not forget the elusive query parameters. The key here is secrecy. Never, under any circumstances whatsoever, should you reveal your query parameters. Let them be like a hidden treasure, waiting for the bravest of developers to uncover. How will they discover them? Well brute force, of course! They can try any and every possible query parameter, until they find what they are looking for. The fact that there are query parameters is all the information they need. What are these parameters? What is their purpose? These are mysteries best left unsolved. After all, life is more exciting when it's full of surprises.

parameters:
- name: "?"
in: query

Tip 5: Keep documentation to a minimum

If you want to allow only the most worthy developers to use your API - follow this tip.

Documentation, the ultimate spoon-feeding tool for developers. To truly test their mettle, provide the bare minimum. The less guidance they have, the more they'll learn - or so you can tell yourself as you watch them grow in order to navigate your API.

After all, why would they waste countless hours reading documentation - when they can immediately just start using your API? Don’t obstruct them in this quest - you are either with them or against them.

Here's an example of how to keep your documentation to a minimum:

Tying it all together

So we’ve seen some very good suggestions, but how does it all work together?

Best if we see it in example:

paths:
/1:
get:
operationId: 018e3981-3250-701c-b27b-1f5db826f2b0
description: Returns data
responses:
- 200:
content:
application/json:
schema:
type: string
enum:
- OK
parameters:
- name: "?"
in: query
...

Conclusion

In conclusion, a truly exceptional Open API spec is not one that is easy to understand and use, but one that leaves developers scratching their heads, questioning their decision to be a programmer.

Follow these tips, and you too can ascend to the ranks of the masters of the mysterious, the ambiguous, the truly incomprehensible Open API. Remember, confusion is the path to enlightenment... or at least, that's what I whisper to myself as I debug my code at the ungodly hour of 3am.

https://www.notion.so/icons/theatre_lightgray.svg Disclaimer: this post was reviewed and approved by the April fools committee.

← Back to the liblab blog

As an experienced engineer, I've learned the value of simplicity and ease of getting things done. Life is too short to spend on writing boilerplate code, or dealing with the complexities of lowest common denominator tooling. I want to focus on the business problem I'm trying to solve, not the plumbing.

This is why I'm always a fan of a well-crafted SDK, a tool that makes it easy to use a service or API. In this post we look at the process of creating SDKs, from concept to creation, and show how you can automate the process using liblab.

What is an SDK?

Let's start with the basic question - what is an SDK? An SDK, short for Software Development Kit, is a set of tools written in one or more programming languages that make it easier to use a service or API. For this post, I will focus on SDKs for APIs, providing a wrapper around the direct REST calls that a user might make against an API.

An SDK is a great abstraction layer. It is written in the language the developer uses, and provides language idiomatic ways to call the API, managing all the hard stuff for you such as the HTTP calls, the mapping of JSON to objects, authentication, retries, and so on.

A good SDK drastically reduces the code you have to write.

The importance of an SDK

SDKs are important to improve the developer experience of using your service or API. They allow your users to focus on the business problem they are trying to solve, rather than the plumbing of calling your API. This is just as important for public facing APIs from SaaS companies, as it is for internal APIs used by your own developers from your corporate microservices.

Some benefits include:

  1. Intellisense and code completion - you can see the methods and properties available to you, and the parameters they take in your IDE.
  2. Authentication - the SDK can handle the authentication process for you, so you don't have to worry about it.
  3. Built in best practices - you can embed best practices inside the SDK, such as retry logic, so that if a call fails due to rate limiting, the SDK will automatically retry the call after a short delay.

To learn more about the comparison between SDKs and calling APIs directly, check out our post SDK vs API, key distinctions.

How to Build an SDK

Creating SDKs is a multi-step process, and is very time consuming. Not only do you need to design and build the SDK, but you also will want to create SDKs in multiple languages to support your users needs.

This might be less important if you are building SDKs for internal APIs and you only use a single language - for example if you are a Java shop you may only need a Java SDK. However, if you are building a public facing API, you will want to support as many programming languages as possible, so that your users can use the language they are most comfortable with. You will probably want a TypeScript SDK or JavaScript SDK, a Python SDK, a C# SDK, a Java SDK, and so on depending on the programming language priorities of your users.

The steps you would take are:

  1. Design your SDK
  2. Build your SDK
  3. Document your SDK
  4. Test your SDK
  5. Publish your SDK
  6. Maintain your SDK

1. Design your SDK

The first step is to design the SDK. A typical pattern is to mimic the API surface, providing functions that act like your API endpoints. This is a great way to build an SDK - it means your documentation and other user guides can be essentially the same for your API and SDKs, with just different sample code to use the SDK rather than make an API call.

API specification

To do this you will need to know how your API works, which is why it is important that your API has documentation, ideally an API specification such as an OpenAPI spec. Some API designers will start from an OpenAPI spec, others will start with code and autogenerate the OpenAPI spec from that code. Either way, you need to have a good understanding of your API before you can start to design your SDK.

The act of designing your SDK can also be a great way to validate that you have a good, clean API design. If you find that your SDK is hard to design, or that you have to do a lot of work to make it easy to use, then this is a good sign that your API needs improvement. For some tips, check out our post on why your OpenAPI spec sucks.

Paths and components

OpenAPI specs have 2 sections that make designing your SDK easier - paths and components. The paths section defines the endpoints of your API, and the components section defines reusable components, such as schemas for request and response bodies, or security schemes.

You want to use components as much as possible to make it easier to understand the data that is being passed around. Using components also helps you to them as much as possible between endpoints.

For example, if you have an endpoint that returns a single user, it is cleaner to have that user defined as a components/schema/user object. You can then reference that in the endpoint that gets a single user, and wrap it as an array for an endpoint that gets multiple users.

From API spec to an SDK design

Once you have your API spec, you can start to design your SDK. A good design is to provide objects that wrap the requests and responses for your API endpoints, and methods that call the API endpoints.

You will need to consider:

  • What objects will encapsulate the components
  • How paths will be grouped and wrapped as methods
  • The interface to handle authentication
  • Each SDK language will have different idioms, libraries and best practices. You will need to decide how to handle these differences. This might be a challenge if you are not familiar with the language.
  • How to handle best practices such as retries. Do you implement this yourself, or use a library?
  • Naming conventions. It is important to create SDKs that use idiomatic code for the SDK language - for example, if you are building a Python SDK, you want to use Python idioms such as using snake_case for method names, and PascalCase for class names, whereas TypeScript would use camelCase for method names.

2. Build your SDK

After you have designed your SDK, you can start to build the code implementation. This is a manual process, and is very time consuming, especially if you have SDKs in multiple languages.

Components

First you want to create objects to wrap the requests and responses for your API endpoints, defined in the components/schemas section of your OpenAPI spec. These objects are often referred to as models or DTOs (data transformation objects). These are usually 'simple' objects that have properties that map to the properties on the schema, and allow you to write JSON mapping code (or use a built in library) to automatically map the JSON to the object.

Sometimes the objects can be more complex. For example if your API specification defines an anyOf or oneOf - an endpoint that can return one of a range of possible types. Some languages can support this through a union type, others cannot, so you will need to decide how to handle these types. Remember, you need to do this for every SDK language you want to support.

SDK methods

Once you have your models, you can start to build the SDK methods that call your API endpoints. These functions can take models as parameters, and return the models as responses.

You will need to handle making HTTP requests, and the mapping of JSON to objects. You will also need to handle the authentication process, and any other best practices you want to build in such as persisting the HTTP connection, retries and logging.

These methods might also need parameters to match the parameters for the endpoint - both path parameters and query parameters.

For example, if the endpoint is GET /llama/{id} with the Id as a path parameter, you might have a method like this:

class Llama(BaseService):
def get_llama(self, id: int) -> Llama:

where the llama Id becomes a method parameter.

Grouping methods

A good practice is to group these functions into service classes. You might want to do it based off the endpoint - for example having the GET, POST, and PUT methods for a single endpoint in a single class.

API specifications can also define groupings of endpoints, such as OpenAPI tags, so you might want to group your functions based on these tags. You know your API, so pick a technique that works for you.

As you build these methods, you should abstract out as much logic as possible into base service classes, or helper methods. For example, you might want to abstract out the HTTP request logic, the JSON mapping logic, the authentication logic, and the retry logic. This way you can define it once, and share the logic with all your service methods.

SDK client

Finally you will want to put some kind of wrapper object, usually referred to as an SDK client, around the endpoints. This will be the single place to surface authentication, setting different URLs if you have a multi-tenant API, or support different API regions or environments. This is your users entry point to the SDK.

class Llamastore:
def __init__(self, access_token="", environment=Environment.DEFAULT) -> None:
# The llama service
self.llama_service = LlamaService(access_token)

# Set a different URL for different environments
def set_base_url(self, url: str) -> None:

# Set the API access token
def set_access_token(self, token: str) -> None:

3. Document your SDK

An SDK is only as good as its SDK documentation. As you create SDKs, you will also need to write documentation that shows how to install, configure, and use the SDK. You will need to keep the documentation in sync with the SDK, and update it as the SDK evolves. This will then need to be published to a documentation web page, or included in the SDK package.

OpenAPI specs support inline documentation, from descriptions of paths and components, to examples of parameters and responses. This is a great way to document your API, and you can use this to generate proper documentation for your users.

4. Test your SDK

Once your SDK is built, you need to ensure that it works as expected. This means writing unit tests that verify:

  • The JSON expected by and returned by your API can map to the objects you have created
  • The HTTP requests are being made correctly by the SDK methods to the right endpoints
  • Authentication is implemented correctly
  • The best practices such as retries work as expected

You should write unit tests that mock the real endpoint, as well as integration tests that call a real endpoint in a sandbox or other test environment.

5. Publish your SDK

Your finished SDK needs to be in the hands of your users. This means publishing it to a package manager, such as npm for JavaScript, or PyPi for Python.

For every SDK language you will need to create the relevant package manifest, with links to your SDK documentation, and publish it to the package manager. For internal SDKs, you might want to publish it to a private package manager, such as GitHub packages, or a private npm registry.

6. Maintain your SDK

It's not enough to just create SDKs once. As your API evolves, you need to update your both your SDK and SDK documentation to reflect the changes. This is a manual process, and is very time consuming, especially if you have SDKs in multiple languages.

Your users will expect your SDK to be in sync with your API, ideally releasing new features to your SDK as soon as they are released to the API. As well as the engineering effort to update the SDK and SDK documentation, you also need to ensure that during SDK development, your internal processes track API updates, create tickets for the work to update the SDK, and ensure that the SDK is released at the same time as the API.

Every new endpoint would mean a new SDK method, or a new class depending on how you have structured your SDK. Every new schema is a new model class. Every change to an existing endpoint or schema is a change to the existing SDK method or model class. You may also need to update any best practices, such as supporting new authentication schemes, or adding new retry logic.

You will also need to track breaking changes, and update your SDK version as appropriate - a major version bump for breaking changes, a minor version bump for new features, and a patch version bump for bug fixes.

Best practices for building the perfect SDK

When building an SDK, there are a number of best practices you should follow to ensure that your SDK is easy to use, and works well for your users.

  • Provide good documentation and examples - your API spec should be full of well written descriptions, examples, and other documentation that can be ported to your SDK. This will make it easier for your users to get started quickly.
  • Use idiomatic code - your SDK should use the idioms of the language you are building the SDK for. It should match the language's naming conventions, use standard libraries, and follow the language's best practices. For example, using requests in Python, making all your C# methods async, using TypeScript's Promise for asynchronous methods, and so on.
  • Embed security best practices - take advantage of security best practices, from using the latest version of any dependencies with mechanisms to monitor for patches and provide updates, to using the latest security protocols and libraries.
  • Handle authentication - your SDK should handle authentication for your users. This might be as simple as providing a method to set an API key, or as complex as handling OAuth2. You should also provide a way to handle different environments, such as development, staging, and production.

Automating the SDK build with liblab

Creating SDKs is a lot of work that only gets bigger as your API grows, or you want to support more languages. This is where automation is your friend. liblab is a tool that can take your API specification, such as an OpenAPI spec, and autogenerate SDKs for you in multiple languages.

The SDK generation process will generate the models and service classes for you, with all the required mapping code. It will also generate your best practices such as authentication and retries, and you can configure these via a configuration file. You can also write code that is injected into the API lifecycle to add additional functionality, such as logging or custom authentication with the liblab hooks feature.

The flow for using liblab - an api spec and config file goes in, and an SDK and documentation comes out. The flow for using liblab - an api spec and config file goes in, and an SDK and documentation comes out.

SDK generation is fast! A typical developer flow is to spend a few hours generating SDKs the first time as you configure the generation process to meet your needs. This is an iterative cycle of generate, check, adjust the configuration, then regenerate. Once you have your configuration the way you need, your SDKs are generated in seconds.

Adding more SDK languages is also fast - you add the new language to the configuration file, and regenerate.

liblab can also help you to keep your SDKs in sync with your API. As your API is updated, your SDK can be re-generated to match. For example, if your API spec lives in a git repository, you can set up a GitHub action to detect any changes, and regenerate your SDK, publishing the new SDK source code to your SDK repositories.

Finally liblab can generate your SDK documentation for you, with full code examples and all the documentation you need to get started. This is taken from your API specification, so is always in sync with your API.

creenshot from liblab UI indicating list pets and query attributes with an example of an SDK code and response fields creenshot from liblab UI indicating list pets and query attributes with an example of an SDK code and response fields

Conclusion

SDKs are a powerful way to improve the developer experience of your API. They come with a cost - the amount of work needed to generate them. This is why automation is so important. With liblab you can automate the process of generating SDKs, and keep them in sync with your API as it evolves.

Sign up for liblab today and start generating SDKs for your APIs in minutes.

← Back to the liblab blog

API's need to change over time. Features are added, bugs are fixed, and changes are made. How can you introduce and track changes without breaking client applications? API versioning is the answer. By versioning your API, you work towards building a robust and scalable product.

What is API versioning?

Versioning an API is the process that allows tracking changes and managing the API's various iterations. Essentially, versioning allows you to create multiple API versions that that coexist but operate independently of each other. That way new features can be added, updates can be made, and old features can be removed with minimal disruption of service to the user.

Why is API versioning important?

Proper versioning is a crucial step to keep projects flexible and ensure compatibility with existing and new tools. Without proper versioning, modifications to the API could cause unexpected errors and result in disruptions for the client. You’ll likely need to make changes to your API over time, so it’s a good idea to analyze whether or not implementing proper API versioning from the start would be a good idea.

A good API versioning strategy not only helps to make projects more flexible, but it can also make projects compatible with more tools and protect backwards compatibility. Over the course of the project, it can also help lower the cost of introducing new features and help communicate changes clearly to the users. Since each API version number gets its own release notes, migration guides, and updated documentation, this strategy promotes a trusting relationship with the user.

When should you version an API?

If you're going to introduce major changes to the API, it would be a good idea to consider adopting an API versioning strategy. As different versions become available, users can incrementally opt-in to new features at their own pace. Versioning can also facilitate making security updates without forcing API users into upgrades that would require downtime to incorporate.

In a situation where the API will support multiple client platforms, API versioning will allow the user to stick with their platform's SDK without being worried about updates for other platforms, and that's something we can help with — liblab offers an robust and comprehensive suite of tools to generate SDKs tailored to your API.

When should you not version an API?

Versioning isn't the best solution for every situation, though. Developing a full versioning strategy for minor updates or bug fixes will more likely add confusion than benefits. Also, in situations where there is only one or two users, such as an API that will only be used internally, it's probably more practical to just update both server and client at once. Same goes if you’re introducing a non-breaking or temporary change, or something on a branch that won't impact any clients.

How to do API versioning

If you think API versioning will be a good fit, you need to understand how to adapt API versioning to suit your needs. One of the first things you’ll want to consider is how you want to label your versioning. There’s a few options:

  1. Semantic Versioning (commonly referred to as SemVer) follows a MAJOR.MINOR.PATCH format. For more information on semantic versioning, semver.org is a good resource. It’s helpful for tracking backward-compatible changes, functionality, and bug fixes. Each of the major breaking changes are incremented as a new major version number, while backward-compatible additions and bug fixes are each just a minor version number.

  2. Date-based versioning tags make every API version number the date it was released, which might be useful in some situations where a chronological sequence of releases is more relevant than semantic clarity.

  3. Endpoint-based versioning may be helpful in limited situations where the scope of the version will only affect certain endpoints with independent resources.

There isn’t consensus on the “best” approach, it really depends on what information will help you better track the changes made to the API. Analyzing your needs and desired results will help you decide which system will work best for you.

Types of API versioning

Next, you need to decide how the user specifies which API version they want to use. Here are some options:

Versioning TypeBasicsExamplePositivesNegatives
URI VersioningThe version numbers are incorporated into a URL pathhttp://www.example.com/api/1/productsEasy to understand and implement Clearly separated API versionsCan become cluttered. Not recommended by REST architecture
Query ParameterThe version number is appended as a query parameter in the API endpointhttp://www.example.com/api/products?version=1Clear separation of API versions Easy to implementLess intuitive for API consumers. Can result in long cluttered URLs
Header BasedThe version number is a specific and unique header fieldcurl -H “Accepts-version: 1.0” <http://www.example.com/api/products>Follows REST principles Keeps URI focused on the resourcesLess intuitive. More effort is needed to check API request
Content NegotiationThe version is based on the representational state or media typecurl -H “Accept: application/vnd.xm.device+json; version=1” <http://www.example.com/api/products>Smaller footprint. No need for URI routing rules. Versions resource representations instead of entire APILess accessible for testing and exploring via browser

Again, each of these techniques have different objectives and advantages, so your specific project requirements should determine which technique is the best for you.

How to build an API versioning strategy

Once you’ve planned out what methods and techniques will best suit your constraints and objectives, you’re ready to formulate your strategy according to API versioning best practices. You’ll need to assess the project scope and define what your versioning policy will be. REST (Representational State Transfer) is a popular API architecture for building web services in which resources are accessed via standard HTTP methods. Using versioning with a REST API allows the developer to add new features to the API, fix bugs, and remove old functionality without breaking anything for the API consumers. If you’re building a REST API, there are a few principles regarding versioning that you might want to keep in mind. Here are some of those recommended api versioning strategies:

1. Communicate changes clearly

The whole point of using a REST API is so that there’s no confusion between client and server about where to access resources. That completely breaks down if you haven’t clearly communicated to the API consumers when things change on the server. You’ll need to consider release notes, migration guides, and updated API documentation to keep everyone on the same page. Perhaps it’d even be worth considering a longer time table to give users enough time to prepare for and implement updates.

2. Use Semantic Versioning

We talked about some of the other options, but semantic versioning is best in line with REST principles. Why? Because REST APIs are stateless; endpoints aren’t affected by outside constraints and function independently from one another. They (in theory, unless you really need it) shouldn’t be fixed to anything in the real world affecting their output, like the date of the most recent new version. Setting up SemVer isolates the endpoints from anything resembling state even further.

3. Maintain backwards compatibility when possible

REST APIs are uniform and consistent. In an ideal world, there would never be any breaking changes. In reality, that’s difficult to implement long-term, but always lean on the side of backwards compatibility. For example, new endpoint parameters should have default values. New features should get their own new endpoints and their own new version. Removing existing fields from API responses is also frowned upon for this reason, especially if you have a good deprecation strategy.

4. Deprecate old versions gradually

What does a good deprecation strategy look like? A clear timeline. Support old versions during the deprecation period and make sure that deprecation endpoints are recorded clearly in the API documentation. Also, be clear with the user. Make sure they’re on the same page about why older versions are being deprecated, what the benefits of upgrading to the new version are, what issues they might face, and how they make solve those issues. Ample support during the transition period will help minimize disruptions and promote trust between the developer and API consumers.

API versioning best practices

Many aspects of your API versioning strategy will be dependent on factors unique to your application, but there are some general guidelines of API versioning best practices to take into consideration.

1. Prioritize the docs

The current state of the entire API should be reflected in comprehensive documentation, customized to the latest API version. Make sure that there are clear instructions on how changes should be introduced with each new version so no user gets confused — you’d be surprised how little friction it takes to make some users jump ship.

2. Keep the line open with the clients

Good communication is key. Understand what your consumers need and how each new version will affect their workflow, not just yours. Establish good channels of communication in advance to inform users of each upcoming change and each new version. Those channels also let you gather feedback from users to understand what their needs are and what their expectations are, and that’ll help you build a roadmap for the future of your API.

3. Plan for security and scalability

While most of API versioning focuses on the functional aspect of the API, security and scalability should be taken into consideration. As new versions are introduced that protect against security threats, older versions may continue to have those since-fixed vulnerabilities. Also, if you build a good API, you’ll start eventually getting increased usage (both over time and in quick spikes) and larger data volumes. The solution? Bake in automated security checks, vulnerability assessments, and scalable practices from the start. Make security updates and patch versions a priority for every version you support, not just the latest version. That includes every major or minor patch, even the since-replaced ones. This is an even bigger area where communication is crucial, since there may even be legal obligations to inform API users of how their data security is being protected in each new update.

4. Test thoroughly

You want to catch as many issues as possible before the API gets to the user. Conduct unit tests, integration tests, and regression tests for each new version. We’ve all been through the frustration of doing an upgrade on one part of a project just to find that we accidentally broke everything else. Thorough testing at each stage of API versioning helps avoid those situations and ensures a reliable product for the user. Automated tools can greatly streamline the process.

How to test API versions

To start, you want to thoroughly test the new API version separately to ensure that it meets all the functional specifications that the new API version is supposed to meet. There’s a couple ways to do this:

1. Unit testing

Unit testing involves testing individual pieces of code. For example, does each endpoint still function like expected? Take an endpoint that just takes in a letter, and if its within a certain range of ASCII values, it’ll shift the letter by however many places you specify. Here’s a function that does that:

const shiftLetter = (letter, key, rangeStart, rangeEnd) => {
const rangeLength = rangeEnd - rangeStart;
const code = letter.charCodeAt(0);
if (rangeStart <= code && code < rangeEnd) {
let n = code - rangeStart + key;
if (n < 0) n = rangeLength - Math.abs(n) % rangeLength;
return String.fromCharCode((n % rangeLength) + rangeStart);
} else return letter;
};

These examples are from an Algolia article about unit testing. If we have standardized our API, we don’t even need to test this over HTTP requests since that part acts predictably. We can just write a little function like this to test this particular unit of code:

const testShiftLetter = () => {
if (shiftLetter("L", 3, 65, 91) != "O") throw "Assertion error"; // test basic case
if (shiftLetter("s", 14, 65, 122) throw "Assertion error"; // test wrap around, and custom ranges
};

All it does is throw an error if the function doesn’t produce the correct result. You can also measure the performance of individual units here. Each new API version requires that you rerun these tests to make sure each individual piece of the API still works as you expect, so you should build this into your automated workflow, perhaps using a tool like GitStream.

2. Integration testing

Integration testing is very similar to unit testing (some don’t even make the distinction). The difference is that now we’re testing how units of code work together to produce the right result. Here's a more complex example from that same article:

const testCaesar = () => {
if (caesar("HELLO", 1) != "IFMMP") throw "Assertion error"; // test basic case
if (caesar(caesar("DECRYPTED TEXT", 19), -19) != "DECRYPTED TEXT") throw "Assertion error"; // test negative keys for decryption
};

See how it tests expected output even in edge cases?

3. System testing

The last type of testing involves using an application built with the API, testing how everything works together. This is harder to implement, but since you’ve built such great documentation and migration guides for each new version, you likely have demos built with your API that you can test with.

How can liblab help with API versioning

One sticking point a lot of developers have with API versioning is how it interacts with the various SDKs that actually consume the API. That’s where we come in — liblab can analyze your spec and generate SDKs tailored to the needs of your API. Trying to support multiple API versions and making sure clients can abstract API complexities and maintain consistent interfacing is usually a nightmare, but how to version APIs more effectively using SDKs.. liblab’s user-friendly controls let you automatically generate flexible SDKs that include all the necessary components right out of the box.

Conclusion

It may seem daunting to consider all these factors at the beginning of a project, but the time and effort now will pay dividends through the entire lifecycle of the project. If you're in a situation where it makes sense to create an API versioning strategy, the hard work right now will definitely be worth it! Thoughtful planning and implementation of best practices will result in robust scalable APIs and ensure long-term stability and adaptability. It's important to remember that software development is an evolving landscape, so we as devs have to keep up to date with improved best practices and new methods. Doing that puts you well on your way towards creating APIs with smooth transitions between versions, enhancing the end user experience, and helping you to build strong relationships with satisfied customers.

← Back to the liblab blog

It's just a simple fact of life that more work (and better work) gets done when everything is well-structured and organized. That's why, for example, professional chefs keep clean kitchens, precise timings, and ordered hierarchies of responsibilities.

A chef building a plate in an organized kitchen.

It's the same reason why, if you regularly work at a desk, you probably make some effort to keep it organized (or at least you want to). Especially developers — who work in a strictly-structured world of math and logic — love straightforward direction in the form of standards.

Fortunately, the charging one has been solved now that we've all standardized on mini-USB. Or is it micro-USB?

Preview

This is why we need standardized Application Programming Interfaces (APIs): the more our API design reflects the consistency developers are expecting, the more productive they'll be with it and the more valuable it'll be to the devs and the API provider.

When we're done here, you'll be able to answer these three questions:

  • What is API standardization and what does it look like in practice?
  • How do standardized APIs actually help in general and in my industry?
  • What can help lower the API standardization barrier-to-entry?

What is API Standardization?

You know what an API is: it's just the layer of glue between two pieces of code. Technically, it applies to almost every communication between modules inside an application, as well as to every external communication to some other program. That means that every time you have two pieces of code talk to each other, they have to have agreed in advance on what kind of communication they're going to use.

For example, maybe they'll use the JSON format, and they'll send messages to each other like this:

{
result: "success",
data: {
message: "Hello from across the API!"
}
}

Now, if this API is completely inside your application, you might be fine with just sending little packets of JSON like this between pieces of code. But the moment you start dealing with more complexity, you'll realize this approach to APIs doesn't scale well. Think about all the possible edge cases:

  • Will the response JSON always contain a result key?
  • What happens if the operation wasn't a success? Where will details about the error be stored?
  • Is the body of the response always inside data? Or is it sometimes at the root level of the object?

You probably have experience building an API like this. Maybe you've directly worked through these questions with your API, or maybe not, but if you can think of definitive answers to them, then you're delving into API standardization. You're setting rules for how the pieces of code talk to each other so that it'll be completely consistent across your app.

A definition

With that example in mind, now we have enough information to write a more succinct definition:

👉 API standardization (n): the process of creating and implementing consistent rules for how two pieces of code talk to each other over an API (Application Programming Interface)

The definition of API standardization.

Those consistent rules might include coming up with answers to questions such as:

  • In what format will the data be sent, both in the request and in the response?
  • What naming convention will we use? Are we sticking with camelCase, snake_case, or something else for variable, resource, function, and endpoint names?
  • How do the standards in our industry affect our ruleset?

You're a talented dev though; you know APIs go way beyond just two files sending tiny JSON packets back and forth.

API definitions over the internet

A company (called the service provider) might let you and your program interact with their programs over the Internet. The HTTP protocol that governs this already gives us some standardization to work with, but the body of each request is almost completely unsupervised. Imagine the chaos if every time we wanted to interact with, say, the Google Maps API, we could send our requests in whatever form we wanted! It'd be almost impossible for the service provider to pick out the needed data from our request, and even if it did, it'd probably be extremely slow. Let's focus on this use case from here on out to try and figure why API standardization isn't just a nice-to-have, but a crucial element of modern, efficient Information Technology.

Importance of API Standardization

What are the benefits of having standardized APIs for external services? Here's a few reasons:

1. It gets everybody collaborating

When API consumers can trust that it's straightforward to interact with the service and build what they want without too much unnecessary hassle, they'll be motivated to go further out of their way to work with others to solve problems.

2. It keeps the bugs to a minimum

It's way easier to avoid unintended functionality when security and predictability are baked right into the messages servers and clients send to each other. This has the effect of increasing the expected uptime of the API and reducing interruptions in service provision.

3. It promotes scalable innovation on the provider's side

When the service provider already has established the input and output of a particular endpoint or function, much of the grunt work involved in adding new features goes away. Standardized APIs open up tons of future prospects moving forward because the developers building the API can afford to be more creative.

4. It simplifies documentation and improves developer experience

Developers already keep track of enough, so if the learning curve is too high to interact with an API, they'll just avoid it. API standardization simplifies docs because we can remove all of the things that the rules make too obvious or too redundant to explain again. Standardization means developers can more easily find what they're looking for in the docs, flattening the learning curve and making the API more approachable to a wider range of users.

5. It reduces long-term technical debt in actual implementations

If the communication both between modules and to outer systems is standardized with an API and consistent rules, it removes the complexity that would otherwise need to be managed in the future, which helps to reduce operational costs that would come with it.

API Standardization Use Cases

Healthcare

Standardized Application Programming Interfaces are incredibly important in healthcare because data scattered among many systems affects how doctors and pharmacists work. For example, imagine you moved from South Carolina to Louisiana, so your providers, insurance company, pharmacies, and other healthcare connections all changed. What if, because the providers in South Carolina didn't have an easy, standardized API to upload your current prescriptions to a centralized database, your new healthcare providers in Louisiana prescribed you a conflicting medicine and damaged your health?

Smart API design prevents potentially life-threatening gaps in data sharing, and that's one of the biggest reasons why API standardization has gained industry-wide adoption in healthcare.

Government

Public services are notoriously difficult to use. Just the word “bureaucracy” comes with negative connotations because workers in different departments have the reputation of (to put it kindly) preferring to keep necessary information to themselves. In contrast, APIs are designed to bring people together through data and promote efficient information technology. No wonder standardized APIs have been a digital transformation in the government sector.

For the United States government, there's an official standard that requires several main objectives to be fulfilled:

  1. Make it available to everyone by putting new APIs in the directory.
  2. Use the API outer layer common to all government APIs for analytics, authentication, and security.
  3. Get versioning right. Wondering how? See our recent article on what makes API versioning so necessary and how to do it.
  4. Build public docs. Thankfully, this is way easier because we're working with standardized APIs.
  5. Have a feedback mechanism where users can report issues and ask questions. Feedback builds trust and also helps retain API users who are having trouble and are ready to quit.
  6. Use OpenAPI spec files to make it clear to users how to access the APIs, and make sure these OpenAPI specs don't suck!
  7. Use the normal endpoint design. Creativity is usually a positive, but once it starts causing mass confusion, it's not worth it.

You're not bound to these rules, but it might be worth implementing them at your company because they're a great way to make sure the principles of API standardization come through in the actual implementations you build.

Financial Services

Financial service technology (a.k.a. “fintech”) companies love APIs and standardization. There's a couple particularly strong reasons:

First, the modern shift toward open banking means customers are just expecting financial institutions to easily talk to each other. For example, in some countries you can set up investment accounts to pull directly from your bank. As a modern user would expect, there was no copy-and-pasting routing numbers, no hacky tiny deposits, no three-day wait, because they have standardized APIs (probably served via Plaid) for connecting the two accounts.

Plaid in action

Also, many smaller companies don't have the infrastructure to run payment data themselves. A typical small business would find it way easier to use something like Stripe, a company that created API definitions for payment methods, invoices, charges, refunds, and every other piece of the payment process. That means that by using their API, we can get from hypothetical ideas to actual implementations really quickly.

Third, like we mentioned earlier, standardized APIs have plenty of security benefits too. That's especially great for fintech companies because they deal with extreme amounts of regulation to prevent data leaks and keep their customers' money and business data safe.

And as always, they're businesses that want to distinguish themselves from the competition. By adopting the principles of standardized APIs, they can focus on innovation and coming up with new ideas that'll grow the business.

How liblab Can Help With API Standardization

One of the biggest benefits of creating standard API definitions for endpoints and resources is that it allows you to automate building Software Development Kits (SDKs) out of your API.

That's where liblab comes in. Before, a small change in how your API worked meant you had to update every piece of code that used the API. But by putting liblab into your workflow, you can automatically generate the language-specific libraries through which your customers and clients will use your tool straight from the API design file, written to the OpenAPI spec. This means that you won't be bothered by the language-specific bugs and intricacies that would normally drag down a project that others depend on — instead, you'll get to efficiently spend time on what strengthens future prospects moving forward, like new API features and performance optimizations.

A pitch for standardized Application Programming Interfaces

Want a quick pitch to bring to the folks in charge of your APIs? Here's a summary of what we've learned so far:

  • APIs need consistency to be useful.
  • API standardization helps facilitate developer collaboration, simplify maintenance, promote faster innovation, make the developer experience more enjoyable, and limit technical debt.
  • Many industries needed API standardization, and how they implemented it can help you decide how to implement it at your company to improve your future prospects.
  • liblab's experts can help you through it. Benefit from our expertise by signing up for liblab.

Now that you're an expert in API standardization, set yourself up for long-term success by partnering up with liblab and automating SDK generation based on your standardized Application Programming Interfaces.

← Back to the liblab blog

If you build APIs, you need to document them. After all, for your users to use your API, they need to know how to use it. A common phrase I like to use as someone who writes a lot of docs is "if it's not documented, it does not exist" - your users can only use a feature if they can discover not only that it exists, but how to use it.

So what is API documentation? How should you write it? What should you include? What are the best practices? In this post I'll answer all of these questions and more and give you some best practices for creating API documentation.

What is API Documentation?

API documentation is the collection of materials your users can use to learn how to effectively build apps using your API. It should contain a range of things:

  • API Reference documentation for the endpoints, parameters, request and response objects, and expected status codes
  • Examples of using the API
  • Examples for the request and response objects to help users know what to pass and what to expect back
  • Error messages and status codes that can be returned, and what they mean
  • Basic usage guides such as how to get started, authentication, and common scenarios
  • Tutorials for more complex scenarios

Why is API Documentation Important?

API documentation is how your users know how to use your API. Without it, they will at best struggle to use your API, and at worst have no idea how to do anything. APIs are lacking in discoverability - without any kind of documentation you literally cannot know what endpoints to call. Even with a list of endpoints, you still need to know what to pass to them, and what to expect back.

For even better discoverability, you can use liblab to generate SDKs from your API specs. SDKs are a much better developer experience than using APIs directly, allowing you to discover the functionality and request and response objects through tools such as IDE autocompletion.

Documentation goes beyond discovering what your API does, it also explains details on how to use it effectively. This can include how to correctly authenticate, how to handle errors, and best practices for using the API.

For example, if you call an endpoint to retrieve some data and you get a 404 status code returned. Does that mean the data does not exist, or that you don't have permission to access it? Good documentation will explain this, and give you the information you need to handle it correctly.

How and where to write API Documentation?

The best place to write API documentation is in your API!

API Specs

When you publish your API, you should always also publish an API spec. This is generated documentation that lists your API endpoints and the request and response objects, and uses standards like Swagger or OpenAPI. The big advantage of this is a lot of the time this can be autogenerated! For example if you are using FastAPI (a Python framework for building APIs) to generate your API, you can have the framework create an OpenAPI spec with no extra code to write.

API specs as a default provide a list of endpoints, what is expected for endpoint parameters, and the request and response objects. These are JSON or YAML documents, so out the box not that easy to read - but there are plenty of tools that can convert these into nice hosted documentation (FastAPI for example has this built in), and again can be built into your API tools or hosting process.

For example, we have a llama store as a reference API for building SDKs against, and it has a spec that is 1115 lines of JSON (you can read it on our GitHub if you want some light bedtime reading). This is small compared to some specs we see at liblab, with over 40,000 lines not uncommon! Reading this much JSON is hard, so there are plenty of tools that render this direct from the API. For example, FastAPI as mentioned before generates OpenAPI specs, as well as hosting generated documentation:

The hosted docs for the llama store

You can see these docs yourself, just clone the llama store, run it locally and access localhost:8000/docs.

Adding documentation to API Specs

As well as these specs listing your endpoints, they can also include a wide range of documentation. This includes:

  • Top level API documentation where you can describe in detail the API, such as how to use it, how to authenticate, and best practices
  • Endpoints descriptions
  • Descriptions and examples for endpoint parameters
  • Description and examples for request and response objects
  • Descriptions for different status codes, including why they might be returned, and what data might some with them

For example, the llama store has a top level description in the OpenAPI spec:

{
"openapi": "3.1.0",
"info": {
"title": "Llama Store API",
"description": "The llama store API! Get details on all your favorite llamas.\n\n## To use this API\n\n- You will need to register a user, once done you can request an API token.\n- You can then use your API token to get details about the llamas.\n\n## User registration\n\nTo register a user, send a POST request to `/user` with the following body:\n \n```json\n{\n \"email\": \"<your email>\",\n \"password\": \"<your password>\"\n}\n```\nThis API has a maximum of 1000 current users. Once this is exceeded, older users will be deleted. If your user is deleted, you will need to register again.\n## Get an API token\n\nTo get an API token, send a POST request to `/token` with the following body:\n \n```json\n{\n \"email\": \"<your email>\",\n \"password\": \"<your password>\"\n}\n```\n\nThis will return a token that you can use to authenticate with the API:\n\n```json\n{\n \"access_token\": \"<your new token>\",\n \"token_type\": \"bearer\"\n}\n```\n\n## Use the API token\n\nTo use the API token, add it to the `Authorization` header of your request:\n\n```\nAuthorization: Bearer <your token>\n```\n\n\n",
}
}

This is actually set in code - something that FastAPI supports is adding these kinds of OpenAPI values to your API code:

app = FastAPI(
servers=[{"url": "http://localhost:8000", "description": "Prod"}],
contact={"name": "liblab", "url": "https://liblab.com"},
description="The llama store API! Get details on all your favorite llamas.\n\n## To use this API\n\n- You will need to register a user, once done you can request an API token.\n- You can then use your API token to get details about the llamas.\n\n## User registration\n\nTo register a user, send a POST request to `/user` with the following body:\n \n```json\n{\n \"email\": \"<your email>\",\n \"password\": \"<your password>\"\n}\n```\nThis API has a maximum of 1000 current users. Once this is exceeded, older users will be deleted. If your user is deleted, you will need to register again.\n## Get an API token\n\nTo get an API token, send a POST request to `/token` with the following body:\n \n```json\n{\n \"email\": \"<your email>\",\n \"password\": \"<your password>\"\n}\n```\n\nThis will return a token that you can use to authenticate with the API:\n\n```json\n{\n \"access_token\": \"<your new token>\",\n \"token_type\": \"bearer\"\n}\n```\n\n## Use the API token\n\nTo use the API token, add it to the `Authorization` header of your request:\n\n```\nAuthorization: Bearer <your token>\n```\n\n\n",
openapi_tags=tags_metadata,
version="0.0.1",
redirect_slashes=True,
title="Llama Store API",
)

This then gives these docs:

The rendered top level description

You may notice that the description has markdown! This is nicely rendered in the docs. This is a great way to add rich documentation to your API specs, and is a great way to add tutorials and best practices. This rich documentation can also provide code examples, error messages and more.

This generated documentation should not just be made available via your API, but also hosted on a public documentation site.

Additional documentation

As well as documenting your API in the API spec, you can also add additional documentation on your public documentation site. Your API docs become the reference documentation, but you should add tutorials, how to guides, and best practice documentation as well.

Your API spec documentation can define what each endpoint does and how to call it, but it may not define the correct flow that a user might take for a typical task. For example, if your API has long running tasks, you may need to document how a user can trigger a task, check the status, then retrieve the result, all using different endpoints.

Who Should Write API Documentation?

As someone who started out in engineering before I moved to developer relations, I know how hard it is to write documentation. It's not something that comes naturally to most engineers, and it's not something that most engineers enjoy doing. But it is something that is important, and something that needs to be done.

In a perfect world, your documentation would be written by a dedicated technical writer, working in collaboration with the engineers to understand how the API works, and with the product teams to understand the end-to-end user experience. They should then feed this documentation back to the engineers to add to the API spec.

We all don't live in a perfect world though, so the next best thing is to have the engineers and product teams write the documentation. They know the API best, and can write the most accurate documentation.

Ideally you should use a framework for your API that makes writing these docs easy - for example FastAPI as mentioned before makes it easy to add documentation to your API code, and then generates the OpenAPI spec for you. This way you can even 'enforce' this by having a check for documentation in your pull request review process, or in a linting check in your CI/CD pipeline.

As an API provider - make sure you have documentation firmly in your process!

API Documentation Best Practices

Here are some API documentation best practices for writing api docs:

1 - Write in clear language

A good rule for everyone writing any documentation, including creating API documentation, is to be as clear as possible. Avoid jargon, unless it is necessary technical terminology for your product, and find ways to define this, or link to other documentation. There are some things you can assume your users know, but don't assume they know everything. It's helpful to define a minimally qualified reader, which defines the minimum knowledge or skills for each piece of documentation, and write for them.

For example, you can assume that your users know how to call an API (though a link to a guide on this is always helpful), but you can't assume they know how to authenticate, or what a JSON object is. As you document more advanced functionality, you can assume some knowledge of your API, such as assuming they know how to create a new user when documenting how to interact with that user.

2 - Show, don't tell

For any documentation, showing is better than telling. Examples always help - it's amazing how much easier it is to understand something when you can see it in action.

This is true for API documentation as well. If you want to teach someone how to get data from your API, show them the request, and what response they will get. When using your API, users could be using one of many programming languages, so provide code examples for the main ones. For example, if your API is targeted towards an enterprise, have code examples in C# and Java.

3 - Add references docs, tutorials, and guides

Documentation comes in a variety of modes, and it is good to implement them all. These are:

  • Tutorials - learning oriented
  • How to guides - task oriented
  • Explanation - understanding oriented
  • Reference docs - information oriented

I won't go into these in more depth here, but read up on Diátaxis for more information.

Reference docs and explanation should be in your API specs, and hosted on your public documentation site. Tutorials and how to guides can be on your public documentation site.

Your tutorials should also always have a quickstart. Humans like instant gratification, so being able to very quickly get started with an API is a great motivator to learn more and use it more. If a user struggles to even do the basics, they are likely to drop your API and move to a competitor. That initial documentation is crucial to keeping users engaged.

4 - Add code samples

Code samples always help! You users are engineers after all, and will be accessing your API using code. Code samples allow them to quickly craft API calls, and see what they will get back. They also allow you to show best practices, such as how to handle errors, and how to handle pagination.

Obviously the best code samples are using an SDK instead of an API - something liblab can help with!

5 - Keep it up to date

This is sometimes the hardest. When an API has no documentation there's often a big effort around writing api documentation once, usually before a big release, but no continuous time given to keeping the api docs up to date - changing them as features change or adding new features.

This is why it's important to have documentation as a part of your engineering and release process. Don't let any feature out the gate without docs, add documentation to your PR processes, or add checking for docs to your CI/CD pipelines. If you have a dedicated technical writer, they can help with this, but if not, make sure the engineers and product teams are writing the docs as they write the code.

Feature flags can be particularly helpful here, allowing features to be released, but not turned on until the docs are ready (and maybe turned on for the doc writers so they can verify what they are writing).

6 - Make it accessible

Accessibility is important for documentation as well as your API. Make sure your documentation is accessible to everyone, including those with visual impairments. This means when you render it on a docs site using good color contrast, and making sure any images have alt text. It also means making sure your documentation is accessible to screen readers, and that any code samples are accessible.

You also may have users who don't speak the default language of your company, so consider translating your documentation into other languages. This is a big effort, but can be done in stages, starting with machine translations for the most popular languages for your users, and moving on to human efforts.

7 - Make it someones problem

The best way to ensure you have good docs, is to have someone responsible. This is the person who can hold up a release or turning on a feature flag if docs are not ready. Without someone taking responsibility, it's easy for docs to be forgotten about, and for them to become out of date. "Oh, we'll do it later, we need to release for customer X" is the start of the slippery slope to no useful docs.

Make your SDKs better with good API documentation

The other big upside of good API documentation is it can automatically become the documentation for your SDK. With liblab, every time you generate an SDK, the documentation and examples are lifted from your API spec and included in the SDK. For example, with the following component in your API spec:

APITokenRequest:
properties:
email:
type: string
title: Email
description: The email address of the user. This must be unique across all users.
password:
type: string
title: Password
description: The password of the user. This must be at least 8 characters long, and contain
at least one letter, one number, and one special character.

You would get the following documentation in your Python SDK:

A documentation popup for an APITokenRequest showing the descriptions of the email and password properties

Conclusion

Your users deserve good documentation for your API, and for any SDKs generated from them. With liblab, you can generate high quality SDKs from your API specs, and include the documentation and examples from your API spec in the SDKs. This means you can focus on writing good API specs and writing good API documentation, and let liblab do the hard work of generating the SDKs and documentation for you.