REST API backend using Golang (Gin) + MySQL + Clean Architecture to manage football teams, players, match schedules, match results, and statistical reports.
- Go 1.25+
- MySQL 8.0+
- Docker & Docker Compose (optional, for Docker setup)
- Clone repository and navigate to project directory:
cd football-management-api- Run with Docker Compose:
docker-compose up -d-
Server will run at
http://localhost:8080. Table migrations and seeders are automatically executed on startup. -
To view logs:
docker-compose logs -f api- To stop:
docker-compose down- To remove database data (reset):
docker-compose down -vNote: Docker Compose automatically configures MySQL and API. Database will be created automatically with credentials:
- User:
football_user - Password:
football_password - Database:
football_management
- Create MySQL database:
CREATE DATABASE football_management;- Copy and configure environment file:
cp .env.example .envConfigure DB_USER, DB_PASSWORD, and JWT_SECRET in the .env file.
- Run server:
go run cmd/main.goServer will run at http://localhost:8080. Table migrations and seeders are automatically executed on startup.
After the server is running, access Swagger UI at:
http://localhost:8080/swagger/index.html
To use JWT-protected endpoints, click the Authorize button and enter the token in the format:
Bearer <token>
If there are changes to handler annotations, run:
swag init -g cmd/main.go -o docs --parseDependency --parseInternalSeeder runs automatically on startup and is idempotent (no duplication if data already exists).
Seeded data:
| Data | Count | Details |
|---|---|---|
| Users | 1 | admin / admin123 |
| Teams | 4 | Persib Bandung, Persija Jakarta, Arema FC, PSM Makassar |
| Players | 20 | 5 players per team (various positions) |
| Matches | 5 | 2 completed + 3 scheduled |
| Goals | 5 | 3 goals in match 1, 2 goals in match 2 |
To reset seed data, clear tables in the database then restart the server.
| Method | Endpoint | Description |
|---|---|---|
| POST | /api/v1/auth/register |
Register new admin |
| POST | /api/v1/auth/login |
Login, get JWT token |
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/v1/teams |
List all teams |
| GET | /api/v1/teams/:id |
Team details with players |
| POST | /api/v1/teams |
Add new team |
| PUT | /api/v1/teams/:id |
Update team information |
| DELETE | /api/v1/teams/:id |
Soft delete team |
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/v1/teams/:id/players |
List players per team |
| POST | /api/v1/teams/:id/players |
Add player to team |
| GET | /api/v1/players/:id |
Player details |
| PUT | /api/v1/players/:id |
Update player |
| DELETE | /api/v1/players/:id |
Soft delete player |
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/v1/matches |
List all matches |
| GET | /api/v1/matches/:id |
Match details |
| POST | /api/v1/matches |
Create match schedule |
| PUT | /api/v1/matches/:id |
Update schedule |
| DELETE | /api/v1/matches/:id |
Soft delete match |
| POST | /api/v1/matches/:id/result |
Report match result |
| GET | /api/v1/matches/:id/goals |
List match goals |
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/v1/reports/matches/:id |
Complete match report |
| GET | /api/v1/reports/top-scorers |
Top scorers list |
curl -X POST http://localhost:8080/api/v1/auth/login \
-H "Content-Type: application/json" \
-d '{"username": "admin", "password": "admin123"}'curl -X POST http://localhost:8080/api/v1/auth/register \
-H "Content-Type: application/json" \
-d '{"username": "manager", "password": "password123"}'curl -X POST http://localhost:8080/api/v1/teams \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <token>" \
-d '{
"name": "Bali United",
"logo_url": "https://example.com/bali-united.png",
"founded_year": 2010,
"address": "Jl. Ngurah Rai No.1",
"city": "Gianyar"
}'curl -X POST http://localhost:8080/api/v1/teams/1/players \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <token>" \
-d '{
"name": "Ciro Alves",
"height_cm": 182,
"weight_kg": 76,
"position": "penyerang",
"jersey_number": 11
}'curl -X POST http://localhost:8080/api/v1/matches \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <token>" \
-d '{
"home_team_id": 1,
"away_team_id": 2,
"match_date": "2026-05-01",
"match_time": "19:30"
}'curl -X POST http://localhost:8080/api/v1/matches/3/result \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <token>" \
-d '{
"goals": [
{"player_id": 6, "team_id": 2, "minute": 12},
{"player_id": 1, "team_id": 1, "minute": 55},
{"player_id": 6, "team_id": 2, "minute": 89}
]
}'curl http://localhost:8080/api/v1/reports/matches/1 \
-H "Authorization: Bearer <token>"curl http://localhost:8080/api/v1/reports/top-scorers?limit=5 \
-H "Authorization: Bearer <token>"- JWT Authentication - All endpoints (except login/register) are protected with Bearer token
- Password Hashing - Bcrypt for storing admin passwords
- Input Validation - Validation using Gin binding tags
- Soft Delete - Data is not permanently deleted, only marked with
deleted_at - CORS Middleware - For cross-origin request security
- SQL Injection Protection - GORM parameterized queries