Skip to main content

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 /docs endpoint.

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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

apiquart-0.0.1.tar.gz (161.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

apiquart-0.0.1-py3-none-any.whl (24.5 kB view details)

Uploaded Python 3

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

Hashes for apiquart-0.0.1.tar.gz
Algorithm Hash digest
SHA256 0e0eb1926855f43414e6e34f6c76d08e62c1474572a0f04283b128c845e6b140
MD5 b4071aa6be0ee532c340830df1d7adae
BLAKE2b-256 9ff0bb701c3d7ae0aa5b679cda6fb52f900560361902bc4f57677e4f1842cd47

See more details on using hashes here.

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

Hashes for apiquart-0.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 bdff2d39e7a0ed144a7a74c837a9f42af9c9ab2876df33f3c82df5633ab81703
MD5 2c9435170601c51966923bf9c49dd2a1
BLAKE2b-256 cd27b576b732829bc47f52047f915dbc23601508f506a400057e0c704d130e4f

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page