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:
...
payloadis a Pydantic input model.depsis the generated dependency container.contextcontains 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 namestep: execution order inside the servicedescription: optional function descriptiondependencies: optional named dependencieserrors: 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
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
afd6292a6b16110edc01d400e5b177b19fe0b40fcdbbd0092c7283e122ae7e3e
|
|
| MD5 |
2754d6526b1e2a18c5387cf7ab4ad09d
|
|
| BLAKE2b-256 |
882f4ba1eb9a4ab68386448efe4f0c44d94d4da72f0c70a0f2cda4be79f60507
|
File details
Details for the file function_api_builder-0.1.2-py3-none-any.whl.
File metadata
- Download URL: function_api_builder-0.1.2-py3-none-any.whl
- Upload date:
- Size: 13.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7026171b9acaef6a9a87164bc624f9273eb55ae84846c3e7eac8709f8be83f9a
|
|
| MD5 |
90e338583809886e45db904504502cf4
|
|
| BLAKE2b-256 |
c22fe209568ce4c5339a8830f66a4dcb07f20648dc2c23a3cb31277856b260ef
|