Skip to content

update: Pydantic links and new features #11

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
144 changes: 84 additions & 60 deletions openapi/frameworks/pydantic.mdx
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
---
title: How To Generate an OpenAPI Spec with Pydantic V2
description: "How to generate OpenAPI schemas and great SDK clients for your Pydantic V2 Models"
title: How To Generate an OpenAPI Document With Pydantic V2
description: "How to generate OpenAPI documents and great SDKs for your Pydantic V2 Models"
---

# How to generate an OpenAPI/Swagger spec with Pydantic V2
# How to generate an OpenAPI document with Pydantic V2

[Pydantic](https://docs.pydantic.dev/latest/) is considered by many API developers to be the best data validation library for Python, and with good reason. By defining an application's models in Pydantic, developers benefit from a vastly improved development experience, runtime data validation and serialization, and automatic OpenAPI schema generation.
[Pydantic](https://docs.pydantic.dev/latest/) is considered by many API developers to be the best data validation library for Python, and with good reason. By defining an application's models in Pydantic, developers benefit from a vastly improved development experience, runtime data validation and serialization, and automatic OpenAPI document generation.

However, many developers don't realize they can generate OpenAPI schemas from their Pydantic models, which they can then use to create SDKs, documentation, and server stubs.
However, many developers don't realize they can generate OpenAPI documents from their Pydantic models, which they can then use to create SDKs, documentation, and server stubs.

In this guide, you'll learn how to create new Pydantic models, generate an OpenAPI schema from them, and use the generated schema to create an SDK for your API. We'll start with the simplest possible Pydantic model and gradually add more features to show how Pydantic models translate to OpenAPI schemas.
In this guide, you'll learn how to create new Pydantic models, generate an OpenAPI document from them, and use the generated schema to create an SDK for your API. We'll start with the simplest possible Pydantic model and gradually add more features to show how Pydantic models translate to OpenAPI documents.

## Prerequisites

Expand All @@ -19,9 +19,9 @@ Before we get started, make sure you have [Python](https://www.python.org/downlo
python --version
```

We use Python 3.12.4 in this guide, but any version of Python 3.8 or higher should work.
We use Python 3.13.3 in this guide, but any version of Python 3.8 or higher should work.

## Create a New Python Project
## Creating a new Python project

First, create a new Python project and install the Pydantic library:

Expand All @@ -37,9 +37,9 @@ python -m venv venv
source venv/bin/activate
```

## Install the Required Libraries
## Install the required libraries

We'll install Pydantic and PyYAML to generate and pretty-print the OpenAPI schema:
We'll install Pydantic and PyYAML to generate and pretty-print the OpenAPI document:

```bash Terminal
# Install the Pydantic library
Expand All @@ -49,11 +49,11 @@ pip install pydantic
pip install pyyaml
```

## Pydantic to OpenAPI Schema Walkthrough
## Pydantic to OpenAPI document walkthrough

Let's follow a step-by-step process to generate an OpenAPI schema from a Pydantic model without any additional libraries.
Let's follow a step-by-step process to generate an OpenAPI document from a Pydantic model without any additional libraries.

### Define a Simple Pydantic Model
### Defining a simple Pydantic model

Create a new Python file called `models.py` and define a simple Pydantic model.

Expand All @@ -69,7 +69,7 @@ class Pet(BaseModel):
breed: str
```

### Generate JSON Schema for the Pydantic Model
### Generating a JSON schema for the Pydantic model

Add a new function called `print_json_schema` to the `models.py` file that prints the JSON schema for the `Pet` model.

Expand Down Expand Up @@ -115,7 +115,7 @@ title: Pet
type: object
```

### Multiple Pydantic Models
### Multiple Pydantic models

Let's add another Pydantic model called `Owner` to the `models.py` file.

Expand Down Expand Up @@ -146,7 +146,7 @@ if __name__ == "__main__":
print_json_schema()
```

### Generate JSON Schema for Multiple Pydantic Models
### Generating a JSON schema for multiple Pydantic models

Update the `print_json_schema` function to print the JSON schema for both the `Pet` and `Owner` models.

Expand Down Expand Up @@ -227,7 +227,7 @@ The generated schema includes definitions for both the `Pet` and `Owner` models.

Note that the root of the schema includes a `$defs` key that contains the definitions for both models, and the `Owner` model references the `Pet` model using the `$ref` keyword.

### Customize Pydantic JSON Schema Generation
### Customizing Pydantic JSON schema generation

Let's customize the generated JSON schema to reference the `Pet` model using the `#/components/schemas` path instead of `$defs`.

Expand Down Expand Up @@ -263,7 +263,7 @@ if __name__ == "__main__":
print_json_schema([Pet, Owner])
```

Next, we'll update the `print_json_schema` function to print a JSON schema that resembles an OpenAPI schema's `components` section.
Next, we'll update the `print_json_schema` function to print a JSON schema that resembles an OpenAPI document's `components` section.

```python
import yaml
Expand Down Expand Up @@ -300,9 +300,9 @@ if __name__ == "__main__":
print_json_schema([Pet, Owner])
```

Run `python models.py` to generate the OpenAPI schema for both the `Pet` and `Owner` models.
Run `python models.py` to generate the OpenAPI document for both the `Pet` and `Owner` models.

The generated OpenAPI schema includes the `components` section, with definitions for both the `Pet` and `Owner` models.
The generated OpenAPI document includes the `components` section, with definitions for both the `Pet` and `Owner` models.

```yaml
components:
Expand Down Expand Up @@ -345,9 +345,9 @@ components:
type: object
```

The JSON Schema we generated resembles an OpenAPI schema's `components` section, but to generate a valid OpenAPI schema, we need to add the `openapi` and `info` sections.
The JSON schema we generated resembles an OpenAPI document's `components` section, but to generate a valid OpenAPI document, we need to add the `openapi` and `info` sections.

Edit the `print_json_schema` function in `models.py` to include the `openapi` and `info` sections in the generated OpenAPI schema.
Edit the `print_json_schema` function in `models.py` to include the `openapi` and `info` sections in the generated OpenAPI document.

```python
import yaml
Expand Down Expand Up @@ -389,9 +389,9 @@ if __name__ == "__main__":
print_json_schema([Pet, Owner])
```

Run `python models.py` to generate the complete OpenAPI schema for both the `Pet` and `Owner` models.
Run `python models.py` to generate the complete OpenAPI document for both the `Pet` and `Owner` models.

The generated OpenAPI schema includes the `openapi`, `info`, and `components` sections with definitions for both the `Pet` and `Owner` models.
The generated OpenAPI document includes the `openapi`, `info`, and `components` sections with definitions for both the `Pet` and `Owner` models.

```yaml
openapi: 3.1.0
Expand Down Expand Up @@ -438,11 +438,11 @@ components:
type: object
```

Now we have a complete OpenAPI document that we can use to generate SDK clients for our API. However, the generated OpenAPI schema does not contain descriptions or example values for the models. We can add these details to the Pydantic models to improve the generated OpenAPI schema.
Now we have a complete OpenAPI document that we can use to generate SDK clients for our API. However, the generated OpenAPI document does not contain descriptions or example values for the models. We can add these details to the Pydantic models to improve the generated OpenAPI document.

### Adding Descriptions to Pydantic Models
### Adding descriptions to Pydantic models

Let's add docstrings to the `Pet` and `Owner` models to include additional information in the generated OpenAPI schema.
Let's add docstrings to the `Pet` and `Owner` models to include additional information in the generated OpenAPI document.

```python
import yaml
Expand Down Expand Up @@ -559,9 +559,9 @@ components:

The `Pet` schema now also includes a description field, derived from the docstring we added to the `Pet` Pydantic model.

### Adding OpenAPI Titles and Descriptions to Pydantic Fields
### Adding OpenAPI titles and descriptions to Pydantic fields

Let's add titles and descriptions to the fields of the `Pet` and `Owner` models to include additional information in the generated OpenAPI schema.
Let's add titles and descriptions to the fields of the `Pet` and `Owner` models to include additional information in the generated OpenAPI document.

We'll use the `Field` class from Pydantic to add descriptions to the fields.

Expand Down Expand Up @@ -686,7 +686,7 @@ components:
type: object
```

### Adding OpenAPI Example Values to Pydantic Models
### Adding OpenAPI example values to Pydantic models

Examples help API users understand your API's data structures, and some SDK and documentation generators use OpenAPI example values to generate useful code snippets and documentation.

Expand Down Expand Up @@ -857,7 +857,7 @@ components:
type: object
```

### Marking Fields as Optional in Pydantic Models
### Marking fields as optional in Pydantic models

By default, Pydantic marks all fields as required. You can mark a field as optional by setting the `default` parameter to `None`.

Expand Down Expand Up @@ -1028,7 +1028,7 @@ components:
type: object
```

### Adding Enums to OpenAPI using Pydantic Models
### Adding enums to OpenAPI using Pydantic models

Enums in OpenAPI are useful for defining a set of possible values for a field.

Expand Down Expand Up @@ -1135,7 +1135,7 @@ if __name__ == "__main__":
print_json_schema([Pet, Owner])
```

In our generated OpenAPI schema, we have a new `pet_type` field in the `Pet` schema.
In our generated OpenAPI document, we have a new `pet_type` field in the `Pet` schema.

```yaml
openapi: 3.1.0
Expand Down Expand Up @@ -1236,31 +1236,31 @@ components:

This enum is represented as a separate schema in the OpenAPI document.

## Adding Paths and Operations to the OpenAPI Schema
## Adding paths and operations to the OpenAPI document

Now that we have generated an OpenAPI schema from our Pydantic models, we can use the schema to generate SDK clients for our API.
Now that we have generated an OpenAPI document from our Pydantic models, we can use the schema to generate SDK clients for our API.

However, the OpenAPI document we generated, while valid, does not include the `paths` section, which defines the API endpoints and operations.

When using Pydantic with FastAPI, you can define your API endpoints and operations directly in your FastAPI application. [FastAPI automatically generates the OpenAPI schema for your API](./fastapi.mdx), including the `paths` section.
When using Pydantic with FastAPI, you can define your API endpoints and operations directly in your FastAPI application. [FastAPI automatically generates the OpenAPI document for your API](/openapi/frameworks/fastapi#speakeasy-integration), including the `paths` section.

Let's see how we can define API endpoints and operations in a framework-agnostic way and add them to the OpenAPI schema.
Let's see how we can define API endpoints and operations in a framework-agnostic way and add them to the OpenAPI document.

### Install openapi-pydantic
### Installing openapi-pydantic

We'll use the [`openapi-pydantic`](https://github.com/mike-oakley/openapi-pydantic/) library to define a complete OpenAPI schema with paths and operations.
We'll use the [`openapi-pydantic`](https://github.com/mike-oakley/openapi-pydantic/) library to define a complete OpenAPI document with paths and operations.

The benefit of using `openapi-pydantic` is that it allows you to define the API endpoints and operations in a Python dictionary, while still getting the benefit of Pydantic's IDE support and type checking.
The benefit of using `openapi-pydantic` is that it allows you to define the API endpoints and operations in a Python dictionary while still getting the benefit of Pydantic's IDE support and type checking.

The library includes convenience methods to convert Pydantic models to OpenAPI schema components and add them to the OpenAPI schema.
The library includes convenience methods to convert Pydantic models to OpenAPI document components and to add them to the OpenAPI document.

Install the `openapi-pydantic` library:

```bash Terminal
pip install openapi-pydantic
```

### Define API Endpoints
### Defining API endpoints

Create a new file called `api.py` to define the API endpoints using the `openapi-pydantic` library:

Expand Down Expand Up @@ -1474,13 +1474,13 @@ components:

The generated OpenAPI document includes all the components from our Pydantic models, along with the API endpoints we defined. The schemas include all the titles, descriptions, examples, and other details we added to our Pydantic models.

## Generating an SDK from the OpenAPI Schema
## Generating an SDK from the OpenAPI document

Now that we have a complete OpenAPI schema with paths and operations, we can use it to generate an SDK client for our API.
Now that we have a complete OpenAPI document with paths and operations, we can use it to generate an SDK client for our API.

### Prerequisites for SDK Generation
### Prerequisites for SDK generation

Install Speakeasy by following the [Speakeasy installation instructions](/docs/speakeasy-cli/getting-started#install).
Install Speakeasy by following the [Speakeasy installation instructions](/docs/speakeasy-reference/cli/getting-started#install)

On macOS, you can install Speakeasy using Homebrew:

Expand All @@ -1494,29 +1494,41 @@ Authenticate with Speakeasy using the following command:
speakeasy auth login
```

### Generate an SDK Using Speakeasy
### Generating an SDK using Speakeasy

Run the following command to generate an SDK from the `openapi.yaml` file:

```bash Terminal
speakeasy quickstart
```

Follow the onscreen prompts to provide the necessary configuration details for your new SDK such as the name, schema location and output path. Enter `openapi.yaml` when prompted for the OpenAPI document location and select TypeScript when prompted for which language you would like to generate.
Follow the onscreen prompts to provide the necessary configuration details for your new SDK, such as the name, schema location, and output path. Enter `openapi.yaml` when prompted for the OpenAPI document location and select TypeScript when prompted for which language you would like to generate.

### Adding Speakeasy Extensions to the OpenAPI Schema
Speakeasy [validates](/docs/core-concepts#validation) the OpenAPI document to check that it's ready for code generation. Validation issues will be printed in the terminal. The generated SDK will be saved as a folder in your project.

Speakeasy uses [OpenAPI extensions](../../openapi/extensions.md) to provide additional information for generating SDKs.
![Speakeasy quickstart command output](./assets/pydantic/speakeasy-quickstart-output.png)

We can add extensions using [OpenAPI Overlays](../../openapi/overlays.mdx), which are YAML files that [Speakeasy overlays on top of the OpenAPI schema](/docs/prep-openapi/overlays/create-overlays).
Speakeasy also suggests improvements for your SDK using [Speakeasy Suggest](/docs/prep-openapi/maintenance), which is an AI-powered tool in Speakeasy Studio. You can view the suggestions in Speakeasy Studio:

Alternatively, you can add extensions directly to the OpenAPI schema using the `x-` prefix.
![Speakeasy Studio suggestions](./assets/pydantic/speakeasy-studio-suggestions.png)

For example, you can add the [`x-speakeasy-retries` extension](../../docs/customize-sdks/retries.mdx) to have Speakeasy generate retry logic in the SDK.
### Adding Speakeasy extensions to the OpenAPI document

Speakeasy uses [OpenAPI extensions](/openapi/extensions) to provide additional information for generating SDKs.

We can add extensions using [OpenAPI overlays](/openapi/overlays), which are YAML files that [Speakeasy lays on top of the OpenAPI document](/docs/prep-openapi/overlays/create-overlays).

We can use overlays alongside [OpenAPI transformations](/docs/prep-openapi/transformations) to improve the OpenAPI document for SDK generation.

Transformations are predefined functions that allow you to remove unused components, filter operations, and format your OpenAPI document. Unlike overlays, transformations directly modify the OpenAPI document itself.

Note that for Speakeasy OpenAPI extensions, you can also add extensions directly to the OpenAPI document using the `x-` prefix.

For example, you can add the [`x-speakeasy-retries`](/docs/customize/runtime/retries) extension to have Speakeasy generate retry logic in the SDK.

Import the `Dict` and `Any` types from the `typing` module in `api.py`, and `ConfigDict` from `pydantic`.

We'll use these types to define the `x-speakeasy-retries` extension in the OpenAPI schema.
We'll use these types to define the `x-speakeasy-retries` extension in the OpenAPI document.

```python api.py
from typing import List, Dict, Any
Expand Down Expand Up @@ -1569,7 +1581,7 @@ def construct_base_open_api() -> OpenAPIwithRetries:
)
```

This produces an OpenAPI schema with retry functionality:
This produces an OpenAPI document with retry functionality:

```yaml openapi.yaml
x-speakeasy-retries:
Expand All @@ -1584,9 +1596,9 @@ x-speakeasy-retries:
retryConnectionErrors: true
```

### Add Tags to the OpenAPI Schema
### Adding tags to the OpenAPI document

To group operations in the OpenAPI schema, you can use tags. This also allows Speakeasy to structure the generated SDK code and documentation logically.
To group operations in the OpenAPI document, you can use tags. This also allows Speakeasy to structure the generated SDK code and documentation logically.

Add a `tags` field to the `OpenAPIwithRetries` object, then add a `tags` field to each operation in the `construct_base_open_api` function:

Expand Down Expand Up @@ -1624,12 +1636,24 @@ python api.py
speakeasy quickstart
```

Speakeasy will detect the changes to your OpenAPI schema, generate the SDK with the updated tags, and automatically increment the SDK's version number.
Speakeasy will detect the changes to your OpenAPI document, generate the SDK with the updated tags, and automatically increment the SDK's version number.

Take a look at the generated SDK to see how Speakeasy groups operations by tags.

## We Can Help Get Your Pydantic Models Ready for SDK Generation
In the SDK `README.md` file, you'll find documentation about your Speakeasy SDK. TypeScript SDKs generated with Speakeasy include an installable [Model Context Protocol (MCP) server](/docs/model-context-protocol) where the various SDK methods are exposed as tools that AI applications can invoke. Your SDK documentation includes instructions for installing the MCP server.

Note that the SDK is not ready for production use. To get it production-ready, follow the steps outlined in your Speakeasy Studio workspace.

## How Speakeasy helps get your Pydantic models ready for SDK generation

In this tutorial, we learned how to generate an OpenAPI schema from Pydantic models and use it to generate an SDK client using Speakeasy.
In this tutorial, we learned how to generate an OpenAPI document from Pydantic models and use it to generate an SDK client using Speakeasy.

If you would like to discuss how to get your Pydantic models ready for SDK generation, give us feedback, or shoot the breeze about all things OpenAPI and SDKs, [join our Slack](https://join.slack.com/t/speakeasy-dev/shared_invite/zt-1cwb3flxz-lS5SyZxAsF_3NOq5xc8Cjw).

If you haven't already, take a look at our [blog](/blog) to learn more about API design, SDK generation, and our latest features, including:

- [Native JSONL support in your SDKs](/blog/release-jsonl-support)
- [Introducing comprehensive SDK testing](/blog/release-sdk-testing)
- [Model Context Protocol: TypeScript SDKs for the agentic AI ecosystem](/blog/release-model-context-protocol)
- [Python generation with async and Pydantic support](/blog/release-python)
- [Choosing your Python REST API framework](/blog/choosing-your-framework-python)