Wallet Payment Backend
A production-style digital wallet backend focused on transactional correctness, reliability, and auditability.
Built with FastAPI, SQLModel, Redis, and Dramatiq, this project demonstrates how real-world financial APIs handle consistency guarantees, idempotent retries, double-entry ledgers, and async background processing. Every endpoint is crafted to reflect production patterns used in payment platforms.
Why this project exists
Financial backends demand more than CRUD. Every transfer, deposit, and withdrawal must preserve consistency across accounts, maintain an immutable audit trail, and handle failures without losing money. This project implements those production primitives — atomic database transactions, Redis-backed idempotency for safe retries, double-entry accounting with balance snapshots, and async workers that decouple side effects from the request path. It is a reference for how real payment backends are structured.
What it demonstrates
Architecture
Transaction Flow
Get started
Explore the full API surface via Swagger UI, browse the ReDoc documentation, or view the source on GitHub.
API Reference
Request–response examples for every endpoint.
Authentication
POST /signup
{
"first_name": "Jane",
"last_name": "Doe",
"email": "jane@example.com",
"password": "securepass123"
}
{
"id": 1,
"first_name": "Jane",
"last_name": "Doe",
"email": "jane@example.com"
}
POST /token
username: jane@example.com
password: securepass123
{
"access_token": "eyJhbGciOiJI...",
"token_type": "bearer"
}
Wallet
POST /wallet
Authorization: Bearer <token>
{
"balance": 500,
"currency": "USD"
}
{
"id": 1,
"user_id": 1,
"balance": 500,
"created_at": "2026-05-31T12:00:00",
"currency": "USD"
}
GET /wallet
Authorization: Bearer <token>
{
"id": 1,
"user_id": 1,
"balance": 500,
"created_at": "2026-05-31T12:00:00",
"updated_at": "2026-05-31T12:00:00",
"currency": "USD",
"full name": "Jane Doe"
}
DELETE /wallet
Authorization: Bearer <token>
{
"message": "wallet belonging to Jane Doe deleted successfully"
}
Transaction
PATCH /transaction/deposit
Authorization: Bearer <token>
X-Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000
{
"amount": 200,
"currency": "USD"
}
{
"wallet_id": 1,
"amount": 200,
"current_balance": 700
}
PATCH /transaction/withdraw
Authorization: Bearer <token>
X-Idempotency-Key: 660e8400-e29b-41d4-a716-446655440001
{
"amount": 50,
"currency": "USD"
}
{
"wallet_id": 1,
"amount": 50,
"current_balance": 650
}
PATCH /transaction/transfer
Authorization: Bearer <token>
X-Idempotency-Key: 770e8400-e29b-41d4-a716-446655440002
{
"to_account_id": 2,
"amount": 100,
"currency": "USD"
}
{
"wallet_id": 1,
"recipient_wallet_id": 2,
"amount": 100,
"current_balance": 550
}
GET /transaction/history
Authorization: Bearer <token>
?limit=10&offset=0
{
"transactions": [
{
"id": 3,
"amount": 100,
"currency": "USD",
"type": "transfer",
"date": "2026-05-31T12:05:00",
"sender": "Jane Doe",
"receiver": "John Smith"
},
{
"id": 2,
"amount": 50,
"currency": "USD",
"type": "withdrawal",
"date": "2026-05-31T12:03:00",
"sender": "Jane Doe",
"receiver": "External Destination"
}
],
"limit": 10,
"offset": 0
}
GET /transaction/{id}/ledger
Authorization: Bearer <token>
/transaction/3/ledger
[
{
"id": 5,
"transaction_id": 3,
"wallet_id": 1,
"entry_type": "debit",
"amount": 100,
"currency": "USD",
"balance_snapshot": 550,
"created_at": "2026-05-31T12:05:00"
},
{
"id": 6,
"transaction_id": 3,
"wallet_id": 2,
"entry_type": "credit",
"amount": 100,
"currency": "USD",
"balance_snapshot": 300,
"created_at": "2026-05-31T12:05:00"
}
]
Users
GET /users/{user_id}
/users/1
{
"id": 1,
"first_name": "Jane",
"last_name": "Doe",
"email": "jane@example.com"
}