REST API for personal expense tracking. Users register, authenticate with JWT, and manage their own expense records.
Live docs (when running locally): Swagger UI · ReDoc
Each authenticated user can create, list, update, and delete expenses. Records are scoped to the owner; listing supports title search, amount range, and pagination.
flowchart LR
Client -->|JSON + JWT| API[FastAPI]
API --> Auth
API --> Expenses
Auth --> DB[(PostgreSQL)]
Expenses --> DB
- Sign up and login with bcrypt-hashed passwords
- JWT access tokens (Bearer) with a 10-minute expiry
- Expense CRUD isolated per user
- Query filters:
title,min_value,max_value,skip,limit - PostgreSQL 16, SQLAlchemy, Alembic
- Docker Compose for a one-command local stack
- pytest coverage for auth and expense flows
| Layer | Tools |
|---|---|
| API | FastAPI, Uvicorn |
| Database | PostgreSQL 16, SQLAlchemy 2 |
| Auth | JWT (python-jose), HTTP Bearer, bcrypt |
| Migrations | Alembic |
| Tests | pytest, FastAPI TestClient |
| Runtime | Docker, Docker Compose |
- Docker Desktop (recommended), or Python 3.14+ and PostgreSQL 16
- Git
git clone https://github.com/mertbatuhan0/Expense-Tracker.git
cd Expense-Tracker
docker compose up --build| Service | Address |
|---|---|
| API | http://localhost:8000 |
| Swagger UI | http://localhost:8000/docs |
| PostgreSQL | localhost:5433 |
Default database credentials in Compose: user postgres, password postgres, database expense_tracker.
- Start PostgreSQL (or use only the
dbservice from Compose). - Create a virtual environment and install dependencies:
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt- Set environment variables (see below), then run:
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000| Variable | Purpose | Default |
|---|---|---|
DATABASE_URL |
SQLAlchemy connection string | postgresql://postgres@localhost:5433/expense_tracker |
SECRET_KEY |
JWT signing key | development fallback in code — set this in any real environment |
ALGORITHM |
JWT algorithm | HS256 |
TEST_DATABASE_URL |
Database used by pytest | required for tests |
Create a .env file in the project root (gitignored). Do not commit secrets.
1. Sign up
curl -X POST http://localhost:8000/auth/Signup \
-H "Content-Type: application/json" \
-d '{"mail": "you@example.com", "username": "batuhan", "password": "secret123"}'2. Log in and copy access_token:
curl -X POST http://localhost:8000/auth/Login \
-H "Content-Type: application/json" \
-d '{"mail": "you@example.com", "password": "secret123"}'3. Create an expense
curl -X POST http://localhost:8000/expenses/ \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"title": "Groceries", "amount": 42}'sequenceDiagram
participant Client
participant Auth as /auth
participant Expenses as /expenses
Client->>Auth: POST /Signup
Client->>Auth: POST /Login
Auth-->>Client: access_token
Client->>Expenses: Authorization Bearer token
Expenses-->>Client: expense JSON
Interactive documentation: http://localhost:8000/docs
| Method | Path | Auth | Description |
|---|---|---|---|
POST |
/auth/Signup |
No | Create an account (username, mail, password) |
POST |
/auth/Login |
No | Return { "access_token", "token_type": "bearer" } |
All expense endpoints require Authorization: Bearer <token>.
| Method | Path | Description |
|---|---|---|
GET |
/expenses/ |
List expenses (skip, limit, title, min_value, max_value) |
GET |
/expenses/{id} |
Get one expense |
POST |
/expenses/ |
Create (title, amount) |
PUT |
/expenses/{id} |
Update (title, amount) |
DELETE |
/expenses/{id} |
Delete |
Expense body:
{
"title": "Groceries",
"amount": 42
}/users exposes user CRUD. Prefer /auth/Signup for registration.
Tests use a separate database via TEST_DATABASE_URL.
export TEST_DATABASE_URL=postgresql://postgres:postgres@localhost:5433/expense_tracker_test
pytestFixtures live in app/tests/conftest.py. Suites:
app/tests/test_auth.py— signup and loginapp/tests/test_expenses.py— expense CRUD and unauthorized access
app/
api/endpoints/ # auth, users, expenses routers
core/security/ # JWT and password hashing
crud/ # database operations
db/ # engine and session
models/ # SQLAlchemy models
schemas/ # Pydantic schemas
tests/ # pytest suite
alembic/ # migrations
docker-compose.yml
Dockerfile
requirements.txt
Personal / learning project. See the repository for source.