Skip to content

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Smart Expense Tracker API

A small REST API for tracking personal expenses, built with FastAPI. Data is stored in a local JSON file (expenses.json) — no database required.

What it does

  • POST /expenses — add an expense (title, amount, category, date)
  • GET /expenses — list all expenses
  • GET /expenses?category=X — filter expenses by category (case-insensitive)
  • GET /expenses?q=text — bonus: search expenses by title substring
  • GET /expenses/summary — overall total + totals/count per category
  • GET /expenses/{id} — fetch a single expense
  • DELETE /expenses/{id} — delete an expense

Interactive Swagger docs are auto-generated by FastAPI at /docs once the server is running (this doubles as the optional "OpenAPI/Swagger docs" bonus).

Requirements

  • Python 3.11+

Install

python3 -m venv venv
source venv/bin/activate        # Windows: venv\Scripts\activate
pip install -r requirements.txt

Run the server

uvicorn src.main:app --reload

The API is now available at http://127.0.0.1:8000, and interactive docs at http://127.0.0.1:8000/docs.

By default it stores data in expenses.json in the project root. To use a different file, set EXPENSES_DATA_FILE before starting:

EXPENSES_DATA_FILE=my_data.json uvicorn src.main:app --reload

Run the tests

pytest tests/ -v

Tests use FastAPI's TestClient and each test gets its own temporary JSON file (via pytest's tmp_path fixture), so running the suite never touches expenses.json or leaves stray files behind.

Example usage

curl -X POST http://127.0.0.1:8000/expenses \
  -H "Content-Type: application/json" \
  -d '{"title": "Coffee", "amount": 4.5, "category": "Food", "date": "2026-07-01"}'

curl "http://127.0.0.1:8000/expenses?category=Food"

curl http://127.0.0.1:8000/expenses/summary

curl -X DELETE http://127.0.0.1:8000/expenses/1

Project structure

src/
  main.py       # FastAPI app + routes (app factory pattern, see AI_NOTES.md)
  models.py     # Pydantic request/response models & validation
  storage.py    # JSON-file backed storage layer (in-memory cache + disk writes)
tests/
  test_api.py   # 22 tests covering CRUD, filtering, search, totals, edge cases
requirements.txt
AI_NOTES.md

Design notes

  • Validation: amount must be > 0, title/category can't be empty, date must be a valid ISO date (YYYY-MM-DD) — Pydantic rejects anything else with a 422.
  • IDs: auto-incrementing integers assigned by the server, persisted in the JSON file alongside the expenses so IDs stay unique across restarts.
  • /expenses/summary is defined before /expenses/{id} in main.py — FastAPI matches routes in order, so if {id} came first, a request to /expenses/summary would incorrectly try to parse "summary" as an int id.
  • Concurrency: a threading.Lock guards writes in storage.py. This is overkill for a single-user take-home assignment, but it's a one-line safety net against corrupting the JSON file if two requests write at once.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages