A simple to-do list CRUD API built with FastAPI, now backed by a SQLite database. Built as part of the FlyRank Internship, Backend Track — Week 2 (CRUD API) and Week 3 (connecting it to a real database).
- Python 3.10+
- FastAPI
- Uvicorn (ASGI server)
- Pydantic (data validation)
- SQLite (built into Python's standard library)
git clone https://github.com/YOUR_USERNAME/todo-api.git
cd todo-api
python -m venv venv
source venv/bin/activate # Windows: venv\Scripts\Activate.ps1
pip install -r requirements.txtuvicorn main:app --reloadServer runs at http://localhost:8000. The database file (tasks.db) and its
tasks table are created automatically on first run, seeded with 3 example
tasks — no manual setup needed.
| Method | Path | Description |
|---|---|---|
| GET | / | API info |
| GET | /health | Health check |
| GET | /tasks | List all tasks |
| GET | /tasks/{id} | Get one task |
| POST | /tasks | Create a task |
| PUT | /tasks/{id} | Update a task |
| DELETE | /tasks/{id} | Delete a task |
curl -i -X POST http://localhost:8000/tasks \
-H "Content-Type: application/json" \
-d '{"title": "Buy milk"}'Response: 201 Created
{"id": 4, "title": "Buy milk", "done": false}Interactive docs available at http://localhost:8000/docs — use "Try it out"
on any endpoint to send real requests from the browser.
All endpoints were tested via curl and via Swagger UI's "Try it out" feature, confirming correct status codes: 200, 201, 204, 400, 404. Persistence was also verified: created tasks survive a full server restart.
curl -i http://localhost:8000/tasks
curl -i http://localhost:8000/tasks/1
curl -i http://localhost:8000/tasks/999 # expect 404
curl -i -X POST http://localhost:8000/tasks -H "Content-Type: application/json" -d '{"title": ""}' # expect 400
curl -i -X PUT http://localhost:8000/tasks/1 -H "Content-Type: application/json" -d '{"title": "Updated", "done": true}'
curl -i -X DELETE http://localhost:8000/tasks/1 # expect 204This project uses SQLite for storage — chosen because it's a single file
(tasks.db), needs zero setup or separate server, and the data survives
server restarts.
The database file is created automatically on first run and is git-ignored,
so each clone starts with a fresh database (seeded with 3 example tasks).
All CRUD operations use parameterized SQL queries (? placeholders) to keep
user input safely separated from the SQL itself.
UPDATE tasks SET done = 1;Running this in DB Browser for SQLite marked every task as completed — the
running API reflected this change immediately on the next GET /tasks call,
with no server restart, since both read the same tasks.db file.
