Fluzpay is a small FastAPI service for authenticated transaction management. It handles user registration/login, JWT-protected transaction CRUD, transaction filtering, summary totals, and audit logs for lifecycle changes.
It is intentionally simple: one API service, one relational database, and a thin service layer where transaction rules live.
- FastAPI app with OpenAPI docs at
/docs - JWT auth with bcrypt password hashing
- SQLAlchemy models for users, transactions, and transaction logs
- Transaction filtering by status, type, and amount range
- Summary endpoint for per-user totals and status counts
- Docker Compose setup with Postgres and nginx
- Async API tests using
httpxagainst the ASGI app
The editable Excalidraw source is in docs/architecture.excalidraw.
.------------------------------------------------------.
/ Client /
'------------------------------------------------------'
|
| HTTP / JSON
v
.------------------------------------------------------.
/ nginx /
| proxy headers, basic hardening, rate limiting |
'------------------------------------------------------'
|
v
.------------------------------------------------------.
/ FastAPI app /
| app/main.py |
| - CORS |
| - health/root endpoints |
| - exception handlers |
'------------------------------------------------------'
| |
v v
.------------------. .--------------------.
/ Auth router / / Transactions router /
| /auth/register | | CRUD, filters, logs |
| /auth/login | | summary endpoint |
'------------------' '--------------------'
| |
v v
.------------------. .--------------------.
/ app/auth.py / / TransactionService /
| JWT + password | | business workflow |
'------------------' '--------------------'
| |
'----------------. .---------------'
v
.----------------------.
/ SQLAlchemy session /
| app/database.py |
'----------------------'
|
v
.----------------------.
/ PostgreSQL /
| users, transactions, |
| transaction_logs |
'----------------------'
Auth:
POST /auth/registerPOST /auth/loginGET /auth/me
Transactions:
POST /transactions/GET /transactions/GET /transactions/summaryGET /transactions/{transaction_id}PUT /transactions/{transaction_id}DELETE /transactions/{transaction_id}GET /transactions/{transaction_id}/logs
Useful query filters on GET /transactions/:
status=pending|completed|failed|cancelledtransaction_type=debit|credit|transfermin_amount=10max_amount=500skip=0limit=100
Create an environment file:
cp env.example .envFor a local Postgres run, set DATABASE_URL to your database. For a quick throwaway run you can use SQLite:
DATABASE_URL=sqlite:///./payflow.db uvicorn app.main:app --reloadThen open:
- API:
http://localhost:8000 - Docs:
http://localhost:8000/docs - Health:
http://localhost:8000/health
docker compose up --buildThe Compose setup starts:
db: Postgres 15app: FastAPI on port8000nginx: reverse proxy on port80
For a deployed setup, put TLS in front of nginx or extend nginx.conf with real certificates from your certificate manager.
Environment variables:
| Name | Purpose | Default |
|---|---|---|
DATABASE_URL |
SQLAlchemy database URL | local Postgres placeholder |
SECRET_KEY |
JWT signing secret | development placeholder |
ALGORITHM |
JWT algorithm | HS256 |
ACCESS_TOKEN_EXPIRE_MINUTES |
Access token lifetime | 30 |
CORS_ORIGINS |
Comma-separated allowed origins | * |
DEBUG |
Enables reload when running app.main directly |
True |
LOG_LEVEL |
Python logging level | INFO |
LOG_FILE |
Optional file path for structured logs | stdout when empty |
python -m pytestThe tests use an in-memory SQLite database and exercise registration, login, protected routes, filters, summaries, validation, cancellation, and audit logs.
users: login identity and profile fieldstransactions: amount, type, status, accounts, reference id, ownershiptransaction_logs: audit trail entries tied to transaction updates
Transactions start as pending. Deleting a transaction is implemented as cancellation, so the row remains available for history and logs.