A small FastAPI service for logging expenses in multiple currencies and computing their total converted into a single base currency using live exchange rates.
Built as a clean, self-contained REST API demonstrating request validation, SQLite persistence, external API integration, and proper error handling.
- Log expenses with amount, currency, category, and date
- Automatic input validation (rejects non-positive amounts, malformed dates)
- Persistent storage via SQLite (survives restarts)
- Convert and total all expenses into any base currency using live rates from the Frankfurter API
- Gracefully skips unknown/unsupported currencies and reports them
- Delete expenses by ID with proper 404 handling
- FastAPI — web framework
- Pydantic — request validation
- SQLite (
sqlite3) — persistence - httpx — async HTTP client for the exchange-rate API
python3 -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
pip install -r requirements.txt
uvicorn main:app --reloadThe API runs at http://localhost:8000. Interactive docs at
http://localhost:8000/docs.
| Method | Path | Description |
|---|---|---|
| GET | / |
Health check |
| POST | /expenses |
Log a new expense |
| GET | /expenses |
List all expenses |
| GET | /expenses/total |
Total all expenses in a base currency (default USD) |
| DELETE | /expenses/{expense_id} |
Delete an expense by ID |
curl -X POST http://localhost:8000/expenses \
-H "Content-Type: application/json" \
-d '{"amount": 45.50, "currency": "USD", "category": "food", "date": "2026-07-25"}'curl "http://localhost:8000/expenses/total?base_currency=EUR"Response:
{
"base_currency": "EUR",
"total": 123.45,
"expenses_count": 7,
"skipped": []
}The test suite uses pytest, with an isolated temporary database per test and a
mocked exchange-rate API (so tests run offline and produce deterministic totals).
pip install -r requirements.txt
python -m pytest tests/ -v- Currency codes are normalized to uppercase on input.
- The exchange-rate lookup makes a single API call per total request, regardless of how many expenses or currencies are involved.
- The SQLite database file (
expenses.db) is created automatically on first run and is excluded from version control.