openapi-python-client is a free, open source api development & testing project written in Python and released under MIT. It has 1,993 GitHub stars, 293 forks and 120 open issues, and was last pushed 3 days ago. On this registry it ranks #109 of 178 tracked projects in API Development & Testing, with 5 head-to-head comparisons available.

What is openapi-python-client?

openapi-python-client is a command-line generator that turns OpenAPI 3.0 and 3.1 documents into modern, type-annotated Python client libraries, built for Python developers who consume REST APIs and would rather generate a client from a spec than maintain one by hand.

What it is

openapi-python-client is an open-source Python package that reads an OpenAPI 3.0 or 3.1 document and emits a complete, installable Python client library for that API. It is written in Python and renders its output through Jinja2 templates, a choice the README justifies on the grounds that it makes the generator easier for Python developers to extend and improve. The generated code deliberately leans on current Python features such as type annotations and dataclasses, and the project advertises itself as type-checked with mypy. It does not handle OpenAPI 2.x, also known as Swagger; the README directs users with older documents to upgrade them to version 3 with one of the available converters first.

The concrete problem it solves is the hand-maintained client layer that sits between a documented HTTP API and the Python code that calls it. Rather than writing and then repeatedly re-syncing wrapper classes against a changing specification, a developer points the generator at the spec and receives a library whose modules, request functions and models are derived from it. The generator names the output from the title in the spec — an API titled "My API" produces a directory expected to be "my-api-client" — and the resulting package contains a pyproject.toml, a README.md the user is told to update with project details, and a Python module named after the project (for example my_api_client) holding a client module with both a Client class and an AuthenticatedClient class.

Key capabilities

  • Generates a client directly from a hosted specification with openapi-python-client generate --url https://my.api.com/openapi.json.
  • Accepts a specification on disk instead of a URL through --path location/on/disk/openapi.json.
  • Writes a pyproject.toml with Poetry metadata by default, PDM metadata when passed --meta=pdm, or only Ruff configuration.
  • Emits a client module exposing Client and AuthenticatedClient classes for calls to the target API.
  • Supports a --custom-template-path flag that overlays user templates on the defaults using Jinja2's ChoiceLoader and FileSystemLoader, so only the templates that need changing must be copied.
  • Controls output placement and existing directories with --output-path and --overwrite.
  • Installs shell tab completion via openapi-python-client --install-completion.

Who uses it and how

  • Python teams consuming REST APIs whose providers publish OpenAPI 3.0 or 3.1 documents, including FastAPI-based services, a tag the project carries.
  • Developers who want generated code that survives a strict type check, since the templates target dataclasses and annotations and the project is checked with mypy.
  • Users who already have a Python environment and prefer a generator written in Python, which the README frames as easier to install and use than alternatives in other languages.
  • Contributors and forkers extending generation behaviour through the Jinja2 templates; the repository shows 1,993 stars, 293 forks and 120 open issues.
  • Anyone installing through pipx with --include-deps, so that ruff is available on the path for the post-generation cleanup hook.

Getting started

Install with pipx install openapi-python-client --include-deps (the recommended route, because --include-deps puts ruff on the path for post-generation cleanup), or with plain pip install openapi-python-client. Then run openapi-python-client generate --url https://my.api.com/openapi.json or point --path at a local specification.

How it compares

The facts provided for this page name no paid products that this project replaces, and they name no similar generator to measure it against. On the evidence available, it stands alone in this registry.

When to use it — and when not to

This is a local command-line generator rather than a hosted service, so adopting it means operating nothing beyond a Python environment, network access to fetch a remote spec, and optionally ruff for post-generation cleanup; no database, object storage or mail server is involved. It should not be chosen by teams whose APIs are still described in OpenAPI 2.x/Swagger, since that format is explicitly unsupported, or by teams that need every corner of the OpenAPI specification covered, because the README states the project is still in development and does not support all OpenAPI features. The custom template feature is also described as beta-level, with an undocumented and unstable template API, and the generated README.md is a placeholder the user must rewrite.

project readme (upstream, from github) — read inline

Run Checks codecov MIT license Generic badge PyPI version shields.io Downloads

openapi-python-client

Generate modern Python clients from OpenAPI 3.0 and 3.1 documents.

This generator does not support OpenAPI 2.x FKA Swagger. If you need to use an older document, try upgrading it to version 3 first with one of many available converters.

This project is still in development and does not support all OpenAPI features

Why This?

This tool focuses on creating the best developer experience for Python developers by:

  1. Using all the latest and greatest Python features like type annotations and dataclasses.
  2. Having documentation and usage instructions specific to this one generator.
  3. Being written in Python with Jinja2 templates, making it easier to improve and extend for Python developers. It's also much easier to install and use if you already have Python.

Installation

I recommend you install with pipx so you don't conflict with any other packages you might have: pipx install openapi-python-client --include-deps.

Note the --include-deps option makes ruff available in your path so that openapi-python-client can use it to clean up the generated code.

If you use pipx run then the post-generation hooks will not be available unless you install them manually.

You can also install with normal pip: pip install openapi-python-client

Then, if you want tab completion: openapi-python-client --install-completion

Usage

Create a new client

openapi-python-client generate --url https://my.api.com/openapi.json

This will generate a new client library named based on the title in your OpenAPI spec. For example, if the title of your API is "My API", the expected output will be "my-api-client". You can change that directory name with the config file (documented below) or with --output-path.

If the directory to generate already exists, you'll get an error unless you use --overwrite.

You can use an OpenAPI file instead of a URL like openapi-python-client generate --path location/on/disk/openapi.json.

Using custom templates

This feature leverages Jinja2's ChoiceLoader and FileSystemLoader. This means you do not need to customize every template. Simply copy the template(s) you want to customize from the default template directory to your own custom template directory (file names must match exactly) and pass the template directory through the custom-template-path flag to the generate command:

openapi-python-client generate \
  --url https://my.api.com/openapi.json \
  --custom-template-path=relative/path/to/mytemplates

Be forewarned, this is a beta-level feature in the sense that the API exposed in the templates is undocumented and unstable.

What You Get

  1. A pyproject.toml file, optionally with [Poetry] metadata (default), [PDM] (with --meta=pdm), or only [Ruff] config.
  2. A README.md you'll most definitely need to update with your project's details
  3. A Python module named just like the auto-generated project name (e.g. "my_api_client") which contains:
    1. A client module which will have both a Client class and an AuthenticatedClient class. You'll need these for calling the functions in the api module.
    2. An api module which will contain one module for each tag in your OpenAPI spec, as well as a default module for endpoints without a tag. Each of these modules in turn contains one function for calling each endpoint.
    3. A models module which has all the classes defined by the various schemas in your OpenAPI spec
  4. A setup.py file if you use --meta=setup (default is --meta=poetry)

For a full example you can look at the end_to_end_tests directory which has baseline_openapi_3.0.json and baseline_openapi_3.1.yaml files. The "golden-record" in that same directory is the generated client from either of those OpenAPI documents.

Configuration

You can pass a YAML (or JSON) file to openapi-python-client with the --config option in order to change some behavior. The following parameters are supported:

class_overrides

Used to change the name of generated model classes. This param should be a mapping of existing class name (usually a key in the "schemas" section of your OpenAPI document) to class_name and module_name. As an example, if the name of a model in OpenAPI (and therefore the generated class name) was something like "_PrivateInternalLongName" and you want the generated client's model to be called "ShortName" in a module called "short_name" you could do this:

Example:

class_overrides:
  _PrivateInternalLongName:
    class_name: ShortName
    module_name: short_name

The easiest way to find what needs to be overridden is probably to generate your client and go look at everything in the models folder.

docstrings_on_attributes

By default, when openapi-python-client generates a model class, it includes a list of attributes and their descriptions in the docstring for the class. If you set this option to true, then the attribute descriptions will be put in docstrings for the attributes themselves, and will not be in the class docstring.

docstrings_on_attributes: true

literal_enums

By default, openapi-python-client generates classes inheriting for Enum for enums. It can instead use Literal values for enums by setting this to true:

literal_enums: true

This is especially useful if enum values, when transformed to their Python names, end up conflicting due to case sensitivity or special symbols.

generate_all_tags

openapi-python-client generates module names within the api module based on the OpenAPI tags of each endpoint. By default, only the first tag is generated. If you want to generate duplicate endpoint functions using every tag listed, you can enable this option:

generate_all_tags: true

project_name_override and package_name_override

Used to change the name of generated client library project/package. If the project name is changed but an override for the package name isn't provided, the package name will be converted from the project name using the standard convention (replacing -'s with _'s).

Example:

project_name_override: my-special-project-name
package_name_override: my_extra_special_package_name

field_prefix

When generating properties, the name attribute of the OpenAPI schema will be used. When the name is not a valid Python identifier (e.g. begins with a number) this string will be prepended. Defaults to "field_". It will also be used to prefix fields in schema starting with "_" in order to avoid ambiguous semantics.

Example:

field_prefix: attr_

package_version_override

Specify the package version of the generated client. If unset, the client will use the version of the OpenAPI spec.

Example:

package_version_override: 1.2.3

post_hooks

In the config file, there's an easy way to tell openapi-python-client to run additional commands after generation. Here's an example showing the default commands (using [Ruff]) that will run if you don't override them in config:

post_hooks:
   - "ruff check . --fix-only"
   - "ruff format ."

use_path_prefixes_for_title_model_names

By default, openapi-python-client generates class names which include the full path to the schema, including any parent-types. This can result in very long class names like MyRouteSomeClassAnotherClassResponse—which is very unique and unlikely to cause conflicts with future API additions, but also super verbose.

If you are carefully curating your title properties already to ensure no duplicate class names, you can turn off this prefixing feature by setting use_path_prefixes_for_title_model_names to false in your config file. This will use the title property of any object that has it set without prefixing.

If this option results in

readme truncated — read the full docs on github

Frequently asked questions

Is openapi-python-client free to use?

openapi-python-client is open source under the MIT licence. There is no licence fee and no seat count — you can self-host it or, where the project offers one, pay a vendor for a managed version instead.

What does openapi-python-client do?

Generate modern Python clients from OpenAPI

What is openapi-python-client written in?

openapi-python-client is primarily written in Python. Its source is publicly available at https://github.com/openapi-generators/openapi-python-client, and it has 1,993 GitHub stars.