LightAPI v2 Documentation
LightAPI v2 is a Python REST API framework where a single annotated class simultaneously acts as your SQLAlchemy ORM model, your Pydantic v2 validation schema, and your HTTP endpoint. No more keeping three files in sync — declare once, get everything.
Built on Starlette + Uvicorn, validated by Pydantic v2, persisted via SQLAlchemy 2.0 imperative mapping.
Key Features
One Class, Three Roles
- Annotation-driven columns —
title: str = Field(min_length=1)creates aVARCHAR NOT NULLcolumn, a Pydantic constraint, and an API validation rule simultaneously - Auto-injected audit columns — every endpoint gets
id,created_at,updated_at,versionautomatically - Full CRUD —
GET,POST,PUT,PATCH,DELETEgenerated from a single class definition
Data Integrity
- Optimistic locking — every
PUT/PATCHrequiresversionin the body; stale writes return409 Conflict - Pydantic v2 validation —
422 Unprocessable Entitywith structured error details on bad input - Consistent error format —
{"detail": "..."}or{"detail": [...pydantic errors...]}across all errors
Security
- JWT Authentication —
Meta.authentication = Authentication(backend=JWTAuthentication) - Permission classes —
AllowAny,IsAuthenticated,IsAdminUser(checksis_adminJWT claim) - CORS —
LightApi(cors_origins=[...])
Querying
- Filter backends —
FieldFilter(exact match with type coercion),SearchFilter(LIKE),OrderingFilter - Pagination — page-number or cursor (keyset) styles via
Meta.pagination - Custom queryset — override
queryset(self, request)to scope the base query
Async I/O (opt-in)
- Single engine swap — pass
create_async_engine(...)instead ofcreate_engine(...)to activate full async I/O - Async queryset —
async def querysetis detected and awaited automatically - Async method overrides —
async def post/get/put/patch/deletecoexist with sync overrides on the same app - Background tasks —
self.background(fn, *args)schedules post-response fire-and-forget tasks - Mixed middleware —
async def processanddef processmiddleware coexist in the same stack - Async reflection —
Meta.reflect = Trueworks withAsyncEngineviaconn.run_sync
Developer Experience
- Redis caching —
Meta.cache = Cache(ttl=60)cachesGETresponses; writes auto-invalidate - HttpMethod mixins —
class MyEp(RestEndpoint, HttpMethod.GET, HttpMethod.POST)for explicit verb control - Serializer —
Meta.serializer = Serializer(read=[...], write=[...])for per-verb field projection - Middleware —
Middleware.process(request, response)— sync or async — with short-circuit support - Database reflection — map existing tables with
Meta.reflect = True | "partial" - YAML config —
LightApi.from_config("lightapi.yaml")— declarative endpoints with Pydantic-validated schema
Quick Start
from sqlalchemy import create_engine
from lightapi import LightApi, RestEndpoint, Field
from typing import Optional
class BookEndpoint(RestEndpoint):
title: str = Field(min_length=1)
author: str = Field(min_length=1)
year: Optional[int] = None
engine = create_engine("sqlite:///books.db")
app = LightApi(engine=engine)
app.register({"/books": BookEndpoint})
app.run()
from sqlalchemy.ext.asyncio import create_async_engine
from lightapi import LightApi, RestEndpoint, Field
from typing import Optional
class BookEndpoint(RestEndpoint):
title: str = Field(min_length=1)
author: str = Field(min_length=1)
year: Optional[int] = None
engine = create_async_engine(
"postgresql+asyncpg://user:pass@localhost/mydb"
)
app = LightApi(engine=engine)
app.register({"/books": BookEndpoint})
app.run()
See the Quickstart Guide for full curl examples.
Documentation
Getting Started
Core Concepts
- RestEndpoint & Field
- Authentication & Permissions
- Filtering & Ordering
- Pagination
- Middleware
- Caching
- Database Reflection
- YAML Configuration
Async Support
Reference
Requirements
- Python 3.10+
- SQLAlchemy 2.x
- Pydantic v2
- Starlette + Uvicorn
Async extras (lightapi[async]):
sqlalchemy[asyncio]asyncpg(PostgreSQL) oraiosqlite(SQLite)greenlet