Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

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 the 0.5 release candidate

The core validation and runtime engine requires only PyYAML:

pip install "apizit-linking==0.5.0rc1"

Install the local FastAPI preview as an optional extra:

pip install "apizit-linking[preview]==0.5.0rc1"
apizit-linking validate .
apizit-linking preview . --port 8080

Version 0.5.0rc1 is a public-beta release candidate intended for evaluation before 0.5.0. Pin it exactly; ordinary unpinned installs do not select pre-releases. Keep production deployments on 0.4.0 until the candidate has passed their integration tests. 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:

  • path
  • query
  • header
  • body
  • form
  • file

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.0rc1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for apizit-linking 0.5.0rc1
File Size Uploaded
apizit_linking-0.5.0rc1.tar.gz 95.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for apizit-linking 0.5.0rc1
File Interpreter ABI Platform
apizit_linking-0.5.0rc1-py3-none-any.whl Python 3 none any Details

Total release size: 144.9 kB

Release files / apizit_linking-0.5.0rc1.tar.gz

Download URL apizit_linking-0.5.0rc1.tar.gz
Size 95.4 kB
Tags Source
SHA-256 checksum
How to use checksums
c124bfc7bc5a8dec92363ac6cd86c82c1e31e8d3ae48339a5d60e926ea1fce0e
BLAKE2b-256 checksum
How to use checksums
3fd6b72c2336bad3e1216ab4eb604a1993e47d3620da74dc033e13d569e47889
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

Release files / apizit_linking-0.5.0rc1-py3-none-any.whl

Download URL apizit_linking-0.5.0rc1-py3-none-any.whl
Size 49.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
678ec587b4a6db87ab35e5b5f6c7282bc053e53483005e9f9d57bb80d3560bb6
BLAKE2b-256 checksum
How to use checksums
c26f2d74d6176c84acd29bb2d7969d19ba03af98e3d33ead84be6b2c4a66a681
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
Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page