The minimalistic API framework for Quart — input/output validation and OpenAPI from Pydantic
Project description
apiquart
The minimalistic API framework for Quart — declarative request/response validation and automatic OpenAPI 3.1 docs, built on Pydantic v2.
apiquart brings APIFlask-style ergonomics to Quart's
async-native world. It is a thin layer over vanilla Quart and Pydantic: an
APIQuart app is a quart.Quart subclass, your schemas are plain Pydantic
models, and removing every decorator still leaves a working route.
@app.input— parse and validate the request (json/query/form/files/ headers/cookies/path); the validated model instance is injected as an argument.@app.output— serialize the return value (ORM object, dict, or model) through Pydantic.@app.doc— attach OpenAPI operation metadata.@app.auth_required— first-class auth via quart-httpauth.- OpenAPI 3.1 generated straight from your Pydantic models, with four
interactive doc UIs behind a single
/docsendpoint.
Installation
pip install apiquart
The distribution name is apiquart; the import name is apiquart. Optional
extras: apiquart[auth] (quart-httpauth), apiquart[yaml] (YAML spec output).
Quickstart
from apiquart import APIQuart, BaseModel, abort
app = APIQuart(__name__, title="Pets API", version="1.0.0")
class PetIn(BaseModel):
name: str
category: str = "other"
class PetOut(PetIn):
id: int
pets: dict[int, dict] = {}
@app.post("/pets")
@app.input(PetIn, arg_name="pet")
@app.output(PetOut, status_code=201)
async def create_pet(pet): # pet is a validated PetIn
pet_id = len(pets) + 1
pets[pet_id] = {"id": pet_id, **pet.model_dump()}
return pets[pet_id]
@app.get("/pets/<int:pet_id>")
@app.output(PetOut)
async def get_pet(pet_id):
if pet_id not in pets:
abort(404, message="Pet not found")
return pets[pet_id]
Run it with any ASGI server:
hypercorn module:app
- OpenAPI spec:
GET /openapi.json - Interactive docs:
GET /docs(Swagger UI by default; try?ui=redoc,?ui=rapidoc,?ui=elements)
Input locations
@app.input(Model, location=...) supports json (default), query, form,
files, form_and_files, headers, cookies and path. The validated model
is injected as f"{location}_data" unless you pass arg_name=. Multiple
@app.input decorators stack for different locations. Invalid input yields a
422 with the standard error envelope.
Output
@app.output(Model, status_code=200) validates and serializes the handler's
return value (model.model_validate(obj).model_dump(mode="json")). Handlers may
return obj, (obj, status), or (obj, status, headers). Use EmptyModel
with status_code=204 to document an empty response.
Errors
Every error is a single JSON envelope:
{
"error": {
"code": "VALIDATION_ERROR",
"message": "The request contains invalid data",
"detail": {"json": [{"loc": ["name"], "msg": "Field required", "type": "missing"}]}
}
}
Raise one with abort(404, message="Pet not found") or
raise HTTPError(...). Quart's own HTTPExceptions are reshaped into the same
envelope. Customize the shape with @app.error_processor.
Authentication
from quart_httpauth import HTTPTokenAuth
from apiquart import APIQuart
app = APIQuart(__name__)
auth = HTTPTokenAuth(scheme="Bearer")
@auth.verify_token
async def verify(token):
return await User.from_token(token)
@app.get("/admin/stats")
@app.auth_required(auth, roles="admin")
async def stats():
return {"user": auth.current_user()}
apiquart introspects the auth object and registers the matching OpenAPI security
scheme (Basic → http/basic, Bearer → http/bearer, custom header → apiKey).
Pagination
from apiquart import BaseModel, PaginationMeta, pagination_builder
class PetsPage(BaseModel):
data: list[PetOut]
pagination: PaginationMeta
@app.get("/pets")
@app.input(PetQuery, location="query")
@app.output(PetsPage)
async def list_pets(query_data):
items, total = await Pet.paginate(query_data.page, query_data.per_page)
return {
"data": items,
"pagination": pagination_builder(query_data.page, query_data.per_page, total),
}
Blueprints and class-based views
APIBlueprint carries the same decorators so blueprint routes contribute to the
spec. Quart's MethodView is supported — decorate the HTTP methods directly.
See examples/ for runnable apps.
License
MIT.
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 apiquart-0.0.1.tar.gz.
File metadata
- Download URL: apiquart-0.0.1.tar.gz
- Upload date:
- Size: 161.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.21 {"installer":{"name":"uv","version":"0.11.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0e0eb1926855f43414e6e34f6c76d08e62c1474572a0f04283b128c845e6b140
|
|
| MD5 |
b4071aa6be0ee532c340830df1d7adae
|
|
| BLAKE2b-256 |
9ff0bb701c3d7ae0aa5b679cda6fb52f900560361902bc4f57677e4f1842cd47
|
File details
Details for the file apiquart-0.0.1-py3-none-any.whl.
File metadata
- Download URL: apiquart-0.0.1-py3-none-any.whl
- Upload date:
- Size: 24.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.21 {"installer":{"name":"uv","version":"0.11.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bdff2d39e7a0ed144a7a74c837a9f42af9c9ab2876df33f3c82df5633ab81703
|
|
| MD5 |
2c9435170601c51966923bf9c49dd2a1
|
|
| BLAKE2b-256 |
cd27b576b732829bc47f52047f915dbc23601508f506a400057e0c704d130e4f
|