A production-ready RESTful API for equipment rental management built with Go's standard library.
goapi.mp4
- JWT authentication with role-based access (owner/renter)
- Full equipment CRUD with photo uploads, search, and filtering
- Reservation lifecycle: create, approve, reject, cancel, complete
- Notification system for reservation updates
- Interactive API docs via Scalar UI (OpenAPI 3.1)
- Pagination on all list endpoints
Layered architecture using only Go's standard library (net/http) -- no web framework. Requests flow through a middleware chain (CORS, Logger, Recovery, Auth) into handlers, which delegate to services for business logic, which call repositories for data access against PostgreSQL.
Handler -> Service -> Repository -> PostgreSQL
- Go 1.24+
- Docker and Docker Compose (recommended)
- PostgreSQL 16 (if running without Docker)
git clone https://github.com/abneribeiro/goapi.git
cd goapi
docker compose up -dThe API will be available at http://localhost:8080.
# View logs
docker compose logs -f api
# Stop services
docker compose down
# Stop and remove volumes
docker compose down -vgit clone https://github.com/abneribeiro/goapi.git
cd goapi
go mod downloadStart PostgreSQL:
docker compose up -d postgresSet environment variables:
export DB_HOST=localhost DB_PORT=5432 DB_USER=postgres DB_PASSWORD=postgres DB_NAME=equipment_rental
export JWT_SECRET=your-secure-secret-keyRun the server from the project root (required for static file resolution):
go run ./cmd/apiOptionally seed the database with sample data:
go run ./scripts/seed/main.goThis creates test users:
| Password | Role | |
|---|---|---|
| owner@example.com | Password123 | owner |
| renter@example.com | Password123 | renter |
| owner2@example.com | Password123 | owner |
- Scalar UI: http://localhost:8080/docs
- OpenAPI Spec: http://localhost:8080/docs/openapi.yaml
| Method | Endpoint | Description |
|---|---|---|
| GET | /health |
API health status |
| Method | Endpoint | Description |
|---|---|---|
| POST | /api/v1/auth/register |
Register new user |
| POST | /api/v1/auth/login |
Login user |
| Method | Endpoint | Auth | Description |
|---|---|---|---|
| GET | /api/v1/users/me |
Required | Get current user profile |
| PUT | /api/v1/users/me |
Required | Update current user profile |
| Method | Endpoint | Auth | Description |
|---|---|---|---|
| GET | /api/v1/equipment |
- | List equipment (paginated, filterable) |
| GET | /api/v1/equipment/search |
- | Search equipment |
| GET | /api/v1/equipment/categories |
- | Get available categories |
| GET | /api/v1/equipment/{id} |
- | Get equipment by ID |
| GET | /api/v1/equipment/{id}/availability |
- | Get availability calendar |
| POST | /api/v1/equipment |
Required | Create equipment |
| PUT | /api/v1/equipment/{id} |
Required | Update equipment |
| DELETE | /api/v1/equipment/{id} |
Required | Delete equipment |
| POST | /api/v1/equipment/{id}/photos |
Required | Upload equipment photo |
| Method | Endpoint | Auth | Description |
|---|---|---|---|
| GET | /api/v1/reservations |
Required | List my reservations |
| GET | /api/v1/reservations/owner |
Required | List reservations for my equipment |
| GET | /api/v1/reservations/{id} |
Required | Get reservation by ID |
| POST | /api/v1/reservations |
Required | Create reservation |
| PUT | /api/v1/reservations/{id}/approve |
Required | Approve reservation (owner) |
| PUT | /api/v1/reservations/{id}/reject |
Required | Reject reservation (owner) |
| PUT | /api/v1/reservations/{id}/cancel |
Required | Cancel reservation |
| PUT | /api/v1/reservations/{id}/complete |
Required | Complete reservation (owner) |
| Method | Endpoint | Auth | Description |
|---|---|---|---|
| GET | /api/v1/notifications |
Required | List notifications |
| GET | /api/v1/notifications/unread-count |
Required | Get unread count |
| PUT | /api/v1/notifications/{id}/read |
Required | Mark as read |
| PUT | /api/v1/notifications/read-all |
Required | Mark all as read |
| DELETE | /api/v1/notifications/{id} |
Required | Delete notification |
Include the JWT token in the Authorization header:
Authorization: Bearer <token>
Token expiration: 24 hours (configurable via JWT_EXPIRATION_HOURS).
All configuration is done via environment variables:
| Variable | Description | Default |
|---|---|---|
SERVER_HOST |
Server host address | 0.0.0.0 |
SERVER_PORT |
Server port | 8080 |
DB_HOST |
PostgreSQL host | localhost |
DB_PORT |
PostgreSQL port | 5432 |
DB_USER |
Database user | postgres |
DB_PASSWORD |
Database password | postgres |
DB_NAME |
Database name | equipment_rental |
DB_SSLMODE |
PostgreSQL SSL mode | disable |
JWT_SECRET |
JWT signing secret | - |
JWT_EXPIRATION_HOURS |
Token expiration (hours) | 24 |
LOG_LEVEL |
Logging level (debug/info/warn/error) | debug |
UPLOAD_PATH |
File upload directory | ./uploads |
DOCS_PATH |
Documentation files directory | ./docs |
MAX_FILE_SIZE |
Max upload size (bytes) | 10485760 |
cp .env.example .envgo test ./... -v # Run all tests
go test ./... -coverprofile=coverage.out # With coverage
go tool cover -html=coverage.out -o coverage.html # Coverage report
go test ./internal/handler/... -v # Single packagegoapi/
├── cmd/
│ └── api/
│ └── main.go # Application entry point
├── internal/
│ ├── config/ # Configuration management
│ │ └── config.go
│ ├── database/ # Database connection & migrations
│ │ ├── postgres.go
│ │ └── migrations.go
│ ├── handler/ # HTTP handlers (controllers)
│ │ ├── auth.go
│ │ ├── user.go
│ │ ├── equipment.go
│ │ ├── reservation.go
│ │ ├── notification.go
│ │ └── docs.go
│ ├── middleware/ # HTTP middleware
│ │ ├── auth.go
│ │ ├── cors.go
│ │ ├── logger.go
│ │ └── recovery.go
│ ├── model/ # Data models & DTOs
│ │ ├── user.go
│ │ ├── equipment.go
│ │ ├── reservation.go
│ │ ├── notification.go
│ │ └── response.go
│ ├── pkg/ # Internal packages
│ │ ├── jwt/ # JWT utilities
│ │ ├── logger/ # Structured logging
│ │ ├── pagination/ # Pagination helpers
│ │ └── validator/ # Input validation
│ ├── repository/ # Data access layer
│ │ ├── user.go
│ │ ├── equipment.go
│ │ ├── reservation.go
│ │ └── notification.go
│ ├── router/ # Route configuration
│ │ └── router.go
│ └── service/ # Business logic layer
│ ├── auth.go
│ ├── user.go
│ ├── equipment.go
│ ├── reservation.go
│ └── notification.go
├── docs/
│ └── openapi.yaml # OpenAPI 3.1 specification
├── scripts/
│ └── seed/ # Database seeding
│ └── main.go
├── requests/ # HTTP request test files
├── uploads/ # File upload directory
├── .env.example # Example environment variables
├── Dockerfile
├── docker compose.yml
├── go.mod
├── go.sum
└── README.md
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.
Built with Go by Abner Ribeiro