openapi-python
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.
Installation
uv add openapi-python[httpx] # Ships with an `httpx` transport
uv add openapi-python # Bring your own transport (requests, asyncio, ...)
Client generation
Generate a client from an OpenAPI spec in openapi.json:
# Types + Protocol + HTTP transport
uv run openapi-python generate --spec ./openapi.json --out ./generated
# Types + Protocol
uv run openapi-python generate --spec ./openapi.json --out ./generated --protocol-only
Using generated clients
Generated clients expose route-specific callables with typed params, query, headers, body, and return values.
When using openapi-python[httpx]:
import httpx
from generated.my_client import AsyncClient, Client, DefaultAsyncTransport, DefaultTransport
sync_http = httpx.Client(
base_url="https://api.example.com",
headers={"authorization": "Bearer token"},
)
async_http = httpx.AsyncClient(
base_url="https://api.example.com",
headers={"authorization": "Bearer token"},
)
client = Client(
transport=DefaultTransport(client=sync_http),
)
async_client = AsyncClient(
transport=DefaultAsyncTransport(client=async_http),
)
book = client.get("/books/{book_id}")(params={"book_id": 1})
async_book = await async_client.get("/books/{book_id}")(params={"book_id": 1})
When using openapi-python, or for --protocol-only clients, provide your own transport:
from generated.my_client import Client
client = Client(transport=my_transport)
book = client.get("/books/{book_id}")(params={"book_id": 1})
See Custom transport on how to build a custom transport.
Protocols
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 don't ship with a built-in transport.
Protocol typing can be relaxed independently with --no-routes, --no-requests, and --no-responses.
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,
request_media_type: str | None,
body: object | None,
response_media_type: str | None,
) -> object:
request_kwargs = {"json": body}
if request_media_type and request_media_type != "application/json":
request_kwargs = {"data": body}
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,
**request_kwargs,
)
response.raise_for_status()
if response.content:
return response.json()
return None
client = Client(
transport=RequestsTransport(),
)
book = client.get("/books/{book_id}")(params={"book_id": 1})
Release files for openapi-python 0.0.19
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| openapi_python-0.0.19.tar.gz | 20.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| openapi_python-0.0.19-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 48.1 kB
Release files / openapi_python-0.0.19.tar.gz
| Download URL | openapi_python-0.0.19.tar.gz |
|---|---|
| Size | 20.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
91166b07b7b5b7c7bea5bf46e524ec9c6a98e629ce99320bdce70276fafdc8b6
|
|
BLAKE2b-256 checksum How to use checksums |
c98c6053d705c0b89bf3755c8aed4b90d63a2b032d80d8956497974499b27c14
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jun 26, 2026.
Transparency logRelease files / openapi_python-0.0.19-py3-none-any.whl
| Download URL | openapi_python-0.0.19-py3-none-any.whl |
|---|---|
| Size | 27.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
d2ce1e5f45f0b0807ffba221dfcfb5f38e5563e44dd2e3f0afd08cdd9aa2e8b1
|
|
BLAKE2b-256 checksum How to use checksums |
396d5ef2b4a65ed7a8618d9b46133702565076f892b162b7e44bdd5055226cfb
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jun 26, 2026.
Transparency log