Expose a Python function as an HTTP API without decorators
Put the HTTP route in YAML and leave the Python function alone. APIZIT Linking validates the connection, converts request values from type hints, and can run a local preview—without adding a FastAPI decorator, request object, or infrastructure import to your business code.
What you will build#
This two-file project exposes hello:hello as GET /hello. The optional name query parameter is passed to the ordinary Python function.
hello-api/
├── apizit_linking.yaml
└── hello.pyThe commands below use only the V1 contract retained by the Linking 1.0 stable release. For a reproducible deployment, pin the exact version you have tested.
1. Write the plain Python function#
Create hello.py. There is no APIZIT Linking or web-framework import:
def hello(name: str = "world") -> dict[str, str]:
return {"message": f"Hello, {name}!"}You can still import and test this function normally. It remains useful as Python code even when no HTTP server is running.
2. Link the function with YAML#
Create apizit_linking.yaml beside the module. The module:function target is hello:hello, and the YAML maps the external query field name to the function parameter of the same name.
version: 1
runtime:
language: python
version: "3.12"
routes:
- path: /hello
method: GET
function: hello:hello
parameters:
name:
source:
location: query
name: nameBecause name has a Python default, omitting it from the request leaves it out of the generated keyword arguments and Python applies "world".
See the full Linking YAML reference for path, query, header, body, form, and file sources.
3. Validate and preview#
From inside hello-api, use an activated Python environment and install the preview:
python -m pip install "apizit-linking[preview,models]==1.0.1"Then validate the project:
apizit-linking validate .The successful output ends with:
APIZIT linking definition is valid: …/apizit_linking.yaml
Compiled routes: 1Start the development preview on the loopback interface:
apizit-linking preview . --port 8080In another terminal, call the route:
curl "http://127.0.0.1:8080/hello?name=Ada"Expected response (200 OK):
{"message":"Hello, Ada!"}Calling /hello without the query string returns {"message":"Hello, world!"}.
What happens at runtime#
- Validation is static. The compiler parses the YAML and Python AST, checks the route, module, top-level function, signature, and parameter binding, and does not import your module.
- Preview loads trusted code. Only after validation succeeds does the preview import
hello.pyinto an isolated project namespace. - The adapter resolves inputs. It reads
namefrom the query string, converts supported annotated values, and invokeshello(name=...). - The return value is serialized. The optional FastAPI adapter serializes the ordinary dictionary as JSON.
The HTTP framework is an adapter around the function, not a dependency inside it. That is the core separation APIZIT Linking provides.
V1 limits you should know#
This initial manifest uses legacy conversion and default 200. The 1.0 release can explicitly declare success statuses/headers, domain-error mappings, typed models and permission guards; each is a separate policy choice. Unmapped business errors return a generic JSON 500.
- The preview is a local development tool, not a production security boundary.
- Customer modules are trusted Python code; import isolation is not a sandbox.
- A binding without a pointer selects a top-level JSON field. Opt into JSON pointers and typed models when the input needs a nested contract.
- Legacy return schemas remain documentary. validation: typed prepares runtime input/output adapters and their OpenAPI schemas explicitly.
Read the complete V1 limits before choosing a production adapter.
Next steps#
- Install the package from PyPI.
- Browse the runnable examples.
- Learn every command in the CLI reference.
- Inspect or fork the examples repository.
Use this boundary with an AI assistant#
Ask your assistant to work on the Python behavior first: inputs, return value and domain cases. Review or run those function tests before adding an HTTP route. Then provide the function signature and the intended method, path and parameter sources as a separate task. This keeps the business decision and the HTTP mapping explicit for both the assistant and the reviewer.
Validate the proposed manifest with JSON diagnostics, inspect the affected module:function targets and preview the request cases. Static validation checks supported contracts; it does not prove business correctness or execute the function. Preview imports the project and must only run code you trust. The architecture makes these boundaries inspectable, but lower token usage, faster work and fewer mistakes would need measurement for your own workflow.
Follow the AI-assisted development guide for the complete sequence. For debugging, trace a route back to Python. Compare Flask and FastAPI when you need a different HTTP contract.