Personal productivity API with note-taking and todo list management. Features email-based authentication.
- Python 3.11 or higher
- uv (Python package manager):
pip install uv
# Clone the repository
git clone <repository-url>
cd toposphere
# Install dependencies and create virtual environment
uv sync
# Activate virtual environment
source .venv/bin/activate# Run migrations to create database tables
python manage.py migratepython manage.py runserverThe API will be available at http://localhost:8000/
Once the server is running, you can access the interactive API documentation:
- Swagger UI:
http://localhost:8000/api/docs/- Interactive API explorer with try-it-now functionality - ReDoc:
http://localhost:8000/api/redoc/- Alternative API documentation interface - OpenAPI Schema:
http://localhost:8000/api/schema/- Raw OpenAPI 3.0 schema (JSON)
curl -X POST http://localhost:8000/api/auth/register/ \
-H "Content-Type: application/json" \
-d '{
"email": "user@example.com",
"password": "SecurePass123"
}'Response:
{
"access": "eyJ0eXAiOiJKV1QiLCJhbGc...",
"refresh": "eyJ0eXAiOiJKV1QiLCJhbGc...",
"id": 1,
"email": "user@example.com"
}Note: The API uses JWT (JSON Web Tokens) for authentication. The response includes both an access token (valid for 30 minutes) and a refresh token (valid for 7 days). Use the refresh token to obtain a new access token when it expires.
curl -X POST http://localhost:8000/api/auth/login/ \
-H "Content-Type: application/json" \
-d '{
"email": "user@example.com",
"password": "SecurePass123"
}'Response:
{
"access": "eyJ0eXAiOiJKV1QiLCJhbGc...",
"refresh": "eyJ0eXAiOiJKV1QiLCJhbGc...",
"id": 1,
"email": "user@example.com"
}When your access token expires (after 30 minutes), use the refresh token to get a new one:
curl -X POST http://localhost:8000/api/auth/refresh/ \
-H "Content-Type: application/json" \
-d '{
"refresh": "YOUR_REFRESH_TOKEN_HERE"
}'Response:
{
"access": "eyJ0eXAiOiJKV1QiLCJhbGc...",
"refresh": "eyJ0eXAiOiJKV1QiLCJhbGc..."
}curl -X POST http://localhost:8000/api/notes/ \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN_HERE" \
-d '{
"title": "My First Note",
"content": "This is the content of my note."
}'curl -X POST http://localhost:8000/api/todos/ \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN_HERE" \
-d '{
"title": "My Tasks",
"description": "Things to do"
}'curl -X POST http://localhost:8000/api/todos/<list_id>/items/ \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN_HERE" \
-d '{
"title": "Buy groceries"
}'curl -X PATCH http://localhost:8000/api/todos/items/<item_id>/ \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN_HERE" \
-d '{
"is_completed": true
}'curl -X GET http://localhost:8000/api/notes/ \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN_HERE"curl -X GET "http://localhost:8000/api/notes/?search=first" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN_HERE"| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
| POST | /api/auth/register/ |
Register new user | No |
| POST | /api/auth/login/ |
Login and get JWT tokens | No |
| POST | /api/auth/refresh/ |
Refresh access token using refresh token | No |
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/notes/ |
List all notes (supports ?search= query) |
| POST | /api/notes/ |
Create a new note |
| GET | /api/notes/<id>/ |
Retrieve a specific note |
| PUT | /api/notes/<id>/ |
Update a note (full) |
| PATCH | /api/notes/<id>/ |
Partial update |
| DELETE | /api/notes/<id>/ |
Delete a note |
Note: All notes and todos endpoints require authentication via Authorization: Bearer <access_token> header.
Todo items are organized into lists. Each user can have multiple lists, and each list can contain multiple items.
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/todos/ |
List all todo lists |
| POST | /api/todos/ |
Create a new list |
| GET | /api/todos/<id>/ |
Retrieve a specific list |
| PUT | /api/todos/<id>/ |
Update a list (full) |
| PATCH | /api/todos/<id>/ |
Partial update |
| DELETE | /api/todos/<id>/ |
Delete a list |
| GET | /api/todos/<list_id>/items/ |
List all items in a list |
| POST | /api/todos/<list_id>/items/ |
Create a new item in a list |
| GET | /api/todos/items/<id>/ |
Retrieve a specific item |
| PUT | /api/todos/items/<id>/ |
Update an item (full) |
| PATCH | /api/todos/items/<id>/ |
Partial update (use for marking complete) |
| DELETE | /api/todos/items/<id>/ |
Delete an item |
# Run all tests
python manage.py test
# Run with verbose output
python manage.py test -v 2Before committing, run the code quality checks:
./check_all.shThis runs:
ruff format- Code formattingruff check- Lintingmypy --strict- Type checking
Passwords must have:
- At least 8 characters
- At least one uppercase letter
- At least one lowercase letter
- At least one digit
toposphere/
├── accounts/ # User authentication app
├── notes/ # Notes CRUD app
├── todos/ # Todo lists and items app
├── test/scripts/ # Shell test scripts
├── test/scenarios/ # Scenario-based integration tests
├── manage.py # Django management commands
├── pyproject.toml # Dependencies and tool config
└── check_all.sh # Code quality script
Make sure the virtual environment is activated:
source .venv/bin/activateStop the server and run migrations again:
python manage.py migratechmod +x check_all.sh