Skip to content

QuoinAPI

CI Python 3.14+ FastAPI SQLModel prek License: MIT

QuoinAPI (pronounced "koyn") is a production-ready Python backend foundation. Built with FastAPI, SQLModel, and the Astral stack (uv, ruff, ty), it gives you a battle-tested starting point with type safety, observability, and clean architecture out of the box.

New here? Start with the Getting Started Guide.

Quick Start

uvx copier copy --trust gh:balakmran/quoin-api my-api
cd my-api
cp .env.example .env
just setup
just dev
git clone https://github.com/balakmran/quoin-api.git my-api
cd my-api
cp .env.example .env
just setup
just dev

Visit http://localhost:8000/docs for the interactive API docs.

Key recipes

Command What it does
just setup Install deps and wire commit hooks — run once
just dev Start Postgres, mock OAuth, apply migrations, and run the server
just new <module> Scaffold and register a complete DDD module
just check Run format → lint → typecheck → test in one gate
just migrate-gen "<msg>" Generate an Alembic migration from your model changes
just token Mint a signed JWT against the local mock OAuth server

Run just --list for the full menu.

Architecture

graph TB
    Client[Client/Browser] -->|HTTP| FastAPI[FastAPI Application]
    FastAPI -->|Business Logic| Service[Service Layer]
    Service -->|Database Access| Repository[Repository Layer]
    Repository -->|SQL| PostgreSQL[(PostgreSQL)]

    FastAPI -->|Structured Logs| Structlog[Structlog]
    FastAPI -->|Traces| OTEL[OpenTelemetry]

    Service -->|Domain Exceptions| Handlers[Exception Handlers]
    Handlers -->|JSON Response| Client

Read the full architecture documentation →.

Tech Stack

  • Framework: FastAPI
  • Database: PostgreSQL (using asyncpg driver)
  • ORM: SQLModel (SQLAlchemy wrapper)
  • Migrations: Alembic
  • Package Manager: uv
  • Task Runner: just
  • Linting/Formatting: Ruff
  • Type Checking: ty
  • Pre-commit Hooks: prek
  • Testing: Pytest, pytest-cov
  • Observability: OpenTelemetry, Structlog
  • Documentation: Zensical (MkDocs Material)

See the decision log for the reasoning behind these choices.

Where next