APIZIT Linking
Keep the code. Add the API.
apizit-linking is a standalone declarative Python-to-HTTP binding engine. It
turns a versioned configuration file into validated HTTP routes while keeping
customer Python code unchanged. APIZIT is one platform that consumes it, not a
dependency of the package.
Documentation · Forkable examples · Public support and issues
def create_customer(customer_name: str, age: int):
return {"name": customer_name, "age": age}
version: 1
routes:
- path: /customers
method: POST
function: customer_service:create_customer
parameters:
customer_name:
source:
location: body
name: name
age:
source:
location: body
name: age
There are no APIZIT decorators, imports, handlers, or web routes in customer code.
Install 0.5
The core validation and runtime engine requires only PyYAML:
pip install "apizit-linking==0.5.0"
Install the local FastAPI preview as an optional extra:
pip install "apizit-linking[preview]==0.5.0"
apizit-linking validate .
apizit-linking preview . --port 8080
Version 0.5.0 is a public beta. Pin it exactly for reproducible builds. The public compatibility policy separates package, Python API, manifest schema, diagnostics, and runtime-artifact guarantees.
Validate locally
The command searches the target directory for apizit_linking.yaml,
apizit_linking.yml, then apizit_linking.json:
apizit-linking validate .
apizit-linking validate . --json
apizit-linking validate path/to/apizit_linking.yaml --project-root .
Validation is static. It parses the customer module with the Python AST and does not import or execute customer code.
Preview locally
apizit-linking preview . --port 8080
Preview binds to 127.0.0.1 by default. It validates before importing customer
modules, then executes them in the server process. Binding to a non-loopback
interface requires --allow-network.
The development server exposes interactive Swagger documentation at /docs,
ReDoc at /redoc, and its OpenAPI 3.1 document at /openapi.json. The document
describes explicit path/query/header/body/form/file bindings, repeated values,
the stable Linking 400 error, and a minimal 200 response inferred from the
Python return annotation.
The preview server is a development tool, not an authentication layer, a production deployment boundary, or a sandbox. Linked customer modules are ordinary trusted Python code and may execute arbitrary code when imported or called.
Forkable example projects
The independent public APIZIT Linking examples repository contains a runnable Hello World starter and five additional projects covering path/query parameters, JSON bodies, errors, packages, and a CRUD-style Task API. It is the single source of truth for user-facing examples.
git clone https://github.com/chipsi44/apizit-linking-examples.git
cd apizit-linking-examples
python -m pip install -r requirements.txt
apizit-linking validate .
apizit-linking preview . --port 8080
Every business module in that repository imports neither APIZIT Linking nor a web framework. Fork it as a starter or pin one of its commits as an APIZIT integration fixture.
V1 configuration reference
The root document is a closed, versioned object:
version: 1
runtime:
language: python
version: "3.12"
routes:
- path: /customers/{customer_id}
method: PATCH
function: customer_service:update_customer
Editor completion and structural validation use the canonical JSON Schema.
function uses the canonical dotted module:function form. path must be an
absolute HTTP path and route placeholders use {parameter_name}. Canonical
methods are uppercase and must be one of GET, POST, PUT, PATCH,
DELETE, OPTIONS, or HEAD; the compiler normalizes case-insensitive
migration input.
The compiler verifies module and function existence, top-level callability,
supported signatures, parameter bindings, request-source compatibility, and
route collisions. A static sibling such as /customers/search is registered
before /customers/{customer_id} regardless of declaration order. Cross-shaped
patterns that overlap without a safe specificity order are rejected as
ROUTE_AMBIGUITY.
Explicit parameter sources
The canonical source syntax is a structured object:
parameters:
customer_name:
source:
location: body
name: name
This binds HTTP body field name to Python parameter customer_name. When a
source is explicit, only that source is inspected. There is no fallback to
another source.
V1 supports:
pathqueryheaderbodyformfile
Header names are case-insensitive; other external names are exact. A route
cannot require both a JSON body value and a form or file value because
those request encodings are incompatible.
Automatic parameter resolution
If a parameter has no explicit source, V1 searches its Python name in this stable order:
path > query > header > body > form > file
The first present source wins. A required absent parameter produces
PARAMETER_NOT_FOUND; explicit mode produces
PARAMETER_NOT_FOUND_IN_SOURCE. Parameters with Python defaults are omitted
from the generated keyword arguments so Python applies their defaults.
Missing values, JSON null, and empty strings are distinct. null is accepted
only by a nullable annotation. V1 converts primitive str, int, float,
bool, nullable unions, lists, and dictionaries. If one annotation contains an
unknown forward reference, other resolvable annotations are still converted.
Stable error shape
Request errors use a JSON object:
{
"error": {
"code": "PARAMETER_NOT_FOUND_IN_SOURCE",
"message": "Required field 'name' was not found in request source 'body'.",
"parameter": "customer_name",
"external_name": "name",
"source": "body"
}
}
Configuration diagnostics include a stable code, severity, field, route index, parameter, and relevant source metadata. The beta does not yet guarantee that new minor releases will never add diagnostic codes or metadata fields.
Python API
Platform adapters compile with compile_linking_file, serialize the complete
validated CompilationResult with to_runtime_dict(), then consume that
closed, versioned artifact through
create_app_from_runtime_artifact. Compilation is the static boundary;
customer imports happen only through the runtime loader, which verifies that
the packaged function signatures, sync/async callable kind, and return
annotation still match the compiled contract.
The optional ASGI adapter is available without changing customer code:
from apizit_linking.fastapi import create_app
app = create_app(".")
Platforms may wrap that app with their own server, authentication, metering, or
deployment layer. Reusable FastAPI factories keep documentation routes disabled
by default so deployment adapters do not expose them accidentally; pass
docs=True to enable /docs, /redoc, and /openapi.json. If one of those
paths (including Swagger's OAuth redirect) could be handled by a linked route,
the adapter moves the documentation endpoints under a safe generated prefix and
exposes the selected URLs on the FastAPI app.
OpenAPI metadata is generated statically from the same compiled route contract
stored in the versioned runtime artifact. It does not invoke customer functions
or delegate request validation to FastAPI, so Linking keeps its documented
400 errors instead of introducing FastAPI 422 errors. Primitive, nullable,
list, and dictionary annotations produce JSON schemas. Missing or custom
annotations remain unconstrained. Return schemas are documentary: the adapter
performs no annotation-based validation or transformation of customer return
values. FastAPI still performs its normal response serialization.
Automatic parameters are shown through a portable query representation and an
x-apizit-automatic-binding extension that preserves the real resolution order
and alternative sources. See
docs/adr/0001-documentary-openapi-and-minimal-responses.md
for the complete contract and its intentionally deferred features.
Package scope
The package owns discovery, YAML/YML/JSON parsing, closed V1 validation, safe
static module:function resolution, AST signature inspection, compilation,
structured diagnostics, request-context resolution, primitive conversion,
sync/async invocation, and the optional FastAPI preview.
It intentionally does not own Mangum, API Gateway, Lambda, deployment, metering, or APIZIT scan UI/reporting. The core installation remains independent of FastAPI.
Development
Maintainers working from an authorized source checkout can run:
uv sync --all-extras --all-groups
uv run python -m unittest discover -s tests -p "test_*.py"
uv run ruff check src tests
uv run black --check src tests
uv build
The complete V1 reference, release procedure, remaining work, and test support are included in the source distribution. The public example gallery is maintained separately. APIZIT Linking is licensed under Apache-2.0.
Metadata
Release files for apizit-linking 0.5.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| apizit_linking-0.5.0.tar.gz | 95.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| apizit_linking-0.5.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 144.7 kB
Release files / apizit_linking-0.5.0.tar.gz
| Download URL | apizit_linking-0.5.0.tar.gz |
|---|---|
| Size | 95.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
60d8987b8ed5d2d64becf16c3d7c7a8bdd0a01a9cc0689dbacd59cabf2f0e8aa
|
|
BLAKE2b-256 checksum How to use checksums |
8666aba87444eb29efd25c1af5789679fb83ce0f5f8d3c9bd5012b596aea8c04
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.14
|
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 Jul 23, 2026.
Transparency logRelease files / apizit_linking-0.5.0-py3-none-any.whl
| Download URL | apizit_linking-0.5.0-py3-none-any.whl |
|---|---|
| Size | 49.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
b67177f45cd62647b57e2d9d924c472e42f0095ecba01f276c9af07d1467286f
|
|
BLAKE2b-256 checksum How to use checksums |
da195c3d85b94c4b612745d1da49b4a69a808dd48825c92dfc5ad2e14faba0bd
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.14
|
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 Jul 23, 2026.
Transparency log