Skip to content

Repository files navigation

🏦 Banking API Platform

A REST API for an online banking domain, with the business rules enforced inside the database

Customers, accounts and transactions served over a documented REST API, with MySQL triggers, stored procedures and audit logs doing the work that application code usually duplicates.

CI License: MIT


πŸ›  Tech Stack

Backend
Python Flask Gunicorn JWT Swagger

Database
MySQL SQL

Infrastructure
Docker Terraform AWS GitHub Actions

Admin UI
Gradio


🎬 Demo

Demo

Admin UI: customers, a customer's accounts, an account's transactions. Then live API requests against the same data, including the audit log written by triggers.

β–Ά Watch the full video

Screenshots of every section

Admin UI β€” customers β€” full CRUD over the customer table

Customers

Admin UI β€” accounts of a customer β€” filtered by customer id

Accounts

Admin UI β€” transactions of an account

Transactions

Admin UI β€” transactions across several accounts β€” many-to-many link table

Account links

API β€” all endpoints β€” 30+ operations grouped by resource, JWT-protected ones marked with a lock

API overview

API β€” GET /customers β€” live request and response

Customers endpoint

API β€” GET /transactions

Transactions endpoint

API β€” GET /logs β€” the audit trail written by database triggers

Logs endpoint


πŸš€ Quick Start

Requirements

  • Docker and Docker Compose, or Python 3.12+ with a reachable MySQL 8 instance

Run with Docker

git clone https://github.com/sergiyclas/banking-api-platform.git
cd banking-api-platform
cp .env.example .env          # set DB_PASSWORD and JWT_SECRET
docker compose up

The compose file starts MySQL, waits for it to become healthy, then starts the API.

Run locally

git clone https://github.com/sergiyclas/banking-api-platform.git
cd banking-api-platform
python -m venv .venv && source .venv/bin/activate    # Windows: .venv\Scripts\activate
pip install -r requirements.txt
cp .env.example .env          # point DB_* at your MySQL instance
python app.py

Open http://localhost:5000/apidocs for the API documentation.

To launch the admin UI in a separate process:

python ui.py       # http://localhost:7860

On the first start the app creates the database and runs scenary.sql, which builds the schema and seeds sample customers, accounts and transactions.


✨ Features

πŸ—„ Business rules inside the database

  • Triggers write the audit log on every insert, update and delete
  • Stored procedures encapsulate multi-step operations, called by name from the DAO
  • SQL functions back the aggregate endpoints such as POST /transactions/count
  • The API stays thin instead of reimplementing the same guarantees in Python

πŸ“‹ Documented REST API

  • 30+ operations across customers, accounts, transactions and logs
  • Every endpoint carries an OpenAPI description, so /apidocs is a usable client
  • Request and response schemas visible per endpoint

πŸ” JWT authentication

  • POST /login issues a token; account endpoints require it
  • Swagger accepts the token through the standard Authorize dialog
  • Signing key comes from the environment, never from the code

πŸ–₯ Admin UI over the same service layer

  • Gradio interface for CRUD, filtering and demos
  • Calls the very same service classes the HTTP layer uses β€” no second implementation
  • Runs as a separate process, so the API can be deployed without it

☁️ Reproducible AWS infrastructure

  • infra/terraform provisions a VPC across two availability zones
  • Application load balancer in front of an auto-scaling group
  • terraform.tfvars.example documents every input variable

πŸ“ˆ Load-testing harness

  • load_test/ drives concurrent traffic against every endpoint
  • Reports latency and error rate per endpoint
  • Packaged in its own container so it can run against a deployed instance

πŸ— Architecture

flowchart LR
    C([Client]) -->|REST| API[Flask API]
    G([Admin]) -->|Gradio UI| SVC
    API --> SVC[Service layer]
    SVC --> DAO[DAO layer]
    DAO --> DB[(MySQL 8)]
    DB -->|triggers| LOG[(Audit log)]
Loading

Layers

Layer Responsibility Location
Route HTTP handling, OpenAPI docs, JWT checks my_project/auth/route/
Service Business operations my_project/auth/service/
DAO SQL, lazily opened connections my_project/auth/dao/
Domain Plain data classes my_project/auth/domain/
Database Schema, triggers, procedures, functions scenary.sql, triggers_procedures.sql

Project layout

my_project/               route β†’ service β†’ DAO β†’ domain layers
config/                   database configuration from environment variables
infra/terraform/          AWS VPC, ALB and auto-scaling group
load_test/                concurrent traffic generator (containerised)
tests/                    unit tests
scenary.sql               schema and seed data
triggers_procedures.sql   triggers, stored procedures and functions
ui.py                     Gradio admin interface

πŸ“‘ API

Selected endpoints; the full list with request and response schemas is on /apidocs.

Method Endpoint Description
POST /login Obtain a JWT token
GET /customers List customers
POST /customers Create a customer
GET /customers/{id}/accounts Accounts of one customer
GET /accounts List accounts (JWT required)
GET /transactions List transactions
POST /transactions/count Aggregate transactions through a SQL function
GET /accounts/{id}/transactions Transactions linked to an account
GET /logs Audit log written by triggers
GET /health Health probe

Example

curl http://localhost:5000/customers
[
  { "customer_id": 1, "customer_name": "Customer 1",
    "email": "customer1@mail.com", "phone": "+380981234567" }
]

βš™οΈ Configuration

Variable Description Default
DB_HOST MySQL host localhost
DB_PORT MySQL port 3306
DB_USER MySQL user root
DB_PASSWORD MySQL password –
DB_NAME Database name online_banking
JWT_SECRET Signing key for JWT tokens –
HOST / PORT Flask bind address 0.0.0.0 / 5000

☁️ Deployment

cd infra/terraform
cp terraform.tfvars.example terraform.tfvars   # set region, project name, CIDRs
terraform init
terraform plan
terraform apply

Terraform creates a VPC with public subnets in two availability zones, an internet gateway, an application load balancer and an auto-scaling group running the container.

.github/workflows/deploy.yml ships the app to a VM over SSH. It is triggered manually (workflow_dispatch) because it depends on repository secrets for the target host.


πŸ§ͺ Testing

pip install pytest ruff
pytest
ruff check .

Unit tests cover the database configuration and the DAO connection handling, and run without a database. Load testing is separate:

cd load_test
docker build -t banking-load-test .
docker run --rm banking-load-test

πŸ“¬ Contact

Serhiy Dzen – AI Software Engineer

Email LinkedIn GitHub


Licensed under the MIT License

About

Banking REST API: Flask + MySQL with JWT auth, Swagger docs, triggers/stored procedures and Docker deployment

Topics

Resources

Stars

1 star

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages