Skip to content

Getting started

Install

Veloce requires Python 3.10 or newer.

pip install veloceframework

To run an app you will also want an ASGI server such as uvicorn:

pip install uvicorn

Your first app

Create main.py:

main.py
from veloce import Veloce, Request

app = Veloce()


@app.get("/")
async def index(request: Request):
    return {"message": "Welcome to Veloce!"}


@app.get("/hello/{name}")
async def hello(name: str):
    return {"hello": name}


if __name__ == "__main__":
    app.run(host="0.0.0.0", port=8000)

Run it either way:

python main.py
# or with the built-in CLI (no extra dependencies):
veloce run main:app
# or under uvicorn, the optional extra: pip install veloceframework[uvicorn]
python -m uvicorn main:app

Then visit http://localhost:8000/hello/world — you should get {"hello": "world"}.

async def is preferred, def is supported

Define handlers with async def for best performance — they run directly on the event loop. A plain def handler also works: Veloce detects it and runs it in a thread-pool executor so it never blocks the loop. Reach for a sync handler when calling blocking library code you cannot await.

What just happened

  • Veloce() created the application. It is a router, so app.get, app.post, and friends are available directly.
  • {name} declared a path parameter. The name: str annotation tells Veloce how to coerce and inject it.
  • Returning a dict produced a JSON response automatically.

A slightly bigger app

from pydantic import BaseModel

from veloce import Depends, HTTPException, Request, Veloce

app = Veloce(title="Example API", version="1.0.0")

_users: dict[int, dict] = {}


class UserCreate(BaseModel):
    name: str
    email: str
    age: int = 0


def get_db() -> dict[int, dict]:
    return _users


@app.post("/users")
async def create_user(user: UserCreate, db=Depends(get_db)):
    user_id = len(db) + 1
    db[user_id] = user.model_dump()
    return {"id": user_id, **db[user_id]}


@app.get("/users/{user_id}")
async def get_user(user_id: int, db=Depends(get_db)):
    if user_id not in db:
        raise HTTPException(404, f"User {user_id} not found")
    return {"id": user_id, **db[user_id]}

This shows the three pillars you will use constantly:

  • Pydantic models as request bodies (user: UserCreate) — validated before your handler runs.
  • Dependency injection (Depends(get_db)) — see Dependency Injection.
  • HTTPException — raise it anywhere to short-circuit with a status code and message.

Interactive API docs

When OpenAPI is enabled (the default), Veloce generates an OpenAPI 3.1 schema and serves Swagger UI and ReDoc for it. With the running app, open:

Pass title= and version= to Veloce(...) to control the document metadata. The three paths are configurable through docs_url, redoc_url, and openapi_url:

app = Veloce(docs_url="/swagger", redoc_url="/api-docs", openapi_url="/schema.json")

Disable a UI with None, not an empty string

Set docs_url=None or redoc_url=None to switch a UI off entirely. Veloce uses None as the sentinel — an empty string is not the disable value.

Next steps