Skip to main content

Autogenerated and fully typed OpenAPI Python clients with a developer-friendly, ergonomic interface.

Project description

openapi-python

QA Release PyPI

openapi-python generates typed Python API clients from OpenAPI specs, with a developer-friendly and ergonomic string-literal-based interface strongly inspired by openapi-typescript.

openapi-python demo

Installation

uv add openapi-python         # If you want to define your own HTTP transport (requests, asyncio, ...)
uv add openapi-python[httpx]  # Ships with an `httpx` transport

Client generation

Generate a client from an OpenAPI spec in openapi.json:

# Types + HTTP transport
uv run openapi-python generate --spec ./openapi.json --out ./generated

# Types + custom transport protocol
uv run openapi-python generate --spec ./openapi.json --out ./generated --protocol-only

... or programatically:

from pathlib import Path
from openapi_python import GenerationRequest, generate_client

result = generate_client(
    GenerationRequest(
        spec_source="./openapi.json",
        output_dir=Path("./generated"),
        package_name="my_client",
        overwrite=True,
    )
)

Using generated clients

Generated clients expose route-specific callables with typed params, query, headers, body, and return values.

With the built-in httpx transport:

from generated.my_client import Client

client = Client(base_url="https://api.example.com")
book = client.get("/books/{book_id}")(params={"book_id": 1})

For async APIs:

from generated.my_client import AsyncClient

async_client = AsyncClient(base_url="https://api.example.com")
book = await async_client.get("/books/{book_id}")(params={"book_id": 1})

For protocol-only clients, provide your own transport:

from generated.my_client import Client

client = Client(base_url="https://api.example.com", transport=my_transport)
book = client.get("/books/{book_id}")(params={"book_id": 1})

Extensibility

GeneratorExtensions exposes two safe hooks:

  • normalize_hooks: transform the normalized model before rendering.
  • render_context_hooks: transform rendered file content map before writing.

Transport Decoupling

Generated clients expose a transport protocol. You can plug in your own transport while keeping route-level typing guarantees.

Use --protocol-only to generate clients that require a supplied transport and do not emit the built-in httpx transport classes. By default, generated clients include DefaultTransport and DefaultAsyncTransport, which require the httpx extra when instantiated.

Protocol typing can be relaxed independently with --no-routes, --no-requests, and --no-responses. Those flags replace the corresponding route literals, request payload types, or response types with broad catch-all types.

Built-in httpx transport

Install the httpx extra and generate with the default transport mode:

uv add "openapi-python[httpx]"
uv run openapi-python generate --spec ./openapi.json --out ./generated --package my_client

You can supply preconfigured httpx clients:

import httpx

from generated.my_client import AsyncClient, Client, DefaultAsyncTransport, DefaultTransport

sync_http = httpx.Client(headers={"authorization": "Bearer token"})
async_http = httpx.AsyncClient(headers={"authorization": "Bearer token"})

client = Client(
    base_url="https://api.example.com",
    transport=DefaultTransport(client=sync_http),
)
async_client = AsyncClient(
    base_url="https://api.example.com",
    transport=DefaultAsyncTransport(client=async_http),
)

Custom transport

Install openapi-python without extras and generate protocol-only code:

uv add openapi-python requests
uv run openapi-python generate \
  --spec ./openapi.json \
  --out ./generated \
  --package my_client \
  --protocol-only

Then provide an object that satisfies the generated Transport protocol:

from collections.abc import Mapping

import requests

from generated.my_client import Client


class RequestsTransport:
    def request(
        self,
        *,
        method: str,
        route: str,
        base_url: str,
        params: Mapping[str, object] | None,
        query: Mapping[str, object] | None,
        headers: Mapping[str, object] | None,
        body: object | None,
    ) -> object:
        response = requests.request(
            method=method.upper(),
            url=f"{base_url.rstrip('/')}{route.format(**(params or {}))}",
            params={key: str(value) for key, value in (query or {}).items()} or None,
            headers={key: str(value) for key, value in (headers or {}).items()} or None,
            json=body,
        )
        response.raise_for_status()
        if response.content:
            return response.json()
        return None


client = Client(
    base_url="https://api.example.com",
    transport=RequestsTransport(),
)
book = client.get("/books/{book_id}")(params={"book_id": 1})

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

openapi_python-0.0.13.tar.gz (19.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

openapi_python-0.0.13-py3-none-any.whl (28.1 kB view details)

Uploaded Python 3

File details

Details for the file openapi_python-0.0.13.tar.gz.

File metadata

  • Download URL: openapi_python-0.0.13.tar.gz
  • Upload date:
  • Size: 19.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for openapi_python-0.0.13.tar.gz
Algorithm Hash digest
SHA256 028389e49b8c7b59e6d8b0df46d6ca2e0860ce3615d262ea4dcdef972e6e1bae
MD5 274e629d983320f21fc0be2a56a5b79e
BLAKE2b-256 3eb66d6218742da7eab2ef454f2630adc7f984bf3a58e4f4ea20c73f919a6c36

See more details on using hashes here.

Provenance

The following attestation bundles were made for openapi_python-0.0.13.tar.gz:

Publisher: release.yml on Minibrams/openapi-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file openapi_python-0.0.13-py3-none-any.whl.

File metadata

  • Download URL: openapi_python-0.0.13-py3-none-any.whl
  • Upload date:
  • Size: 28.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for openapi_python-0.0.13-py3-none-any.whl
Algorithm Hash digest
SHA256 59a5627094dc66a8dd52c4930c780525d7b71cb2296fd5f9099d95bc163ab172
MD5 2058392b4cbd96a65d8ba86f56264e0c
BLAKE2b-256 9844b3f2d510636c5f6c1c1e4b52b4fb3b0ec4eed6405bbbbdc776b6ac3c0f8d

See more details on using hashes here.

Provenance

The following attestation bundles were made for openapi_python-0.0.13-py3-none-any.whl:

Publisher: release.yml on Minibrams/openapi-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page