OpenAPI Tips
Tags Best Practices in OpenAPI
Nolan Sullivan
November 22, 2023
Announcing: OpenAPI Reference
Hi! These blog posts have been popular, so we've built an entire OpenAPI Reference Guide to answer any question you have.
It includes detailed information on tags.
Happy Spec Writing!
Introduction
This article explains how to use tags in OpenAPI (opens in a new tab).
Tags are the way to organize your API endpoints into groups to make them easier for users to understand.
Definitions
Every separate feature in your API that a customer can call is named an endpoint.
An endpoint is an operation (an HTTP method like GET or POST) applied to a path (for example, /users
).
Below is an example endpoint in an OpenAPI schema. The path is play
, and the operation is a POST.
paths: /play: post: description: Choose your jazz style. operationId: band#play
In informal conversation, people often refer to API endpoints and operations as if the terms are interchangeable.
Paths are the natural way to categorize your endpoints. You might have separate paths in your API for products, purchases, or accounts. However, paths are hierarchical. Each endpoint can be in only one path. This may make it difficult for users of your API to browse to the feature they are looking for if they assume it's under a different path.
By contrast, each endpoint may have multiple tags, so may be shown in multiple groups in your schema documentation.
Example Schema
To demonstrate using tags, let's make a simple schema for a jazz club API with just three paths:
/play
— plays music./stop
— stops music./order
— orders a drink.
API Information
Start with some basic information about your API.
openapi: 3.0.3info: title: The Speakeasy Club description: A club that serves drinks and plays jazz. version: 1.0.0servers: []
Simple Tag
Add the tags
root-level object with a tag for drink operations.
Only the tag name
is mandatory.
openapi: 3.0.3info: title: The Speakeasy Club description: A club that serves drinks and plays jazz. version: 1.0.0servers: []tags: - name: Drinks
Detailed Tag
Add another tag with more detail. The Music tag has a description
string and an externalDocs
object with two required fields: description
and url
.
The URL points to information anywhere on the web that you want to use to describe the endpoint. Use externalDocs
if you don't want to overcrowd your schema with unnecessary detail or if another department in your company maintains the documentation separately.
openapi: 3.0.3info: title: The Speakeasy Club description: A club that serves drinks and plays jazz. version: 1.0.0servers: []tags: - name: Drinks - name: Music description: A band that plays jazz. externalDocs: description: List of jazz genres url: https://en.wikipedia.org/wiki/List_of_jazz_genres
Paths
Now that we have tag definitions, we can tag our endpoints.
Here the /play
and /stop
endpoints are tagged with Music
, and the /order
endpoint is tagged with Drinks
.
We could also make another tag called Front of house
and apply it to both endpoints to organize them separately to Backstage
endpoints.
openapi: 3.0.3info: title: The Speakeasy Club description: A club that serves drinks and plays jazz. version: 1.0.0servers: []tags: - name: Drinks - name: Music description: A band that plays jazz. externalDocs: description: List of jazz genres url: https://en.wikipedia.org/wiki/List_of_jazz_genrespaths: /play: post: tags: - Music summary: Play music description: Choose your jazz style. operationId: band#play requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/PlayRequestBody" example: style: Bebop responses: "204": description: No Content response. /stop: post: tags: - Music summary: Stop music description: Stop playing. operationId: band#stop responses: "204": description: No Content response. /order: post: tags: - Drinks summary: Order tea description: Order a cup of tea. operationId: order#tea requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/TeaRequestBody" example: includeMilk: false responses: "204": description: No Content response.
Simple Tag
Add the tags
root-level object with a tag for drink operations.
Only the tag name
is mandatory.
Detailed Tag
Add another tag with more detail. The Music tag has a description
string and an externalDocs
object with two required fields: description
and url
.
The URL points to information anywhere on the web that you want to use to describe the endpoint. Use externalDocs
if you don't want to overcrowd your schema with unnecessary detail or if another department in your company maintains the documentation separately.
Paths
Now that we have tag definitions, we can tag our endpoints.
Here the /play
and /stop
endpoints are tagged with Music
, and the /order
endpoint is tagged with Drinks
.
We could also make another tag called Front of house
and apply it to both endpoints to organize them separately to Backstage
endpoints.
openapi: 3.0.3info: title: The Speakeasy Club description: A club that serves drinks and plays jazz. version: 1.0.0servers: []
The Full Schema Example
Below is the full example schema with components
added to specify how to call the endpoints.
Paste the code into the Swagger editor (opens in a new tab) to see it displayed as a formatted document. Note that operations in the Swagger output are grouped by tag
.
openapi: 3.0.3info: title: The Speakeasy Club description: A club that serves drinks and plays jazz. version: 1.0.0servers: []tags: - name: Drinks - name: Music description: A band that plays jazz. externalDocs: description: List of jazz genres url: https://en.wikipedia.org/wiki/List_of_jazz_genrespaths: /play: post: tags: - Music summary: Play music description: Choose your jazz style. operationId: band#play requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/PlayRequestBody" example: style: Bebop responses: "204": description: No Content response. /stop: post: tags: - Music summary: Stop music description: Stop playing. operationId: band#stop responses: "204": description: No Content response. /order: post: tags: - Drinks summary: Order tea description: Order a cup of tea. operationId: order#tea requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/TeaRequestBody" example: includeMilk: false responses: "204": description: No Content response.components: schemas: PlayRequestBody: type: object properties: style: type: string description: Style of music to play example: Bebop enum: - Bebop - Swing example: style: Bebop required: - style TeaRequestBody: type: object properties: includeMilk: type: boolean description: Whether to have milk. example: true example: includeMilk: false
Below is what it looks like in the editor.
Tags in Speakeasy
Speakeasy will split the SDKs and documentation it generates based on your tags.
You can add the x-speakeasy-group field to an endpoint to tell Speakeasy to ignore the endpoint's tag and group it under the custom group instead.
Conclusion
That's everything you need to know about tags in OpenAPI.
There are just three more tag rules you might want to know:
- Tags are optional, both at the root level and on endpoints.
- Tags must have unique names in your schema.
- The tag
description
may use CommonMark syntax (opens in a new tab).