Skip to content

Repository files navigation

BankAPI

Backend of a banking REST API built with FastAPI, PostgreSQL, and SQLAlchemy.

The project provides user authentication, role-based authorization, bank account management, deposits, withdrawals, transfers, transaction history, automated testing, Docker support, Continuous Integration, and production deployment.


Live Demo

Production API

API URL:
https://bankapi-by5f.onrender.com

API Documentation


Features

  • User registration
  • JWT authentication
  • Role-based authorization
  • User management
  • Bank account management
  • Multiple currency support
  • Deposits
  • Withdrawals
  • Transfers between accounts
  • Transaction history
  • Account activation and deactivation
  • Account ownership validation
  • Balance validation
  • Administrative permissions
  • Database migrations with Alembic
  • Automated tests
  • 99% code coverage
  • Docker
  • Docker Compose
  • GitHub Actions
  • Continuous Integration
  • PostgreSQL
  • Production deployment with Render
  • Asynchronous database operations

Technologies

Technology Purpose
Python 3.14 Main programming language
FastAPI REST API framework
FastAPI Users Authentication management
SQLAlchemy 2 ORM
PostgreSQL 16 Relational database
AsyncPG Asynchronous PostgreSQL driver
Alembic Database migrations
Pydantic Data validation
JWT Authentication
Uvicorn ASGI server
Docker Containerization
Docker Compose Local development environment
Pytest Automated testing
pytest-cov Code coverage
HTTPX HTTP client for tests
GitHub Actions Continuous Integration
Render Production deployment
uv Python dependency management

Architecture

The project follows a layered architecture that separates authentication, business logic, data models, schemas, and API routes.

BankAPI/
│
├── app/
│   │
│   ├── auth/
│   │   ├── backend.py
│   │   ├── dependencies.py
│   │   ├── permissions.py
│   │   └── user_manager.py
│   │
│   ├── models/
│   │   ├── user.py
│   │   ├── account.py
│   │   └── transaction.py
│   │
│   ├── schemas/
│   │   ├── user.py
│   │   ├── account.py
│   │   └── transaction.py
│   │
│   ├── services/
│   │   ├── user_service.py
│   │   ├── account_services.py
│   │   ├── transaction_service.py
│   │   └── transfer_service.py
│   │
│   ├── routers/
│   │   ├── users.py
│   │   ├── accounts.py
│   │   ├── transactions.py
│   │   └── transfers.py
│   │
│   ├── config.py
│   ├── db.py
│   └── main.py
│
├── alembic/
│
├── tests/
│   └── conftest.py
│
├── .github/
│   └── workflows/
│       └── tests.yml
│
├── Dockerfile
├── docker-compose.yml
├── .dockerignore
├── .gitignore
├── alembic.ini
├── pytest.ini
├── pyproject.toml
├── README.md
└── uv.lock

Authentication

The API uses JWT (JSON Web Token) authentication.

The authentication flow is:

Registration
     │
     ▼
   Login
     │
     ▼
JWT Access Token
     │
     ▼
Authorization Header
     │
     ▼
Protected Endpoint

Authenticated requests use:

Authorization: Bearer <access_token>

Users and Roles

The system supports three roles:

ADMIN
EMPLOYEE
CUSTOMER

CUSTOMER

Customers can:

  • Manage their own accounts.
  • Create bank accounts.
  • Make deposits into their own accounts.
  • Make withdrawals from their own accounts.
  • Transfer money from their own accounts.
  • View their transaction history.

Customers cannot perform administrative operations.


EMPLOYEE

Employees can access administrative operations allowed for the employee role, such as authorized user and account management operations.


ADMIN

Administrators have additional administrative permissions, including:

  • View all users.
  • View individual users.
  • Modify user roles.
  • View all accounts.
  • Activate accounts.
  • Deactivate accounts.

Authorization

Permissions are controlled through JWT authentication and role validation.

Request
   │
   ▼
JWT Authentication
   │
   ▼
Current User
   │
   ▼
Role Validation
   │
   ├── Allowed ──────► Endpoint
   │
   └── Not Allowed ──► 403 Forbidden

Users without sufficient permissions receive:

403 Forbidden

Bank Accounts

Each bank account belongs to a user.

An account contains:

  • ID
  • Account number
  • Account type
  • Currency
  • Balance
  • Status
  • Owner
  • Creation date
  • Last update date

Account Types

SAVINGS
CHECKING

Available Currencies

MXN
USD
EUR

Business Rules

Users

  • New users are assigned the CUSTOMER role by default.
  • Users cannot select their role during registration.
  • Users cannot register directly as ADMIN.
  • Users cannot register directly as EMPLOYEE.
  • Only an ADMIN can modify another user's role.
  • An administrator cannot modify their own role.
  • Users without sufficient permissions receive 403 Forbidden.

Accounts

  • Each account belongs to a user.
  • The initial balance is 0.00.
  • Account balances cannot be negative.
  • Account numbers are generated automatically.
  • Account numbers are unique.
  • Users can only manage their own accounts.
  • Inactive accounts cannot be used for financial operations.
  • An ADMIN can activate or deactivate accounts.
  • Deactivating an account does not delete its transaction history.

Deposits

Deposits increase the balance of an account.

Previous Balance
       +
    Deposit
       =
New Balance

Validation Rules

Before processing a deposit, the API verifies that:

  • The account exists.
  • The account belongs to the authenticated user.
  • The account is active.
  • The amount is valid.

Each deposit:

  1. Updates the account balance.
  2. Creates a transaction record.
  3. Stores the previous balance.
  4. Stores the resulting balance.

Example:

Previous Balance: 100.00
Deposit:           50.00
New Balance:      150.00

Withdrawals

Withdrawals decrease the balance of an account.

Previous Balance
       -
   Withdrawal
       =
New Balance

Validation Rules

Before processing a withdrawal, the API verifies that:

  • The account exists.
  • The account belongs to the authenticated user.
  • The account is active.
  • The amount is valid.
  • The user has sufficient funds.
  • The balance will not become negative.

Each withdrawal creates a transaction record.

Example:

Previous Balance: 150.00
Withdrawal:        50.00
New Balance:      100.00

Transfers

A transfer moves money from a source account to a destination account.

Source Account
      │
      │ - amount
      ▼
Destination Account
      │
      │ + amount
      ▼

Validation Rules

Before processing a transfer, the API verifies that:

  • The source account exists.
  • The destination account exists.
  • The source account belongs to the authenticated user.
  • The source account is active.
  • The destination account is active.
  • The source account has sufficient funds.
  • The source and destination accounts are different.
  • The transfer amount is valid.

The destination account can belong to another user.


Transfer Flow

Authenticated User
        │
        ▼
Select Source Account
        │
        ▼
Does it belong to the user?
        │
     ┌──┴──┐
    NO     YES
    │       │
   403      ▼
        Is it active?
            │
         ┌──┴──┐
        NO     YES
        │       │
       400      ▼
          Are there enough funds?
               │
            ┌──┴──┐
           NO     YES
           │       │
          400      ▼
              Update balances
                   │
                   ▼
              TRANSFER_OUT
                   +
              TRANSFER_IN
                   │
                   ▼
                 COMMIT
                   │
                   ▼
             Transfer completed

A transfer generates two transaction records:

Source Account
      │
      └── TRANSFER_OUT

Destination Account
      │
      └── TRANSFER_IN

Transaction History

Every financial operation generates a transaction record.

Supported transaction types:

DEPOSIT
WITHDRAW
TRANSFER_IN
TRANSFER_OUT

A transaction contains information such as:

account_id
transaction_type
amount
balance_before
balance_after
description
created_at

This allows the system to maintain a complete history of account movements and track how the account balance changed after each operation.


Transaction Integrity

Operations that modify account balances use database transactions.

When an operation succeeds:

Operation
    │
    ▼
COMMIT
    │
    ▼
Changes Persisted

When an error occurs:

Operation
    │
    ▼
Error
    │
    ▼
ROLLBACK
    │
    ▼
Previous Database State

This is especially important for transfers because two account balances and two transaction records are involved.

The goal is to prevent a transfer from leaving the source account updated while the destination account remains unchanged if an error occurs.


Database

The project uses:

PostgreSQL 16

with:

SQLAlchemy 2
AsyncPG
Alembic

The application uses SQLAlchemy's asynchronous engine with:

postgresql+asyncpg://

Database Migrations

Database migrations are managed using Alembic.

Run migrations

uv run alembic upgrade head

Create a migration

uv run alembic revision --autogenerate -m "description"

Local Installation

Requirements

  • Python 3.14
  • PostgreSQL

Or alternatively:

  • Docker
  • Docker Compose
  • uv

Clone the Repository

git clone https://github.com/IsraelLG22/bankAPI.git

cd bankAPI

Install Dependencies

The project uses uv for dependency management.

uv sync

Environment Variables

Create a:

.env

file in the project root.

Example:

DATABASE_URL=postgresql+asyncpg://USER:PASSWORD@HOST:PORT/DATABASE

SECRET_KEY=your-secret-key

ALGORITHM=HS256

ACCESS_TOKEN_EXPIRE_MINUTES=30

RESET_PASSWORD_TOKEN_SECRET=your-reset-password-secret

VERIFICATION_TOKEN_SECRET=your-verification-secret

Never commit your .env file to GitHub.

Sensitive configuration is managed through environment variables.


Docker

The project includes Docker support for running the API and PostgreSQL locally.

Build the containers

docker compose build

Start the services

docker compose up

Or:

docker compose up --build

Docker Compose

The local environment contains two services:

┌───────────────────────────────────────┐
│           Docker Compose              │
│                                       │
│  ┌────────────────┐ ┌──────────────┐  │
│  │     FastAPI    │ │  PostgreSQL  │  │
│  │     :8000      │ │    :5433     │  │
│  └────────────────┘ └──────────────┘  │
│                                       │
└───────────────────────────────────────┘

The API is available at:

http://localhost:8000

Swagger UI:

http://localhost:8000/docs

ReDoc:

http://localhost:8000/redoc

Stop Docker

docker compose down

Do not use docker compose down -v if you want to preserve your local PostgreSQL data.


Testing

The project uses:

  • Pytest
  • pytest-asyncio
  • pytest-cov
  • HTTPX

Automated tests cover the main functionality of the API:

  • Authentication
  • User management
  • Roles
  • Bank accounts
  • Deposits
  • Withdrawals
  • Transfers
  • Validation rules
  • Authorization
  • Error handling

Run All Tests

uv run pytest -v

Run a Specific Test File

uv run pytest tests/test_auth.py -v

Run a Specific Test

uv run pytest tests/test_auth.py::test_login -v

Code Coverage

The project currently achieves approximately:

99% code coverage

Current coverage result:

TOTAL    437    3    99%

Run the coverage report with:

uv run pytest --cov=app --cov-report=term-missing

Continuous Integration

The project uses GitHub Actions to automatically run tests.

Workflow:

.github/workflows/tests.yml

The workflow runs on:

push → main
push → master

pull_request → main
pull_request → master

CI Pipeline

GitHub
   │
   ▼
Checkout Repository
   │
   ▼
Python 3.14
   │
   ▼
Install uv
   │
   ▼
uv sync --frozen
   │
   ▼
Run Tests
   │
   ▼
Run Coverage

This helps detect regressions before changes are integrated into the project.


Deployment

The API is deployed to production using:

Docker
Render
PostgreSQL

Deployment architecture:

                 GitHub
                    │
                    ▼
              GitHub Actions
              Tests + Coverage
                    │
                    ▼
                  Render
              ┌─────┴─────┐
              │           │
              ▼           ▼
         Web Service   PostgreSQL
              │
              ▼
           Docker
              │
              ▼
           FastAPI

Production Environment

The application uses environment variables configured in Render.

The production database is independent from the PostgreSQL database used by the local Docker Compose environment.

Database migrations are executed during deployment/startup:

uv run alembic upgrade head

The FastAPI application is then started using Uvicorn:

uv run uvicorn app.main:app

Main API Endpoints

Authentication

POST /auth/register
POST /auth/jwt/login

Users

GET /users/
GET /users/{user_id}
PATCH /users/{user_id}/role

Accounts

POST /accounts/
GET /accounts/me
GET /accounts/
PATCH /accounts/{account_id}/status

Transactions

POST /transactions/deposit
POST /transactions/withdraw
GET /transactions/{account_id}

Transfers

POST /transfers/

Visit /docs to see the complete API specification, request parameters, response schemas, and HTTP status codes.


API Documentation

FastAPI automatically generates OpenAPI documentation.

Swagger UI

/docs

ReDoc

/redoc

The interactive documentation allows developers to inspect and test the API endpoints directly.


Security

The project implements:

  • JWT authentication
  • Role-based access control
  • Protected endpoints
  • Pydantic data validation
  • Password hashing
  • Environment-based secrets
  • Account ownership validation
  • Balance validation
  • Active account validation
  • PostgreSQL integrity constraints
  • Database transactions
  • Rollback on failed operations

Sensitive credentials and secrets are not stored in the repository.


Important Files

File Description
app/main.py FastAPI application entry point
app/db.py SQLAlchemy engine and session configuration
app/config.py Application configuration and environment variables
app/auth/ Authentication and authorization
app/models/ Database models
app/schemas/ Pydantic schemas
app/services/ Business logic
app/routers/ API endpoints
alembic/ Database migrations
tests/ Automated tests
Dockerfile Docker image configuration
docker-compose.yml Local Docker environment
.dockerignore Files excluded from the Docker build context
.github/workflows/tests.yml GitHub Actions CI workflow
pyproject.toml Project configuration and dependencies
uv.lock Locked dependency versions

Project Status

The following features are currently implemented:

  • FastAPI
  • PostgreSQL
  • SQLAlchemy Async
  • AsyncPG
  • Alembic
  • UUID identifiers
  • JWT Authentication
  • Role-based authorization
  • User management
  • Bank account management
  • Deposits
  • Withdrawals
  • Transfers
  • Transaction history
  • Business rule validation
  • Automated tests
  • 99% code coverage
  • Docker
  • Docker Compose
  • Git
  • GitHub
  • GitHub Actions
  • Continuous Integration
  • Production PostgreSQL
  • Render deployment
  • Production API

🔮 Future Improvements

Possible future improvements include:

  • Refresh tokens
  • Password recovery
  • Email verification
  • User pagination
  • Transaction pagination
  • Rate limiting
  • Environment-specific CORS configuration
  • Structured logging
  • Application monitoring
  • Health check endpoint
  • Full CI/CD pipeline
  • Frontend application
  • Load testing
  • Financial reports
  • Additional account management features

Author

Israel Lopez

Backend project developed using Python and FastAPI.

The project focuses on:

  • REST API development
  • Backend architecture
  • Authentication and authorization
  • Relational databases
  • Asynchronous programming
  • Automated testing
  • Docker
  • Continuous Integration
  • Production deployment

License

This project was developed for educational purposes and as a demonstration of backend development skills.

About

RESTful banking API built with FastAPI, PostgreSQL, SQLAlchemy, JWT authentication, role-based access control, transactions, transfers, automated tests, and Docker.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages