REST API for managing expeditions, members, and real-time event delivery via WebSocket. Built with FastAPI, SQLAlchemy 2, asyncpg, and PostgreSQL.
Real-time events (status changes, member invites, confirmations) are delivered through PostgreSQL triggers and LISTEN/NOTIFY — no polling required.
- Python 3.11+
- PostgreSQL 14+
- uv package manager
# 1. Install dependencies
uv sync
# 2. Configure environment
cp .env.example .env
# Fill in the values in .env
# 3. Create the database
psql -U <user> -c "CREATE DATABASE <DATABASE_NAME>;"
# 4. Run migrations
uv run alembic upgrade head| Variable | Description |
|---|---|
DATABASE_USER |
PostgreSQL user |
DATABASE_PASSWORD |
PostgreSQL password |
DATABASE_HOST |
PostgreSQL host |
DATABASE_PORT |
PostgreSQL port (default: 5432) |
DATABASE_NAME |
Database name |
JWT_SECRET_KEY |
Secret key for signing JWT tokens |
cp .env.example .env
# Fill in DATABASE_USER, DATABASE_PASSWORD, DATABASE_NAME, JWT_SECRET_KEY
# Leave DATABASE_HOST as-is — Compose overrides it to point at the db service
docker compose up --buildMigrations run automatically on startup. API available at http://localhost:8000.
uv run uvicorn app.main:app --reloadAPI is available at http://localhost:8000. Interactive docs at http://localhost:8000/docs.
Tests use a separate database. Create it first:
psql -U <user> -c "CREATE DATABASE expedition_test;"Then run:
uv run pytestConnect to the WebSocket endpoint with a valid JWT token:
ws://localhost:8000/api/v1/ws?token=<jwt>
Events are delivered as JSON with an event field:
| Event | Payload |
|---|---|
expedition_status |
expedition_id, status |
member_invited |
expedition_id, user_id |
member_confirmed |
expedition_id, user_id |