OpenAPI Overview & Best Practices
OpenAPI is a standard for describing RESTful APIs. OpenAPI allows developers to define all the core elements of an API: endpoints, request and response data formats, authentication methods, etc.
There are several versions of the OpenAPI specification in circulation: 2.0 (also known as Swagger), 3.0, and 3.1.
Speakeasy supports OpenAPI versions 3.0 and 3.1. We recommend developers use OpenAPI version 3.1 for all projects. The advantage of using OpenAPI version 3.1 is that it is fully compatible with JSON Schema (opens in a new tab), which gives you access to a much larger ecosystem of tools and libraries.
OpenAPI Best Practices
OpenAPI can describe any HTTP API, whether it's REST or something more akin to RPC-based calls. This gives the OpenAPI Specification a lot of baked-in flexibility: There are many ways to achieve the same result that are equally valid according to the OpenAPI Specification.
With so much flexibility, it isn't always obvious how to construct an OpenAPI spec that is sufficient for code generation. We recommend a set of best practices to follow when writing OpenAPI documents. The following sections will outline key points to consider as you create your OpenAPI description.
servers
Adding multiple servers allows you to define different environments or versions. This is especially useful for separating production and testing environments.
tags
Contains an optional list of tags
that are generally used to group or categorize a set of operations. We strongly recommend that you always define tags
for operations, but it is not required.
In code generation
Tags will be used to namespace the methods in the SDK. For example, if you have a tag called drinks
, then all the methods for that tag will be namespaced under drinks.listDrinks()
. You can create multi-level namespaces by using a .
in the tag name, for example, menu.drinks
will become menu.drinks.listDrinks()
.
operationId
A unique identifier for the operation. This ID must be unique in the document, and is case sensitive. We strongly recommend that you always define an operationId
, but it is not required.
In code generation
The operationId
is used to create the name of the method that will be generated for the operation. We recommend you follow a consistent pattern for naming your operations, for example, listDrinks
, createDrink
, updateDrink
, and deleteDrink
.
If you are generating your spec from an API framework, ensure that operationId
values are human-readable. Some frameworks (for example, FastAPI) create long operationId
identifiers that result in method names that are not idiomatic.
$ref
The $ref keyword in OpenAPI allows referencing components defined in the Components Object, commonly utilized for reusable elements like schemas, parameters, responses, and examples.
In code generation
Component schemas describe the request and response bodies of operations, serving as the basis for generating SDK types. Using components prevents issues where multiple types are defined for the same data structure.
Dedicated Error Classes
Create dedicated error classes by defining response objects with specific HTTP status codes, such as 400 Bad Request
or 404 Not Found,
accompanied by clear descriptions and structured schemas to convey detailed error information.
If the name of the error class does not clearly incidate the error type, consider using the x-speakeasy-name-override
extension to rename it.
title
The title
property provides a human-readable title for each schema improving the readability of your OpenAPI specification.
Description
Utilize the description
field to provide clear and concise information about the purpose, behavior, and expected usage of API elements.
Examples
Examples
improve the usability of your OpenAPI specification by providing examples that illustrate expected request and response structures.
servers
Adding multiple servers allows you to define different environments or versions. This is especially useful for separating production and testing environments.
tags
Contains an optional list of tags
that are generally used to group or categorize a set of operations. We strongly recommend that you always define tags
for operations, but it is not required.
In code generation
Tags will be used to namespace the methods in the SDK. For example, if you have a tag called drinks
, then all the methods for that tag will be namespaced under drinks.listDrinks()
. You can create multi-level namespaces by using a .
in the tag name, for example, menu.drinks
will become menu.drinks.listDrinks()
.
operationId
A unique identifier for the operation. This ID must be unique in the document, and is case sensitive. We strongly recommend that you always define an operationId
, but it is not required.
In code generation
The operationId
is used to create the name of the method that will be generated for the operation. We recommend you follow a consistent pattern for naming your operations, for example, listDrinks
, createDrink
, updateDrink
, and deleteDrink
.
If you are generating your spec from an API framework, ensure that operationId
values are human-readable. Some frameworks (for example, FastAPI) create long operationId
identifiers that result in method names that are not idiomatic.
$ref
The $ref keyword in OpenAPI allows referencing components defined in the Components Object, commonly utilized for reusable elements like schemas, parameters, responses, and examples.
In code generation
Component schemas describe the request and response bodies of operations, serving as the basis for generating SDK types. Using components prevents issues where multiple types are defined for the same data structure.
Dedicated Error Classes
Create dedicated error classes by defining response objects with specific HTTP status codes, such as 400 Bad Request
or 404 Not Found,
accompanied by clear descriptions and structured schemas to convey detailed error information.
If the name of the error class does not clearly incidate the error type, consider using the x-speakeasy-name-override
extension to rename it.
title
The title
property provides a human-readable title for each schema improving the readability of your OpenAPI specification.
Extending OpenAPI
The OpenAPI Specification does not have an exhaustive vocabulary for describing API functionality. To overcome gaps in the specification, you can add several extension fields to an OpenAPI document that describe additional metadata and functionality.
Extensions typically follow a naming format of x-<vendor>-<function>
, where <vendor>
is the name of the vendor or tool that created the extension and <function>
is the goal accomplished by the extension.
A range of Speakeasy extensions are available to help you prepare a spec for code generation. Some of the most commonly used extensions are described below.
x-speakeasy-name-override
Use this extension to override the name of a class, operation, or parameter. The most common use case is to override operationId
values in your spec to simplify the created SDK method names.
If your operationId
identifiers follow a consistent pattern, you can define the name override globally using a regular expression to match the operationId
and replace it with a new name.
In this instance, the SDK will contain a method menu.drinks.list()
rather than menu.drinks.list_drinks_v2_get()
— much nicer!
x-speakeasy-group
Sometimes the tags
in an OpenAPI spec may already be used for an unrelated purpose (for example, autogenerating labels in documentation). In this scenario, you may want to use something other than tags
to organize and group your methods.
You can add the x-speakeasy-group
field to any operation in your OpenAPI spec to define custom namespaces and override any tags
associated with the method.
In this case, the listDrinks
operation is added to a menu.drinks
namespace rather than a menu
namespace.
x-speakeasy-usage-example
Documentation is an important part of any SDK. This extension allows you to choose which operation is featured at the top of your README.md
.
We recommend that you pick the API operation that your users will most frequently employ. At a Speakeasy, that would likely be getting the list of drinks on offer.
x-speakeasy-example
Another useful documentation extension is x-speakeasy-example
, which allows you to provide an example value to be used in the Authentication
section of your SDK README.md
.
This will help signal to users how they should instantiate the SDK with their security token.
x-speakeasy-name-override
Use this extension to override the name of a class, operation, or parameter. The most common use case is to override operationId
values in your spec to simplify the created SDK method names.
If your operationId
identifiers follow a consistent pattern, you can define the name override globally using a regular expression to match the operationId
and replace it with a new name.
In this instance, the SDK will contain a method menu.drinks.list()
rather than menu.drinks.list_drinks_v2_get()
— much nicer!
x-speakeasy-group
Sometimes the tags
in an OpenAPI spec may already be used for an unrelated purpose (for example, autogenerating labels in documentation). In this scenario, you may want to use something other than tags
to organize and group your methods.
You can add the x-speakeasy-group
field to any operation in your OpenAPI spec to define custom namespaces and override any tags
associated with the method.
In this case, the listDrinks
operation is added to a menu.drinks
namespace rather than a menu
namespace.
x-speakeasy-usage-example
Documentation is an important part of any SDK. This extension allows you to choose which operation is featured at the top of your README.md
.
We recommend that you pick the API operation that your users will most frequently employ. At a Speakeasy, that would likely be getting the list of drinks on offer.