Overview
This API enables the Android attendance app to sync student data and attendance records with the web server. The Android app works offline-first — all attendance scans are stored locally and synced in bulk when connected.
Base URL: https://absenc.ikkazuma.com/api
Content-Type: application/json
Architecture
RFID Reader → Android App → Web API (this)
Flow
- Android pulls student data + NFC card UIDs via
GET /api/v1/sync/students - Android caches data locally for offline NFC lookup
- Student taps NFC → Android looks up locally or via
GET /api/v1/sync/nfc-lookup/{card_uid} - Attendance stored locally on Android
- After gate closes or manually triggered, Android bulk uploads via
POST /api/v1/sync/attendance
Authentication
All API endpoints require Laravel Sanctum token authentication. Include the token in the Authorization header.
1. Login to get token
POST /api/login
Content-Type: application/json
{
"email": "[email protected]",
"password": "password"
}
Response 200:
{
"token": "1|abc123...",
"user": {
"id": 1,
"name": "Admin Super",
"email": "[email protected]"
}
}
Response 401:
{
"message": "Invalid credentials"
}
Response 403:
{
"message": "Account is inactive"
}
2. Use token in subsequent requests
GET /api/v1/sync/students
Authorization: Bearer 1|abc123...
Accept: application/json
3. Get current user (verify token)
GET /api/user
Authorization: Bearer 1|abc123...
Response 200:
{
"id": 1,
"name": "Admin Super",
"email": "[email protected]"
}
4. Logout (revoke token)
POST /api/logout
Authorization: Bearer 1|abc123...
Response 200:
{
"message": "Logged out"
}
GET /api/v1/sync/students
Pull all active students with their class assignment and NFC card UID. Use this to populate the Android local cache.
Query Parameters
| Param | Type | Required | Description |
|---|---|---|---|
academic_year |
string | No | Defaults to current year (e.g., 2026/2027) |
Response 200
{
"students": [
{
"id": 1,
"nis": "2026001",
"nisn": "0012345678",
"name": "Ahmad Rizki",
"gender": "L",
"class_id": 5,
"class_name": "X IPA 1",
"nfc_card_uid": "AA:BB:CC:DD",
"photo_url": "http://example.com/storage/students/photo.jpg"
}
]
}
GET /api/v1/sync/nfc-lookup/{card_uid}
Lookup a student by their NFC card UID. Used when the Android local cache misses (new card, cache cleared, etc).
Path Parameters
| Param | Type | Description |
|---|---|---|
card_uid |
string | NFC card UID (e.g., AA:BB:CC:DD) |
Response 200
{
"student": {
"id": 1,
"nis": "2026001",
"name": "Ahmad Rizki",
"class_id": 5
}
}
Response 404
{
"message": "Card not found"
}
POST /api/v1/sync/attendance
Bulk upload attendance records. This is the primary sync endpoint. Works offline-safe with idempotency — safe to retry the same batch.
Request Body
{
"device_id": "android-device-001",
"sync_batch_id": "uuid-v4-from-android",
"records": [
{
"local_record_id": "uuid-v4-per-record",
"student_id": 1,
"date": "2026-08-09",
"time_in": "07:15:00",
"time_out": "13:30:00",
"status": "present"
}
]
}
Fields
| Field | Required | Description |
|---|---|---|
device_id |
Yes | Unique Android device identifier |
sync_batch_id |
Yes | UUID grouping records from same sync operation |
records |
Yes | Array of 1-100 attendance records |
records.*.local_record_id |
Yes | UUID assigned by Android for idempotency |
records.*.student_id |
Yes | Student ID (from students sync) |
records.*.date |
Yes | Attendance date (YYYY-MM-DD) |
records.*.time_in |
No | Check-in time (HH:MM:SS) |
records.*.time_out |
No | Check-out time (HH:MM:SS) |
records.*.status |
Yes | present, late, absent, sick, or permission |
class_id is resolved server-side from the student's active class — do not send it. status may be auto-changed to late if time_in exceeds the configured late threshold.
Response 200
{
"synced": 2,
"skipped": 0,
"failed": 0,
"errors": []
}
Partial failure response
{
"synced": 1,
"skipped": 0,
"failed": 1,
"errors": [
{
"local_record_id": "uuid-of-failed-record",
"error": "No active class for student"
}
]
}
Idempotency
Each record has a local_record_id (UUID). If the same batch is re-uploaded (e.g., after network failure), already-synced records are skipped (counted in skipped). Safe to retry entire batches.
Rate Limits
Max 100 records per request. Split larger batches into multiple requests.
GET /api/v1/sync/attendance-status
Check attendance status for a specific date. Returns both attended and not-yet-attended students.
Query Parameters
| Param | Type | Required | Description |
|---|---|---|---|
date |
date | Yes | Date to check (YYYY-MM-DD) |
class_id |
integer | No | Filter by class. Omit for all classes. |
Response 200
{
"records": [
{
"student_id": 1,
"nis": "2026001",
"name": "Ahmad Rizki",
"class_id": 5,
"status": "present",
"time_in": "07:15:00",
"time_out": "13:30:00"
},
{
"student_id": 2,
"nis": "2026002",
"name": "Siti Nurhaliza",
"class_id": 5,
"status": "not_yet",
"time_in": null,
"time_out": null
}
]
}
Error Reference
| HTTP Code | Meaning | Common Cause |
|---|---|---|
401 |
Unauthorized | Missing or expired token. Re-login to get new token. |
404 |
Not Found | NFC card UID not assigned to any student. |
422 |
Validation Error | Missing or invalid fields. Check errors in response. |
500 |
Server Error | Unexpected error. Retry or contact admin. |