11 KiB
Nilai Clock Client - API Reference
Base Configuration
Production API Endpoint
https://myapp.ouji.com/nilai_clock_api/
Authentication
All protected endpoints require JWT Bearer token in the Authorization header:
Authorization: Bearer <jwt-token>
Common Headers
Content-Type: application/json
ngrok-skip-browser-warning: true
Authentication Endpoints
POST /api/auth/login
Authenticate user with username, password, and device UUID.
Request Body:
{
"username": "string",
"password": "string",
"deviceUuid": "string"
}
Success Response (200):
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"fullName": "Worker Full Name"
}
Error Responses:
400: Missing required fields401: Invalid credentials403: Device not authorized
JWT Token Payload:
{
"userId": 123,
"role": "worker",
"iat": 1642234567,
"exp": 1642320967
}
POST /api/auth/refresh
Refresh expired JWT token.
Headers: Authorization: Bearer <current-token>
Success Response (200):
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
Error Responses:
401: Invalid or expired token500: Token refresh failed
Worker Endpoints
POST /api/clock
Record clock in/out event with location verification.
Headers: Authorization: Bearer <token>
Request Body:
{
"userId": 123,
"eventType": "clock_in", // or "clock_out"
"qrCodeValue": "550e8400-e29b-41d4-a716-446655440000",
"latitude": -6.2088,
"longitude": 106.8456,
"notes": "Optional notes"
}
Success Response (200):
{
"message": "Clock in successful",
"timestamp": "2024-01-15T08:00:00.000Z",
"eventType": "clock_in",
"location": {
"latitude": -6.2088,
"longitude": 106.8456
}
}
Error Responses:
400: Invalid event type or missing data401: Unauthorized403: Outside geofence area404: QR code not found or inactive409: Cannot clock in/out (already in same state)
Special Cases:
qrCodeValue: "FORCE_CLOCK_OUT"- Bypasses all validation checks
GET /api/worker/clock-history/:userId
Retrieve worker's clock in/out history.
Headers: Authorization: Bearer <token>
Parameters:
userId(path): Worker's user ID
Success Response (200):
[
{
"id": 1,
"event_type": "clock_in",
"timestamp": "2024-01-15T08:00:00.000Z",
"qrCodeUsedName": "Main Entrance"
},
{
"id": 2,
"event_type": "clock_out",
"timestamp": "2024-01-15T17:00:00.000Z",
"qrCodeUsedName": "Main Entrance"
}
]
Error Responses:
401: Unauthorized404: Worker not found500: Database error
GET /api/workers/:id
Get worker details by ID.
Headers: Authorization: Bearer <token>
Parameters:
id(path): Worker's user ID
Success Response (200):
{
"full_name": "John Doe"
}
Error Responses:
401: Unauthorized404: Worker not found500: Database error
Location & Tracking Endpoints
POST /api/location/update
Send location update to server (background tracking).
Headers: Authorization: Bearer <token>
Request Body:
{
"userId": 123,
"longitude": 106.8456,
"latitude": -6.2088,
"timestamp": "2024-01-15T08:00:00.000Z",
"accuracy": 5.0,
"source": "background" // or "manual", "clock_event"
}
Success Response (200):
{
"message": "Location updated successfully",
"timestamp": "2024-01-15T08:00:00.000Z"
}
Error Responses:
400: Invalid location data401: Unauthorized500: Database error
GET /api/location/status/:userId
Get current location tracking status for user.
Headers: Authorization: Bearer <token>
Parameters:
userId(path): Worker's user ID
Success Response (200):
{
"isTracking": true,
"lastUpdate": "2024-01-15T08:00:00.000Z",
"currentLocation": {
"latitude": -6.2088,
"longitude": 106.8456
},
"withinGeofence": true
}
Security Endpoints
POST /api/security/check - DEPRECATED
DEPRECATED: This endpoint has been commented out in favor of server-side security computation.
Client-side security calculation has been removed per user preference for server-side security validation. Anti-spoofing functionality (fake GPS detection, UUID validation) continues to work through existing server-side mechanisms.
GET /api/security/app-blacklist
Get list of blacklisted applications.
Headers: Authorization: Bearer <token>
Success Response (200):
[
"com.lexa.fakegps",
"com.incorporateapps.fakegps.fre",
"com.blogspot.newapphorizons.fakegps",
"com.theappninjas.gpsjoystick"
]
POST /api/security/alert - NOT IMPLEMENTED
NOT IMPLEMENTED: This endpoint was documented but never implemented in the server.
Security alerts are handled server-side through existing mechanisms:
- Geofence violations are logged automatically during location updates
- Device validation failures are logged during login attempts
- High-risk device detection is handled by server-side security validation
GET /api/security/status/:userId
Get security status for user.
Headers: Authorization: Bearer <token>
Parameters:
userId(path): Worker's user ID
Success Response (200):
{
"latestSecurityCheck": {
"id": 100,
"user_id": 123,
"timestamp": "2024-01-15T08:00:00.000Z",
"risk_level": "low",
"risk_score": 10
},
"recentAlerts": [
{
"id": 456,
"alert_type": "location_anomaly",
"severity": "medium",
"created_at": "2024-01-15T07:30:00.000Z"
}
],
"securityStatus": "low"
}
Device Management Endpoints
POST /api/device/register
Register device for user account.
Headers: Authorization: Bearer <token>
Request Body:
{
"userId": 123,
"deviceUuid": "android-550e8400-e29b-41d4-a716-446655440000"
}
Success Response (200):
{
"message": "Device registered successfully",
"deviceUuid": "android-550e8400-e29b-41d4-a716-446655440000",
"registeredAt": "2024-01-15T08:00:00.000Z"
}
Error Responses:
400: Invalid device UUID401: Unauthorized409: Device already registered to another user500: Database error
POST /api/device/validate
Validate device for user account.
Headers: Authorization: Bearer <token>
Request Body:
{
"userId": 123,
"deviceUuid": "android-550e8400-e29b-41d4-a716-446655440000"
}
Success Response (200):
{
"valid": true,
"message": "Device validated successfully",
"deviceInfo": {
"registeredAt": "2024-01-15T08:00:00.000Z",
"lastSeen": "2024-01-15T08:00:00.000Z"
}
}
Error Responses:
400: Invalid device UUID401: Unauthorized403: Device not authorized for this user404: Device not found500: Database error
Note: Managers bypass device validation and always receive valid: true.
Manager Endpoints (Web Only)
GET /api/managers/workers
Get list of all workers with filtering and pagination.
Headers: Authorization: Bearer <token>
Query Parameters:
search(optional): Search term for worker namespage(optional): Page number (default: 1)limit(optional): Items per page (default: 20)tags(optional): Comma-separated tag IDs
Success Response (200):
{
"workers": [
{
"id": 123,
"username": "worker123",
"full_name": "John Doe",
"created_at": "2024-01-01T00:00:00.000Z",
"tags": "Production, Day Shift"
}
],
"totalCount": 50,
"currentPage": 1,
"totalPages": 3
}
GET /api/managers/qr-codes
Get list of all QR codes.
Headers: Authorization: Bearer <token>
Success Response (200):
[
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Main Entrance",
"is_active": true,
"created_at": "2024-01-01T00:00:00.000Z"
}
]
POST /api/managers/qr-codes
Create new QR code.
Headers: Authorization: Bearer <token>
Request Body:
{
"name": "Side Entrance"
}
Success Response (201):
{
"id": "550e8400-e29b-41d4-a716-446655440001",
"name": "Side Entrance",
"is_active": true
}
Error Response Format
All endpoints return consistent error responses:
{
"message": "Descriptive error message",
"code": "ERROR_CODE",
"details": {
"field": "Additional error details"
}
}
Common Error Codes
INVALID_CREDENTIALS: Login failedTOKEN_EXPIRED: JWT token has expiredDEVICE_NOT_AUTHORIZED: Device not registered for userOUTSIDE_GEOFENCE: Location outside allowed areaQR_CODE_INACTIVE: QR code is disabledDUPLICATE_EVENT: Cannot perform same clock action twiceSECURITY_VIOLATION: Security check failedVALIDATION_ERROR: Request data validation failed
HTTP Status Codes
200: Success201: Created successfully400: Bad Request (validation errors)401: Unauthorized (invalid/missing token)403: Forbidden (insufficient permissions)404: Not Found409: Conflict (duplicate data)500: Internal Server Error
Rate Limiting
API endpoints are rate-limited to prevent abuse:
- Authentication endpoints: 5 requests per minute per IP
- Clock endpoints: 10 requests per minute per user
- Location updates: 60 requests per minute per user
- General endpoints: 100 requests per minute per user
Rate limit headers are included in responses:
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 95
X-RateLimit-Reset: 1642234567
Webhook Events (Future)
The API supports webhook notifications for real-time events:
Clock Events
{
"event": "worker.clock_in",
"data": {
"userId": 123,
"timestamp": "2024-01-15T08:00:00.000Z",
"location": {
"latitude": -6.2088,
"longitude": 106.8456
}
}
}
Security Alerts
{
"event": "security.violation",
"data": {
"userId": 123,
"alertType": "gps_spoofing_detected",
"severity": "high",
"timestamp": "2024-01-15T08:00:00.000Z"
}
}
SDK Examples
JavaScript/TypeScript
class NilaiClockAPI {
constructor(baseURL, token) {
this.baseURL = baseURL
this.token = token
}
async clockIn(userId, qrCodeValue, latitude, longitude) {
const response = await fetch(`${this.baseURL}/api/clock`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${this.token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
userId,
eventType: 'clock_in',
qrCodeValue,
latitude,
longitude
})
})
if (!response.ok) {
throw new Error(`Clock in failed: ${response.status}`)
}
return response.json()
}
}
cURL Examples
# Login
curl -X POST https://myapp.ouji.com/nilai_clock_api/api/auth/login \
-H "Content-Type: application/json" \
-d '{"username":"worker123","password":"password","deviceUuid":"device-uuid"}'
# Clock In
curl -X POST https://myapp.ouji.com/nilai_clock_api/api/clock \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"userId":123,"eventType":"clock_in","qrCodeValue":"qr-uuid","latitude":-6.2088,"longitude":106.8456}'
# Get History
curl -X GET https://myapp.ouji.com/nilai_clock_api/api/worker/clock-history/123 \
-H "Authorization: Bearer <token>"