Skip to content

Repository files navigation

Warning

Early Development: This project is under active development. APIs may change.


openapi-burrito logo

openapi-burrito

Wrap your OpenAPI specs in type-safe Python clients

CI PyPI version Python License OpenAPI

Table of Contents

Quick Start

# Install
uv tool install openapi-burrito

# Generate
openapi-burrito generate openapi.json -o ./my_client
from my_client import AsyncClient

api = AsyncClient(base_url="https://api.example.com")

# Path-first API: type-checked paths and snake_case parameters
res = await api.GET("/users/{user_id}", user_id=123)

if res.is_success:
    print(res.data)
else:
    print(f"Error {res.status_code}: {res.error}")

# Or let errors raise: unwrap() returns the typed body directly
user = (await api.GET("/users/{user_id}", user_id=123)).unwrap()

await needs an async context: wrap calls in an async def + asyncio.run(...), or try snippets interactively with python -m asyncio.

Prefer sync? Generate with --client sync and drop the awaits — same paths, same overloads, httpx.Client underneath:

from my_client import Client

api = Client(base_url="https://api.example.com")
res = api.GET("/users/{user_id}", user_id=123)

Features

  • Path-First API - Call endpoints by path literal (api.GET("/users/{user_id}")), with full IDE autocomplete for paths and parameters
  • Type-Safe - TypedDict models and @overload signatures; generated code passes mypy --strict
  • Async by Default - AsyncClient out of the box; --client sync or --client both when you need the synchronous Client
  • Zero Runtime - Generated code is yours; its only dependency is httpx
  • httpx-Based - Connection pooling, timeouts, all httpx client features
  • Middleware System - Logging, retry, auth via composable middleware
  • Snake Case Params - Path parameters auto-converted to Python style ({userId}{user_id})

Philosophy: Types Without Runtime Magic

This library has exactly one opinion: your types should come from the spec, and your runtime should stay out of the way.

  • Dicts in, dicts out. Responses are plain dicts typed as TypedDict — no model classes to instantiate, serialize, or fight with. res.data IS the parsed JSON.
  • No validation, no coercion. The generated client does not validate payloads against the schema and does not convert strings to datetime. Your type checker verifies structure at development time; at runtime you get what the API sent, untouched.
  • No inheritance hooks, no plugins, no config file. One command in, one small readable package out.

If you want runtime validation and rich models, you want a pydantic-based generator like openapi-python-client — that's a great tool with a different philosophy. openapi-burrito is for when you'd rather have the thinnest possible typed layer over httpx.

If you build FastAPI services, this will feel like home: the same httpx + type-hints + async idioms you already use, pointed at the APIs you consume instead of the ones you serve.

Installation

For Users

# As a CLI tool (recommended)
uv tool install openapi-burrito

# With preview server support (Swagger UI, Redoc)
uv tool install openapi-burrito[preview]

For Developers

# Clone and install all dev dependencies
git clone https://github.com/simon-lund/openapi-burrito.git
cd openapi-burrito
make install

# Run linting and type checks
make lint

# Run tests
make test

Security

This generator sanitizes identifiers and string literals to prevent code injection from malformed OpenAPI specs. However, always review untrusted specs before generating.

Parser Safety Audit

All fields output by the parser are validated/sanitized:

Field Validation Notes
Model/param names sanitize(mode="id") Converted to valid Python identifiers
Model property keys Identifier check / JSON-escape Plain identifiers render in class syntax; everything else is JSON-escaped in functional TypedDict syntax (keys must match the wire format)
Paths sanitize(mode="str") String-escaped for literals
Descriptions/docs sanitize(mode="doc") Docstring-escaped (incl. backslashes)
type strings Type translator Built from validated schema types
method HTTPMethod enum Only known HTTP methods allowed
in (param location) Enum check Only path|query|header|cookie
required, read_only, write_only bool() cast Forced to boolean
default repr() Python string representation
pyproject.toml metadata JSON-escape TOML-safe string literals

Additionally, every generated .py file must pass compile() and the pyproject.toml must parse as TOML before anything is written to disk — malformed output aborts generation instead of landing in your project.

A malicious spec could attempt injection like:

components:
  schemas:
    "User:\n    pass\nimport os; os.system('rm -rf /')  # ":
      type: object

While this generator escapes such payloads, the safest approach is to only generate clients from trusted sources.

See CVE-2020-15142 for an example of this vulnerability class in other generators.

Documentation

Guide Description
Introduction Installation and basic usage
Authentication API keys, tokens, OAuth patterns
Middleware Logging, retry, custom handling
Type System UNSET, Unknown, NotRequired, limitations
CLI Reference generate and preview commands
Contributing Development setup and guidelines

Examples

See the examples/ directory:

Star History

Star History Chart

About

A CLI tool to generate a type-safe, path based Python client from an OpenAPI specification.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages