# REST API RIETS v1

Semua payload dan respons memakai JSON UTF-8. Endpoint browser same-origin menggunakan cookie sesi HttpOnly dan header `X-CSRF-Token`. Endpoint aplikasi/gateway menggunakan `Authorization: Bearer ACCESS_TOKEN`.

## Flow browser QR + GPS

### Buka QR area

`GET /track/{random_area_code}`

Menampilkan nama area dan form verifikasi. Kode QR hanya mengidentifikasi area; NIK dan nama tetap divalidasi terhadap master karyawan.

### Verifikasi karyawan

`POST /track/verify`

Form: `_token`, `nik`, `name`, opsional `pin`, `device_uuid`, dan `source=gps`.

Sukses membuat `tracking_sessions` dan mengarahkan browser ke `/tracking/live`.

### Batch lokasi

`POST /api/v1/location/update`

```json
{
  "session_id": "087305ad-05e5-43fa-a47e-839ba209f6b7",
  "source": "gps",
  "locations": [
    {
      "client_event_id": "88773050-69ab-4bed-aa10-01a55a9d4969",
      "source": "gps",
      "latitude": -6.2000123,
      "longitude": 106.8166123,
      "accuracy_m": 14.2,
      "altitude_m": 22.1,
      "speed_mps": 0.8,
      "heading_deg": 83,
      "battery_percent": 82,
      "network_type": "4g",
      "recorded_at": "2026-07-31T09:12:10.120+07:00"
    }
  ]
}
```

`client_event_id` wajib unik. Retry event yang sama diakui tetapi tidak membuat baris ganda. Lokasi lama tidak dapat menimpa `current_locations` yang lebih baru.

Respons:

```json
{
  "ok": true,
  "accepted_ids": ["88773050-69ab-4bed-aa10-01a55a9d4969"],
  "result": {"accepted": 1, "duplicates": 0, "rejected": []}
}
```

### Stop tracking

`POST /api/v1/tracking/stop`

```json
{"session_id":"087305ad-05e5-43fa-a47e-839ba209f6b7","reason":"user_stop"}
```

Stop menutup sesi; semua update berikutnya dengan sesi tersebut ditolak.

## Aplikasi native / gateway

### Login dan refresh

- `POST /api/v1/auth/login`
- `POST /api/v1/auth/refresh`

```json
{"email":"employee@example.com","password":"secret","device_name":"Android RKA"}
```

### Bootstrap perangkat

`GET /api/v1/bootstrap`

Mengembalikan konfigurasi tracking, daftar BLE beacon aktif, dan jadwal kerja.

### BLE tracking lama yang kompatibel

`POST /api/v1/tracking`

```json
{
  "device_uuid":"ANDROID-001",
  "battery":82,
  "network":"wifi",
  "recorded_at":"2026-07-31T09:12:10+07:00",
  "beacons":[
    {"uuid":"fda50693-a4e2-4fb1-afcf-c6eb07647825","major":1,"minor":2,"rssi":-65}
  ]
}
```

Data endpoint ini dicatat eksplisit sebagai `source=ble`.

### Heartbeat perangkat

`POST /api/v1/device/heartbeat`

```json
{"device_uuid":"ANDROID-001","platform":"android","app_version":"1.0.0","battery":82,"network":"wifi"}
```

## Monitoring admin

`GET /stream/locations` membuka SSE maksimum 25 detik dan tersambung ulang otomatis. `GET /stream/locations?poll=1` adalah fallback JSON polling untuk hosting yang membatasi SSE.

## Kode status

- `200`: berhasil atau duplicate sudah diakui.
- `401`: sesi/token tidak aktif.
- `403`: tidak memiliki permission.
- `419`: CSRF/sesi halaman kedaluwarsa.
- `422`: payload atau posisi ditolak.
- `429`: rate limit tercapai.
