Skip to main content

Generate complete FastAPI applications from decorated Python business functions.

Project description

API Builder

Generate a complete FastAPI application from decorated Python business functions.

Status

This project is alpha software. The intended PyPI distribution name is api-builder. PyPI currently rejects that exact name as too similar to an existing project, so the first published release is temporarily available as function-api-builder while the name issue is resolved.

Install

Intended install command:

pip install api-builder

Current published fallback:

pip install function-api-builder

Both distributions expose the same Python packages and the same api-builder command.

What It Does

API Builder turns plain, typed business functions into a runnable FastAPI service. You write the business logic once. The builder discovers those functions, validates their metadata and Pydantic models, then generates an app/ directory containing:

  • public service routes
  • optional local development routes for individual functions
  • request validation through Pydantic
  • service sequencing
  • dependency and request-context containers
  • standard error responses
  • health checks
  • OpenAPI documentation
  • generated smoke tests

The generated application is ordinary Python code. After generation, run it with Uvicorn or edit the generated app as part of your application workflow.

End-to-End Flow

The complete flow is:

functions/**/*.py
        |
        |  @function metadata + type annotations
        v
  discovery and import
        |
        |  signature, models, steps, routes, dependencies
        v
       validation
        |
        |  generated Python modules and manifest
        v
      app/ directory
        |
        |  FastAPI startup imports generated routers
        v
  HTTP API + OpenAPI

1. Write a business function

Business functions live under functions/. Every function exposed by the builder uses the same three-argument contract:

def business_function(payload, deps, context) -> OutputModel:
    ...
  • payload is a Pydantic input model.
  • deps is the generated dependency container.
  • context contains request metadata and the current service execution context.
  • The return annotation is a Pydantic output model.

The function may be synchronous or asynchronous.

2. Decorate it with service metadata

from pydantic import BaseModel
from api_builder_runtime import function


class EchoInput(BaseModel):
    message: str


class EchoOutput(BaseModel):
    message: str


@function(service="echo", step=1)
def echo(payload: EchoInput, deps, context) -> EchoOutput:
    return EchoOutput(message=payload.message)

The decorator records the metadata needed by the builder:

  • service: the public service name
  • step: execution order inside the service
  • description: optional function description
  • dependencies: optional named dependencies
  • errors: optional application error codes and HTTP statuses

The decorator does not execute the function. It marks the function for discovery.

3. Run the builder

From the root of the project containing functions/:

api-builder

Useful options:

api-builder --check                 # validate without writing app/
api-builder --force                 # overwrite generated files
api-builder --service echo          # generate one service
api-builder --no-dev-routes         # omit local function routes
api-builder --project-root ./demo   # build another project

4. Run the generated API

uvicorn app.main:app --reload

The public route for the echo service is:

curl -X POST http://127.0.0.1:8000/api/v1/echo \
  -H 'content-type: application/json' \
  -d '{"message":"hello"}'

The response uses the generated standard envelope:

{
  "data": {
    "message": "hello"
  }
}

OpenAPI is available at /docs and /openapi.json. Health status is available at /healthz.

Multi-Step Services

A service can contain multiple functions. Steps run in ascending order, and the output of each step becomes the input for the next step.

class ReadInput(BaseModel):
    file_reference: str


class ReadOutput(BaseModel):
    text: str


class SummarizeInput(BaseModel):
    text: str


class SummarizeOutput(BaseModel):
    summary: str


@function(service="document", step=1)
async def read_document(
    payload: ReadInput, deps, context
) -> ReadOutput:
    return ReadOutput(text="Document contents")


@function(service="document", step=2)
async def summarize_document(
    payload: SummarizeInput, deps, context
) -> SummarizeOutput:
    return SummarizeOutput(summary=payload.text)

The builder validates that:

  • steps are unique
  • steps are contiguous, starting at 1
  • required fields needed by the next step are produced by the previous step
  • generated route paths and operation IDs are unique

The public route remains one service route:

POST /api/v1/document

Generated Project Layout

Running api-builder creates this shape:

app/
├── config.py                 # environment-backed settings
├── context.py                # request execution context
├── dependencies.py           # named dependency container
├── errors.py                 # standard exception mapping
├── health.py                 # GET /healthz
├── main.py                   # FastAPI application factory
├── middleware.py             # request middleware
├── responses.py              # response envelopes
├── routers/
│   ├── public.py             # service routes
│   └── dev.py                # local function routes
├── services/                 # generated service orchestration
├── generated/
│   ├── function_registry.py  # discovered function registry
│   ├── service_registry.py   # service registry
│   ├── manifest.py           # runtime metadata
│   └── manifest.json         # inspectable metadata
└── tests/                    # generated health/OpenAPI tests

Generated files contain a header identifying them as generated. Treat the decorated functions under functions/ as the source of truth and regenerate after changing their metadata or type models.

Development Routes

When the environment is local, development, or test, API Builder exposes one route per decorated function:

POST /__dev/functions/{service}/{function}

These routes require the X-Internal-Dev-Token header. They are excluded from the OpenAPI schema and application entirely in production environments.

Use them to exercise a single step while developing a service. The public service route remains the normal integration boundary.

Errors

Business functions can raise FunctionError:

from api_builder_runtime import FunctionError


raise FunctionError("EMPTY_DOCUMENT", "The document contains no readable text.")

Declare an error status on the decorator when a custom HTTP status is needed:

@function(
    service="document",
    step=2,
    errors={"EMPTY_DOCUMENT": 422},
)
async def summarize_document(payload, deps, context):
    ...

The generated error handler returns a stable API error shape and avoids exposing internal tracebacks or implementation details to clients.

Validation Rules

Build-time validation fails fast when the project contains an invalid function:

  • missing functions/ directory
  • no decorated functions
  • wrong function signature
  • missing or invalid Pydantic input model
  • missing or invalid Pydantic output model
  • invalid service or dependency names
  • duplicate or missing service steps
  • incompatible adjacent step models
  • duplicate routes or operation IDs

Use api-builder --check in CI to validate source functions without changing the working tree.

Example

The repository includes a two-step PDF summary example at:

examples/basic/functions/pdf_summary.py

Build it with:

api-builder --project-root examples/basic --force

Library API

The builder can also be called from Python:

from pathlib import Path
from api_builder import build


result = build(Path("."), force=True)
for route in result.routes:
    print(route.method, route.path)

The runtime decorator is intentionally small and has no application-global registry. Discovery happens when the builder scans the current project.

Local Development

python -m venv .venv
source .venv/bin/activate
pip install -e '.[dev]'
pytest
ruff check src tests examples/basic/functions
mypy src tests
python -m build
python -m twine check dist/*

Scope

API Builder generates application structure and validates the contract between decorated functions. It does not diagnose infrastructure failures, determine root cause, repair runtime systems, or create external service clients automatically. Dependencies are named in function metadata and represented in the generated app; application owners decide how those dependencies are implemented.

License

MIT. See the project metadata for the current author and package version.

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

function_api_builder-0.1.2.tar.gz (13.4 kB view details)

Uploaded Source

Built Distribution

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

function_api_builder-0.1.2-py3-none-any.whl (13.1 kB view details)

Uploaded Python 3

File details

Details for the file function_api_builder-0.1.2.tar.gz.

File metadata

  • Download URL: function_api_builder-0.1.2.tar.gz
  • Upload date:
  • Size: 13.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for function_api_builder-0.1.2.tar.gz
Algorithm Hash digest
SHA256 afd6292a6b16110edc01d400e5b177b19fe0b40fcdbbd0092c7283e122ae7e3e
MD5 2754d6526b1e2a18c5387cf7ab4ad09d
BLAKE2b-256 882f4ba1eb9a4ab68386448efe4f0c44d94d4da72f0c70a0f2cda4be79f60507

See more details on using hashes here.

File details

Details for the file function_api_builder-0.1.2-py3-none-any.whl.

File metadata

File hashes

Hashes for function_api_builder-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 7026171b9acaef6a9a87164bc624f9273eb55ae84846c3e7eac8709f8be83f9a
MD5 90e338583809886e45db904504502cf4
BLAKE2b-256 c22fe209568ce4c5339a8830f66a4dcb07f20648dc2c23a3cb31277856b260ef

See more details on using hashes here.

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