A simple event booking system with tickets and payments. Built as microservices. Uses JWT for auth and Redis for caching. Can run in Docker.
Two main services:
- BookingService (port 5001) — events, tickets, users, venues
- PaymentService (port 5079) — payment handling and ticket validation
- PostgreSQL (port 5432) — main database
- Redis (port 6379) — caching layer
- ASP.NET Core 10.0
- Clean Architecture (Domain / Application / Infrastructure / Presentation)
- PostgreSQL + EF Core
- Redis (StackExchange.Redis)
- JWT auth with User/Admin roles
- Docker + Docker Compose
- Swagger for API docs
- AutoMapper
- BCrypt for password hashing
- JWT-based login
- Passwords hashed with BCrypt
- Role checks (User, Admin)
- Secrets passed via environment variables, not hardcoded in config
- Clone the repo:
git clone https://github.com/YOUR_USERNAME/EventBookingAPI.git
cd EventBookingAPI- Create
.envfile in the project root:
POSTGRES_USER=postgres
POSTGRES_PASSWORD=your_postgres_password
JWT_SECRET=your_super_secret_key_at_least_32_chars
INTERNAL_SECRET=your_internal_service_secretThe same
JWT_SECRETis used by both services — they must match.
- Start everything:
docker compose up -d --buildMigrations run automatically on first start. Swagger UI:
- Clone the repo and copy config templates:
git clone https://github.com/YOUR_USERNAME/EventBookingAPI.git
cd EventBookingAPI
cp BookingService/Presentation/appsettings.Example.json BookingService/Presentation/appsettings.json
cp PaymentService/Presentation/appsettings.Example.json PaymentService/Presentation/appsettings.json-
Edit both
appsettings.jsonfiles — fill in your PostgreSQL credentials. -
Set the
JWT_SECRETenvironment variable (must be the same for both services):
# Linux/macOS
export JWT_SECRET=your_super_secret_key_at_least_32_chars
# Windows (PowerShell)
$env:JWT_SECRET="your_super_secret_key_at_least_32_chars"- Apply DB migrations:
dotnet ef database update -p BookingService/Infrastructure -s BookingService/Presentation
dotnet ef database update -p PaymentService/Infrastructure -s PaymentService/Presentation- Start services (two terminals):
cd BookingService/Presentation && dotnet runcd PaymentService/Presentation && dotnet runPOST /api/auth/register
{ "email": "user@example.com", "password": "YourPassword123!" }
POST /api/auth/login
{ "email": "user@example.com", "password": "YourPassword123!" }
Response:
{ "token": "eyJhbGci..." }Click the Authorize button at the top of the Swagger page, paste the token, click Authorize.
All endpoints except /api/auth/* require Authorization: Bearer <token>.
| Method | Endpoint | Auth |
|---|---|---|
| POST | /api/auth/register | No |
| POST | /api/auth/login | No |
| Method | Endpoint | Auth |
|---|---|---|
| GET | /api/event | Yes |
| GET | /api/event/{id} | Yes |
| POST | /api/event | Yes |
| PATCH | /api/event/{id} | Yes |
| DELETE | /api/event/{id} | Yes |
| Method | Endpoint | Auth |
|---|---|---|
| GET | /api/ticket | Yes |
| GET | /api/ticket/{id} | Yes |
| GET | /api/ticket/paged?page=1&pageSize=10 | Yes |
| POST | /api/ticket | Yes |
| PATCH | /api/ticket/{id} | Yes |
| DELETE | /api/ticket/{id} | Yes |
| Method | Endpoint | Auth |
|---|---|---|
| GET | /api/user | Yes |
| GET | /api/user/{id} | Yes |
| POST | /api/user | Yes |
| PATCH | /api/user/{id} | Yes |
| DELETE | /api/user/{id} | Yes |
| Method | Endpoint | Auth |
|---|---|---|
| GET | /api/venue | Yes |
| GET | /api/venue/{id} | Yes |
| POST | /api/venue | Yes |
| PATCH | /api/venue/{id} | Yes |
| DELETE | /api/venue/{id} | Yes |
| Method | Endpoint | Auth |
|---|---|---|
| GET | /api/payment | Yes |
| GET | /api/payment/{id} | Yes |
| POST | /api/payment | Yes |
docker compose up -d --build # build and start
docker compose up -d # start (no rebuild)
docker compose down # stop
docker compose down -v # stop + delete all data
docker compose logs -f # stream logs
docker compose logs -f booking-service # logs for one service
docker compose exec booking-service /bin/bash