Production-ready REST API for Indonesian National Holidays & Joint Leave Days
Based on official SKB 3 Menteri regulations | JWT Authentication | Rate Limiting | Audit Logging
Quick Start โข API Docs โข Use Cases โข SDK โข Self-Hosting
Public API Endpoint: https://api.holidayapi.id/v1 (Coming Soon - Currently Self-Host)
# Try it now with curl
curl -X GET "https://api.holidayapi.id/v1/holidays/year/2024" \
-H "Accept: application/json"- โ JWT Authentication with access & refresh tokens
- โ Role-Based Access Control (RBAC) - Super Admin & Admin roles
- โ User Management - Registration, login, profile management
- โ Password Security - Bcrypt hashing with password policy
- โ Comprehensive Audit Logging - Track all user actions
- โ Security Headers - XSS, CSRF, Content Security Policy protection
- โ Input Sanitization - Protection from injection attacks
- โ Enhanced Rate Limiting - Per-user rate limiting (60 RPM public, authenticated users higher)
- โ REST API with versioning (v1)
- โ CRUD operations for admin (JWT protected)
- โ Filter by type - National holidays, joint leave days, or both
- โ Filter by period - Year, month, or specific day queries
- โ Swagger documentation with interactive testing
- โ SQLite database (pure Go, no CGO required)
- โ Comprehensive logging with structured format
- โ Input validation with custom validators
- โ Docker support with production-ready configuration
- โ Unit & Integration tests with mocking
- Quick Start
- Installation
- API Documentation
- Use Cases
- Who is This For
- Self-Hosting Guide
- SDK & Clients
- Integrations
- Configuration
- Docker Deployment
- Go 1.23 or higher
- Git
- Docker (optional)
# Clone the repository
git clone https://github.com/ilramdhan/holidayapi.git
cd holidayapi
# Start with Docker Compose
docker-compose up --build
# API is now running at http://localhost:8080# Clone the repository
git clone https://github.com/ilramdhan/holidayapi.git
cd holidayapi
# Install dependencies
go mod tidy
# Run the application
go run cmd/server/main.gogo get github.com/ilramdhan/holidayapi# Health check
curl http://localhost:8080/health
# Get API documentation
curl http://localhost:8080/swagger/index.html- Swagger UI: http://localhost:8080/swagger/index.html
- OpenAPI Spec: http://localhost:8080/swagger/doc.json
http://localhost:8080/api/v1
| Endpoint | Description | Example |
|---|---|---|
GET /api/v1/holidays |
Get all holidays with filters | Try it |
GET /api/v1/holidays/year/{year} |
Get holidays by year | /holidays/year/2024 |
GET /api/v1/holidays/month/{year}/{month} |
Get holidays by month | /holidays/month/2024/1 |
GET /api/v1/holidays/today |
Get today's holiday | /holidays/today |
GET /api/v1/holidays/this-year |
Get current year holidays | /holidays/this-year |
GET /api/v1/holidays/upcoming |
Get upcoming holidays | /holidays/upcoming |
GET /health |
Health check | /health |
| Endpoint | Description | Auth Required |
|---|---|---|
POST /api/v1/auth/login |
User login (get JWT tokens) | No |
POST /api/v1/auth/refresh |
Refresh access token | Refresh Token |
GET /api/v1/auth/profile |
Get user profile | JWT |
POST /api/v1/auth/change-password |
Change password | JWT |
| Endpoint | Description | Role |
|---|---|---|
POST /api/v1/admin/holidays |
Create new holiday | Admin/Super Admin |
PUT /api/v1/admin/holidays/{id} |
Update holiday | Admin/Super Admin |
DELETE /api/v1/admin/holidays/{id} |
Delete holiday | Admin/Super Admin |
GET /api/v1/admin/audit-logs |
View all audit logs | Super Admin |
Automatically calculate working days, leave balances, and payroll based on official Indonesian holidays.
# Example: Calculate working days in a month
import requests
response = requests.get("https://api.holidayapi.id/v1/holidays/month/2024/1")
holidays = response.json()["data"]
working_days = total_days - len(holidays)Display Indonesian holidays in calendar applications and scheduling tools.
Plan promotions and sales around holiday periods. Identify peak shopping seasons.
Optimize delivery schedules by accounting for non-working days and joint leave periods.
Calculate settlement dates, interest calculations, and business days excluding holidays.
Integrate official holiday data into public service portals and citizen applications.
Schedule exams, breaks, and academic calendars aligned with national holidays.
| Audience | Use Case |
|---|---|
| Developers | Build apps with accurate Indonesian holiday data |
| HR Teams | Automate leave and payroll calculations |
| Startups | Free, reliable holiday API for their products |
| Enterprise | Self-hosted solution with full data control |
| Government | Public service integration |
| Students | Learn Go, REST API, JWT authentication |
- Docker & Docker Compose, OR
- Go 1.23+ with SQLite support
# Clone repository
git clone https://github.com/ilramdhan/holidayapi.git
cd holidayapi
# Create environment file
cp .env.example .env
# Edit .env with your settings
nano .env
# Start production stack
docker-compose -f docker-compose.yml up -d# Server Configuration
SERVER_HOST=0.0.0.0
SERVER_PORT=8080
# Database
DATABASE_PATH=./data/holidays.db
MIGRATIONS_PATH=./migrations
# Security
JWT_SECRET_KEY=your-super-secret-key-min-32-chars
ADMIN_API_KEY=your-admin-api-key
# Rate Limiting
RATE_LIMIT_RPM=60
RATE_LIMIT_BURST=10
# JWT Settings
JWT_ACCESS_TOKEN_TTL=15m
JWT_REFRESH_TOKEN_TTL=168hNote: Railway telah menghentikan dukungan untuk template deployment gratis. Silakan gunakan opsi lain di bawah ini atau deploy secara manual.
# Install flyctl
curl -L https://fly.io/install.sh | sh
# Launch app
fly launch
# Deploy
fly deploypackage main
import (
"context"
"fmt"
"log"
"github.com/ilramdhan/holidayapi/pkg/client"
)
func main() {
// Create client
c := client.New("https://api.holidayapi.id/v1")
// Get holidays for 2024
holidays, err := c.GetHolidaysByYear(context.Background(), 2024)
if err != nil {
log.Fatal(err)
}
for _, h := range holidays {
fmt.Printf("%s: %s\n", h.Date, h.Name)
}
}import { HolidayClient } from '@holidayapi/indonesia';
const client = new HolidayClient('https://api.holidayapi.id/v1');
// Get holidays
const holidays = await client.getHolidaysByYear(2024);
console.log(holidays);from holidayapi import HolidayClient
client = HolidayClient('https://api.holidayapi.id/v1')
# Get holidays for 2024
holidays = client.get_holidays_by_year(2024)
for holiday in holidays:
print(f"{holiday['date']}: {holiday['name']}")๐ฅ Download Postman Collection
Use our n8n node to automate holiday-aware workflows.
Coming soon - Connect Holiday API with 5000+ apps.
Sync Indonesian holidays to your Google Calendar.
Get holiday notifications in your Slack workspace.
curl -X GET "http://localhost:8080/api/v1/holidays/year/2024" \
-H "Accept: application/json"Response:
{
"success": true,
"data": [
{
"id": 1,
"date": "2024-01-01",
"name": "Tahun Baru 2024",
"type": "national",
"description": "Hari Tahun Baru Masehi"
},
{
"id": 2,
"date": "2024-02-08",
"name": "Isra Mikraj Nabi Muhammad SAW",
"type": "national",
"description": "Kenaikan Nabi Muhammad SAW"
}
],
"meta": {
"total": 2,
"year": 2024
}
}curl -X GET "http://localhost:8080/api/v1/holidays/today" \
-H "Accept: application/json"curl -X GET "http://localhost:8080/api/v1/holidays/upcoming?limit=5" \
-H "Accept: application/json"# Only national holidays
curl -X GET "http://localhost:8080/api/v1/holidays/year/2024?type=national"
# Only collective leave days
curl -X GET "http://localhost:8080/api/v1/holidays/year/2024?type=collective_leave"# 1. Login
curl -X POST "http://localhost:8080/api/v1/auth/login" \
-H "Content-Type: application/json" \
-d '{
"username": "admin",
"password": "Admin123!"
}'
# 2. Use token for admin endpoints
curl -X POST "http://localhost:8080/api/v1/admin/holidays" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-d '{
"date": "2024-12-25",
"name": "Hari Raya Natal",
"type": "national",
"description": "Perayaan kelahiran Yesus Kristus"
}'| Variable | Default | Description |
|---|---|---|
SERVER_HOST |
localhost |
Server host |
SERVER_PORT |
8080 |
Server port |
DATABASE_PATH |
./data/holidays.db |
SQLite database path |
MIGRATIONS_PATH |
./migrations |
Database migrations path |
RATE_LIMIT_RPM |
60 |
Rate limit requests per minute |
RATE_LIMIT_BURST |
10 |
Rate limit burst size |
JWT_SECRET_KEY |
your-secret-key |
JWT signing secret key |
JWT_ACCESS_TOKEN_TTL |
15m |
Access token expiration time |
JWT_REFRESH_TOKEN_TTL |
168h |
Refresh token expiration time (7 days) |
ADMIN_API_KEY |
admin-secret-key |
Legacy admin API key |
docker build -t holidayapi:latest .docker run -d \
--name holidayapi \
-p 8080:8080 \
-e JWT_SECRET_KEY=your-secret-key \
-v $(pwd)/data:/root/data \
holidayapi:latestversion: '3.8'
services:
holidayapi:
build: .
ports:
- "8080:8080"
environment:
- JWT_SECRET_KEY=${JWT_SECRET_KEY}
- ADMIN_API_KEY=${ADMIN_API_KEY}
volumes:
- ./data:/root/data
restart: unless-stopped# Run all tests
go test ./...
# Run with coverage
go test -cover ./...
# Run specific package tests
go test ./internal/services/...We welcome contributions! Please see our Contributing Guide for details.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add 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.
- Holiday data based on official SKB 3 Menteri (Ministerial Decree)
- Built with Gin Web Framework
- Database powered by modernc/sqlite
- ๐ง Email: me@ilramdhan.dev
- ๐ Issues: GitHub Issues
- ๐ฌ Discussions: GitHub Discussions
Made with โค๏ธ in Indonesia ๐ฎ๐ฉ