This is my solution for Expense Tracker API challenge, provided by Developer Roadmaps. It is a RESTful API designed to track user expenses, allowing users to create, list, update, and delete expenses. Users can register and log in, and each user has their own isolated set of expenses.
Key features:
- JWT-based authentication and authorization
- Input validation for authentication and expense operations
- Full CRUD operations for expenses
- Pagination and flexible sorting for expense listing
- Date range filtering for expenses
- Swagger UI documentation
- Soft delete support for user profiles
For Docker (Recommended):
- Docker & Docker Compose
For Local Development:
- Java 21+
- Maven 3.9+
- PostgreSQL 18+
This is the simplest setup. Docker Compose will automatically build and start all required services, using default values in the Compose file.
docker compose up -d --buildThen access the application at http://localhost:8080/ (or the port you configured).
Optionally, you can override any environment variables with your own settings.
cp .env.example .env
# Edit .env with your local values-
Create a PostgreSQL database
-
Set the required environment variables using either method below:
-
Option 1: Using
.envfile. Copy the example file and edit with your values:cp .env.example .env # Edit .env with your local settings -
Option 2: Exporting via shell
export PG_USERNAME=<your-postgresql-user-here> export PG_PASSWORD=<your-postgresql-password-here> export POSTGRES_DB=<database-name> export JWT_SECRET=<jwt-secret-here>
-
-
(Optional) Set server port:
export PORT=8081- Start the application:
mvn spring-boot:run- Access at
http://localhost:8080/(or the port you configured).
| Variable | For Docker | For Local Development | Description |
|---|---|---|---|
| PORT | Optional (Default: 8080) |
Optional (Default: 8080) |
Server port |
| PG_USERNAME | Optional (Default: admin) |
Required | PostgreSQL username |
| PG_PASSWORD | Optional (Default: dbpassword) |
Required | PostgreSQL password |
| POSTGRES_DB | Optional (Default: expenses_db) |
Required (must match the manually created database) | PostgreSQL database name |
| JWT_SECRET | Optional (Default: see compose) | Required | Secret key for signing JWT tokens. Use a strong random value in production. |
Warning
Never use the default JWT_SECRET value in production. Generate a secure secret with:
openssl rand -hex 32Once the application is running, you can interact via Swagger UI at /docs or directly through HTTP requests.
| Route | HTTP Method | Params | Description | Auth |
|---|---|---|---|---|
/docs |
GET | - | Swagger documentation | None |
/api/v1/auth/register |
POST | Body with name, email and password |
Register a new user | None |
/api/v1/auth/login |
POST | Body with email and password |
Login an existing user | None |
/api/v1/users/{id} |
PUT | {id} + Body with fields to update |
Update user profile | Bearer |
/api/v1/users/{id} |
DELETE | {id} |
Delete user profile | Bearer |
/api/v1/expenses |
GET | Query Parameters: • page - Page number (default: 0)• size - Page size (default: 10)• orderBy - Sort field (default: name)• direction - Sort direction: ASC/DESC (default: ASC)• startDate - Filter from date (format: yyyy-MM-dd)• endDate - Filter until date (format: yyyy-MM-dd) |
Retrieve paginated and sorted expenses | Bearer |
/api/v1/expenses |
POST | Body with name, description, amount, category and date |
Create a new expense | Bearer |
/api/v1/expenses/{id} |
GET | {id} |
Retrieve an expense by its ID | Bearer |
/api/v1/expenses/{id} |
PATCH | {id} + Body with fields to update |
Update an existing expense | Bearer |
/api/v1/expenses/{id} |
DELETE | {id} |
Delete an existing expense | Bearer |
POST /api/v1/auth/register
{
"name": "John Doe",
"email": "johndoe@gmail.com",
"password": "#P4ssword_"
}POST /api/v1/auth/login
{
"email": "johndoe@gmail.com",
"password": "#P4ssword_"
}PUT /api/v1/users/{id}
{
"email": "johndoeupdated@gmail.com"
}POST /api/v1/expenses
{
"name": "Prime Video",
"description": "Amazon Prime subscription",
"amount": 19.9,
"category": "subscriptions",
"date": "2025-12-12"
}PATCH /api/v1/expenses/{id}
{
"amount": 24.9
}