A secure REST API for managing personal income and expenses.
The application allows users to register, log in, create income and expense transactions, view their transaction history, and calculate their current balance.
- User registration
- Secure password hashing with bcrypt
- Duplicate username validation
- OAuth2-compatible login
- JWT authentication
- Authenticated user profile with
/me - Add income and expense transactions
- View the authenticated user's transactions
- Calculate the authenticated user's balance
- Interactive API documentation with Swagger UI
- Python
- FastAPI
- Uvicorn
- SQLAlchemy
- MySQL
- PyMySQL
- Pydantic
- Pydantic Settings
- Passlib and bcrypt
- JSON Web Tokens with python-jose
personal-finance-manager/
├── app/
│ ├── core/
│ │ ├── config.py
│ │ └── security.py
│ ├── db/
│ │ ├── crud.py
│ │ └── database.py
│ ├── models/
│ │ ├── transaction_model.py
│ │ └── user_model.py
│ ├── schemas/
│ │ ├── transaction_schema.py
│ │ └── user_schema.py
│ └── main.py
├── database/
│ ├── migrations/
│ ├── schema.sql
│ └── seed.sql
├── tests/
├── .gitignore
├── README.md
└── requirements.txt
Clone the repository:
git clone https://github.com/ErkanSoftwareDeveloper/personal-finance-manager.git
cd personal-finance-managerCreate a virtual environment:
python3 -m venv .venvActivate the virtual environment on macOS or Linux:
source .venv/bin/activateInstall the dependencies:
pip install -r requirements.txtThe project uses MySQL.
Create the database and tables by running:
database/schema.sql
You can execute this file using DBeaver, MySQL Workbench, or the MySQL command-line client.
The default database name is:
finance_managerDB
The database connection is configured through the DATABASE_URL environment variable.
Do not store database credentials directly in the Python source code.
Create a .env file in the project root:
SECRET_KEY=your-secure-secret-key
ACCESS_TOKEN_EXPIRE_MINUTES=30
DATABASE_URL=mysql+pymysql://root:your_password@localhost:3306/finance_managerDBWhen the local MySQL root user has no password, the database URL can look like this:
DATABASE_URL=mysql+pymysql://root:@localhost:3306/finance_managerDBGenerate a secure JWT secret key with:
python -c "import secrets; print(secrets.token_hex(32))"Copy the generated value into SECRET_KEY.
The .env file is ignored by Git and must never be committed.
Start the development server:
python -m uvicorn app.main:app --reloadIf the python command is not available, use:
python3 -m uvicorn app.main:app --reloadThe API will be available at:
http://127.0.0.1:8000
Swagger documentation:
http://127.0.0.1:8000/docs
- Register a new user with
POST /register. - Log in with
POST /login. - The API returns a JWT access token.
- Use the token through the Swagger Authorize button or send it in the request header:
Authorization: Bearer your_access_token
Protected endpoints automatically identify the current user from the token.
Users do not send their own user_id when creating or viewing financial data.
POST /registerExample request:
{
"username": "erkan",
"password": "secure-password"
}Example response:
{
"user_id": 1,
"username": "erkan"
}POST /loginThe login endpoint uses OAuth2 form data.
Example response:
{
"access_token": "jwt-token",
"token_type": "bearer"
}GET /meReturns the authenticated user's public information.
POST /transactionsAuthentication is required.
Example income request:
{
"amount": 2500.00,
"transaction_type": "income",
"category": "Salary"
}Example expense request:
{
"amount": 120.50,
"transaction_type": "expense",
"category": "Groceries"
}The transaction is automatically assigned to the authenticated user.
GET /transactionsReturns only the authenticated user's transactions.
GET /balanceThe balance is calculated from all transactions:
balance = total income - total expenses
The balance is not stored separately in the database.
The API includes validation for:
- Username and password length
- Duplicate usernames
- Positive transaction amounts
- Supported transaction types
- Missing or invalid JWT tokens
- Expired JWT tokens
Common status codes:
200 OK
201 Created
400 Bad Request
401 Unauthorized
422 Validation Error
- Passwords are never stored as plain text.
- Passwords are hashed with bcrypt.
- Protected endpoints require JWT authentication.
- Financial data is associated with the user identified by the token.
- Secret keys are loaded from environment variables.
- The
.envfile is excluded from version control.
This repository contains the first version of the backend API.
The current scope includes:
- Authentication
- Income transactions
- Expense transactions
- Transaction history
- Balance calculation
Possible future improvements include:
- Automated tests
- Transaction update and deletion
- Category management
- Date filtering
- Pagination
- Monthly reports
- Docker support
- Database migrations with Alembic
- Frontend integration
Erkan Software Developer
GitHub: ErkanSoftwareDeveloper