Go REST API backend for the SetHabit fitness tracking platform. Provides CRUD, analytics, delta sync, and GDPR compliance endpoints.
cmd/sethabit-api/ # Entry point
internal/
├── config/ # Environment-based configuration
├── database/ # PostgreSQL connection + auto-migrations
├── handlers/ # HTTP handlers (one file per domain)
├── models/ # Data models
└── services/ # Business logic layer
pkg/
└── middleware/ # JWT auth, CORS, logging middleware
migrations/ # SQL migration files (run on startup)
.\dev.ps1 db-up # Start local PostgreSQL in Docker
.\dev.ps1 migrate-up # Run migrations
.\dev.ps1 run # Start API with hot reload
Or manually:
cp .env.example .env # Configure database + JWT secret
go run cmd/sethabit-api/main.go
The API runs at http://localhost:8000 by default.
All endpoints under /api/v1/. Protected routes require Authorization: Bearer <JWT> from the auth service.
| Method |
Path |
Description |
| GET |
/ping |
Health check |
| Method |
Path |
Description |
| GET |
/users/me |
Get profile |
| PUT |
/users/me |
Update profile |
| Method |
Path |
Description |
| GET |
/weights |
List weight entries |
| POST |
/weights |
Create weight entry |
| GET |
/weights/:id |
Get entry |
| PUT |
/weights/:id |
Update entry |
| DELETE |
/weights/:id |
Delete entry |
| Method |
Path |
Description |
| GET |
/exercises |
List exercises |
| POST |
/exercises |
Create exercise |
| GET |
/exercises/:id |
Get exercise |
| PUT |
/exercises/:id |
Update exercise |
| DELETE |
/exercises/:id |
Delete exercise |
| POST |
/exercises/:id/image |
Upload exercise image |
| DELETE |
/exercises/:id/image |
Delete exercise image |
| Method |
Path |
Description |
| GET |
/metadata/types |
List metadata types |
| GET |
/metadata?type= |
Get user metadata by type |
| Method |
Path |
Description |
| GET |
/exercise-logs |
List logs |
| POST |
/exercise-logs |
Create log |
| GET |
/exercise-logs/:id |
Get log |
| PUT |
/exercise-logs/:id |
Update log |
| DELETE |
/exercise-logs/:id |
Delete log |
| Method |
Path |
Description |
| GET |
/workouts |
List workouts |
| POST |
/workouts |
Create workout |
| GET |
/workouts/:id |
Get workout |
| PUT |
/workouts/:id |
Update workout |
| DELETE |
/workouts/:id |
Delete workout |
| Method |
Path |
Description |
| GET |
/workout-logs |
List workout logs |
| POST |
/workout-logs |
Create workout log |
| GET |
/workout-logs/:id |
Get workout log |
| PUT |
/workout-logs/:id |
Update workout log |
| DELETE |
/workout-logs/:id |
Delete workout log |
| Method |
Path |
Description |
| GET |
/custom-trackers |
List trackers |
| POST |
/custom-trackers |
Create tracker |
| GET |
/custom-trackers/:id |
Get tracker |
| PUT |
/custom-trackers/:id |
Update tracker |
| DELETE |
/custom-trackers/:id |
Delete tracker |
| Method |
Path |
Description |
| GET |
/diary |
List entries |
| POST |
/diary |
Create entry |
| GET |
/diary/:id |
Get entry |
| PUT |
/diary/:id |
Update entry |
| DELETE |
/diary/:id |
Delete entry |
| Method |
Path |
Description |
| GET |
/streak |
Get current streak |
| POST |
/streak/update |
Record activity |
| POST |
/streak/reset |
Manual reset |
| PUT |
/streak/settings |
Update streak settings |
| Method |
Path |
Description |
| GET |
/analytics/weight-progress |
Weight trend data |
| GET |
/analytics/exercise-progress/:exercise_id |
Exercise progress |
| GET |
/analytics/personal-records |
All personal records |
| Method |
Path |
Description |
| GET |
/personal-records |
List records |
| POST |
/personal-records |
Create record |
| DELETE |
/personal-records/:exerciseId/:metricName |
Delete record |
| Method |
Path |
Description |
| GET/PUT |
/account-settings |
Account settings |
| GET/PUT |
/widget-settings |
Home widget config |
| GET/PUT |
/preferences |
User preferences |
| CRUD |
/graph-configs |
Analytics graph configs |
| Method |
Path |
Description |
| GET |
/account/export |
Export all user data (JSON) |
| GET |
/account/export/download |
Download data as file |
| POST |
/account/deletion/start |
Request account deletion (30-day grace) |
| POST |
/account/deletion/cancel |
Cancel pending deletion |
| GET |
/account/deletion/status |
Check deletion status |
| Method |
Path |
Description |
| GET |
/sync/delta?since=<timestamp> |
Get records changed since timestamp |
| GET |
/sync/version |
Get current sync version |
| Method |
Path |
Description |
| POST |
/notifications/fcm-token |
Register push token |
| DELETE |
/notifications/fcm-token/:device_id |
Remove push token |
| Variable |
Default |
Description |
PORT |
8080 |
Server port |
ENVIRONMENT |
development |
Environment name |
DATABASE_URL |
— |
PostgreSQL connection string |
JWT_SECRET |
— |
Shared JWT signing secret (same as auth service) |
MEDIA_SERVICE_URL |
— |
Media service base URL for image proxy |
FRONTEND_URL |
http://localhost:3000 |
CORS allowed origin |
go test ./... # All tests
go test -cover ./... # With coverage
go test ./internal/services/... # Specific package
Container image built by GitHub Actions → pushed to ghcr.io/sysopoly/sethabit-api:latest.
Deployed on VPS via Podman Quadlet (managed by sysopoly-infrastructure repo).
MIT
- RESTful: Follow REST conventions for predictable API behavior
- JSON: All requests and responses use JSON format
- Stateless: No server-side session state
- Idempotent: Safe operations can be repeated
- Consistent: Uniform response structure across endpoints
- Versioned: API versioning for backward compatibility
- Database: Optimized indexes for common queries
- Connection Pooling: Efficient database connection management
- Pagination: Limit large result sets
- Caching: Response caching for read-heavy operations (planned)
Built with ❤️ using Go, Gin, and PostgreSQL