Add: Complete API endpoints documentation - List all endpoints with request/response examples - Include authentication requirements - Document error responses - Add query parameters and access control info
This commit is contained in:
917
API_ENDPOINTS.md
Normal file
917
API_ENDPOINTS.md
Normal file
@@ -0,0 +1,917 @@
|
||||
# API Endpoints Documentation
|
||||
|
||||
Dokumentasi lengkap semua endpoint yang tersedia di API Btekno.
|
||||
|
||||
**Base URL**: `https://api.btekno.cloud`
|
||||
|
||||
---
|
||||
|
||||
## 📋 Daftar Isi
|
||||
|
||||
- [Public Endpoints](#public-endpoints)
|
||||
- [Authentication](#authentication)
|
||||
- [Retribusi - Ingest](#retribusi---ingest)
|
||||
- [Retribusi - Frontend CRUD](#retribusi---frontend-crud)
|
||||
- [Retribusi - Summary](#retribusi---summary)
|
||||
- [Retribusi - Dashboard](#retribusi---dashboard)
|
||||
- [Retribusi - Realtime](#retribusi---realtime)
|
||||
|
||||
---
|
||||
|
||||
## Public Endpoints
|
||||
|
||||
### Health Check
|
||||
**GET** `/health`
|
||||
|
||||
Health check endpoint untuk monitoring.
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"status": "ok",
|
||||
"time": 1703123456
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Documentation
|
||||
**GET** `/`
|
||||
|
||||
Redirect ke `/docs` (Swagger UI).
|
||||
|
||||
**GET** `/docs`
|
||||
|
||||
Swagger UI documentation (public access).
|
||||
|
||||
**GET** `/docs/openapi.json`
|
||||
|
||||
OpenAPI 3.0 specification JSON.
|
||||
|
||||
---
|
||||
|
||||
## Authentication
|
||||
|
||||
### Login
|
||||
**POST** `/auth/v1/login`
|
||||
|
||||
Login untuk mendapatkan JWT token.
|
||||
|
||||
**Request Body:**
|
||||
```json
|
||||
{
|
||||
"username": "admin",
|
||||
"password": "password123"
|
||||
}
|
||||
```
|
||||
|
||||
**Response (200):**
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"data": {
|
||||
"token": "eyJ0eXAiOiJKV1QiLCJhbGc...",
|
||||
"expires_in": 3600,
|
||||
"user": {
|
||||
"id": 1,
|
||||
"username": "admin",
|
||||
"role": "admin"
|
||||
}
|
||||
},
|
||||
"timestamp": 1703123456
|
||||
}
|
||||
```
|
||||
|
||||
**Error Responses:**
|
||||
- `401` - Invalid credentials
|
||||
- `403` - User inactive
|
||||
- `422` - Validation error
|
||||
|
||||
**Authentication:** None (public endpoint)
|
||||
|
||||
---
|
||||
|
||||
## Retribusi - Ingest
|
||||
|
||||
### Ingest Event
|
||||
**POST** `/retribusi/v1/ingest`
|
||||
|
||||
Endpoint untuk mesin/IoT mengirim event data.
|
||||
|
||||
**Headers:**
|
||||
```
|
||||
X-API-KEY: your-api-key-here
|
||||
Content-Type: application/json
|
||||
```
|
||||
|
||||
**Request Body:**
|
||||
```json
|
||||
{
|
||||
"timestamp": 1703123456,
|
||||
"location_code": "kerkof_01",
|
||||
"gate_code": "gate01",
|
||||
"category": "motor"
|
||||
}
|
||||
```
|
||||
|
||||
**Response (200):**
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"data": {
|
||||
"stored": true
|
||||
},
|
||||
"timestamp": 1703123456
|
||||
}
|
||||
```
|
||||
|
||||
**Error Responses:**
|
||||
- `401` - Invalid API key
|
||||
- `404` - Location/Gate/Tariff not found
|
||||
- `422` - Validation error
|
||||
|
||||
**Authentication:** `X-API-KEY` header
|
||||
|
||||
**Category Values:**
|
||||
- `person_walk`
|
||||
- `motor`
|
||||
- `car`
|
||||
|
||||
---
|
||||
|
||||
## Retribusi - Frontend CRUD
|
||||
|
||||
Semua endpoint di bawah ini memerlukan **JWT Authentication**.
|
||||
|
||||
**Headers:**
|
||||
```
|
||||
Authorization: Bearer <jwt-token>
|
||||
Content-Type: application/json
|
||||
```
|
||||
|
||||
### Locations
|
||||
|
||||
#### List Locations
|
||||
**GET** `/retribusi/v1/frontend/locations`
|
||||
|
||||
Get list of locations dengan pagination.
|
||||
|
||||
**Query Parameters:**
|
||||
- `page` (optional, default: 1)
|
||||
- `limit` (optional, default: 20, max: 100)
|
||||
- `location_code` (optional, filter)
|
||||
|
||||
**Response (200):**
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"data": [
|
||||
{
|
||||
"code": "kerkof_01",
|
||||
"name": "Kerkof 01",
|
||||
"type": "kerkof",
|
||||
"is_active": 1
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"page": 1,
|
||||
"limit": 20,
|
||||
"total": 10,
|
||||
"pages": 1
|
||||
},
|
||||
"timestamp": 1703123456
|
||||
}
|
||||
```
|
||||
|
||||
**Access:** Viewer, Operator, Admin
|
||||
|
||||
---
|
||||
|
||||
#### Create Location
|
||||
**POST** `/retribusi/v1/frontend/locations`
|
||||
|
||||
Create new location.
|
||||
|
||||
**Request Body:**
|
||||
```json
|
||||
{
|
||||
"code": "kerkof_02",
|
||||
"name": "Kerkof 02",
|
||||
"type": "kerkof",
|
||||
"is_active": 1
|
||||
}
|
||||
```
|
||||
|
||||
**Response (201):**
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"data": {
|
||||
"code": "kerkof_02",
|
||||
"name": "Kerkof 02",
|
||||
"type": "kerkof",
|
||||
"is_active": 1
|
||||
},
|
||||
"timestamp": 1703123456
|
||||
}
|
||||
```
|
||||
|
||||
**Access:** Operator, Admin
|
||||
|
||||
---
|
||||
|
||||
#### Update Location
|
||||
**PUT** `/retribusi/v1/frontend/locations/{code}`
|
||||
|
||||
Update location (code tidak bisa diubah).
|
||||
|
||||
**Request Body:**
|
||||
```json
|
||||
{
|
||||
"name": "Kerkof 02 Updated",
|
||||
"type": "kerkof",
|
||||
"is_active": 1
|
||||
}
|
||||
```
|
||||
|
||||
**Response (200):**
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"data": {
|
||||
"code": "kerkof_02",
|
||||
"name": "Kerkof 02 Updated",
|
||||
"type": "kerkof",
|
||||
"is_active": 1
|
||||
},
|
||||
"timestamp": 1703123456
|
||||
}
|
||||
```
|
||||
|
||||
**Access:** Operator, Admin
|
||||
|
||||
---
|
||||
|
||||
#### Delete Location
|
||||
**DELETE** `/retribusi/v1/frontend/locations/{code}`
|
||||
|
||||
Soft delete location (set `is_active = 0`).
|
||||
|
||||
**Response (200):**
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"data": {
|
||||
"deleted": true
|
||||
},
|
||||
"timestamp": 1703123456
|
||||
}
|
||||
```
|
||||
|
||||
**Access:** Admin only
|
||||
|
||||
---
|
||||
|
||||
### Gates
|
||||
|
||||
#### List Gates
|
||||
**GET** `/retribusi/v1/frontend/gates`
|
||||
|
||||
Get list of gates dengan pagination.
|
||||
|
||||
**Query Parameters:**
|
||||
- `page` (optional, default: 1)
|
||||
- `limit` (optional, default: 20, max: 100)
|
||||
- `location_code` (optional, filter)
|
||||
|
||||
**Response (200):**
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"data": [
|
||||
{
|
||||
"location_code": "kerkof_01",
|
||||
"gate_code": "gate01",
|
||||
"name": "Gate 01",
|
||||
"direction": "in",
|
||||
"is_active": 1
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"page": 1,
|
||||
"limit": 20,
|
||||
"total": 5,
|
||||
"pages": 1
|
||||
},
|
||||
"timestamp": 1703123456
|
||||
}
|
||||
```
|
||||
|
||||
**Access:** Viewer, Operator, Admin
|
||||
|
||||
---
|
||||
|
||||
#### Create Gate
|
||||
**POST** `/retribusi/v1/frontend/gates`
|
||||
|
||||
Create new gate.
|
||||
|
||||
**Request Body:**
|
||||
```json
|
||||
{
|
||||
"location_code": "kerkof_01",
|
||||
"gate_code": "gate02",
|
||||
"name": "Gate 02",
|
||||
"direction": "out",
|
||||
"is_active": 1
|
||||
}
|
||||
```
|
||||
|
||||
**Response (201):**
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"data": {
|
||||
"location_code": "kerkof_01",
|
||||
"gate_code": "gate02",
|
||||
"name": "Gate 02",
|
||||
"direction": "out",
|
||||
"is_active": 1
|
||||
},
|
||||
"timestamp": 1703123456
|
||||
}
|
||||
```
|
||||
|
||||
**Access:** Operator, Admin
|
||||
|
||||
---
|
||||
|
||||
#### Update Gate
|
||||
**PUT** `/retribusi/v1/frontend/gates/{location_code}/{gate_code}`
|
||||
|
||||
Update gate (location_code dan gate_code tidak bisa diubah).
|
||||
|
||||
**Request Body:**
|
||||
```json
|
||||
{
|
||||
"name": "Gate 02 Updated",
|
||||
"direction": "out",
|
||||
"is_active": 1
|
||||
}
|
||||
```
|
||||
|
||||
**Response (200):**
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"data": {
|
||||
"location_code": "kerkof_01",
|
||||
"gate_code": "gate02",
|
||||
"name": "Gate 02 Updated",
|
||||
"direction": "out",
|
||||
"is_active": 1
|
||||
},
|
||||
"timestamp": 1703123456
|
||||
}
|
||||
```
|
||||
|
||||
**Access:** Operator, Admin
|
||||
|
||||
---
|
||||
|
||||
#### Delete Gate
|
||||
**DELETE** `/retribusi/v1/frontend/gates/{location_code}/{gate_code}`
|
||||
|
||||
Soft delete gate (set `is_active = 0`).
|
||||
|
||||
**Response (200):**
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"data": {
|
||||
"deleted": true
|
||||
},
|
||||
"timestamp": 1703123456
|
||||
}
|
||||
```
|
||||
|
||||
**Access:** Admin only
|
||||
|
||||
---
|
||||
|
||||
### Tariffs
|
||||
|
||||
#### Create Tariff
|
||||
**POST** `/retribusi/v1/frontend/tariffs`
|
||||
|
||||
Create new tariff.
|
||||
|
||||
**Request Body:**
|
||||
```json
|
||||
{
|
||||
"location_code": "kerkof_01",
|
||||
"gate_code": "gate01",
|
||||
"category": "motor",
|
||||
"price": 5000
|
||||
}
|
||||
```
|
||||
|
||||
**Response (201):**
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"data": {
|
||||
"location_code": "kerkof_01",
|
||||
"gate_code": "gate01",
|
||||
"category": "motor",
|
||||
"price": 5000
|
||||
},
|
||||
"timestamp": 1703123456
|
||||
}
|
||||
```
|
||||
|
||||
**Access:** Operator, Admin
|
||||
|
||||
---
|
||||
|
||||
#### Update Tariff
|
||||
**PUT** `/retribusi/v1/frontend/tariffs/{location_code}/{gate_code}/{category}`
|
||||
|
||||
Update tariff price (location_code, gate_code, category tidak bisa diubah).
|
||||
|
||||
**Request Body:**
|
||||
```json
|
||||
{
|
||||
"price": 6000
|
||||
}
|
||||
```
|
||||
|
||||
**Response (200):**
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"data": {
|
||||
"location_code": "kerkof_01",
|
||||
"gate_code": "gate01",
|
||||
"category": "motor",
|
||||
"price": 6000
|
||||
},
|
||||
"timestamp": 1703123456
|
||||
}
|
||||
```
|
||||
|
||||
**Access:** Operator, Admin
|
||||
|
||||
---
|
||||
|
||||
#### Delete Tariff
|
||||
**DELETE** `/retribusi/v1/frontend/tariffs/{location_code}/{gate_code}/{category}`
|
||||
|
||||
Hard delete tariff (permanent delete).
|
||||
|
||||
**Response (200):**
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"data": {
|
||||
"deleted": true
|
||||
},
|
||||
"timestamp": 1703123456
|
||||
}
|
||||
```
|
||||
|
||||
**Access:** Admin only
|
||||
|
||||
---
|
||||
|
||||
### Streams
|
||||
|
||||
#### List Streams
|
||||
**GET** `/retribusi/v1/frontend/streams`
|
||||
|
||||
Get list of streams (alias untuk gates).
|
||||
|
||||
**Query Parameters:**
|
||||
- `page` (optional, default: 1)
|
||||
- `limit` (optional, default: 20, max: 100)
|
||||
- `location_code` (optional, filter)
|
||||
|
||||
**Response (200):**
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"data": [
|
||||
{
|
||||
"location_code": "kerkof_01",
|
||||
"gate_code": "gate01",
|
||||
"name": "Gate 01",
|
||||
"direction": "in",
|
||||
"is_active": 1
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"page": 1,
|
||||
"limit": 20,
|
||||
"total": 5,
|
||||
"pages": 1
|
||||
},
|
||||
"timestamp": 1703123456
|
||||
}
|
||||
```
|
||||
|
||||
**Access:** Viewer, Operator, Admin
|
||||
|
||||
---
|
||||
|
||||
## Retribusi - Summary
|
||||
|
||||
Semua endpoint di bawah ini memerlukan **JWT Authentication**.
|
||||
|
||||
### Daily Summary
|
||||
|
||||
#### Trigger Daily Aggregation
|
||||
**POST** `/retribusi/v1/admin/summary/daily`
|
||||
|
||||
Trigger manual aggregation untuk daily summary.
|
||||
|
||||
**Request Body:**
|
||||
```json
|
||||
{
|
||||
"date": "2025-12-16"
|
||||
}
|
||||
```
|
||||
|
||||
**Response (200):**
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"data": {
|
||||
"rows_processed": 150,
|
||||
"date": "2025-12-16"
|
||||
},
|
||||
"timestamp": 1703123456
|
||||
}
|
||||
```
|
||||
|
||||
**Access:** Admin only
|
||||
|
||||
---
|
||||
|
||||
#### Get Daily Summary
|
||||
**GET** `/retribusi/v1/summary/daily`
|
||||
|
||||
Get daily summary data.
|
||||
|
||||
**Query Parameters:**
|
||||
- `date` (required, format: YYYY-MM-DD)
|
||||
- `location_code` (optional, filter)
|
||||
- `gate_code` (optional, filter)
|
||||
|
||||
**Response (200):**
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"data": [
|
||||
{
|
||||
"summary_date": "2025-12-16",
|
||||
"location_code": "kerkof_01",
|
||||
"gate_code": "gate01",
|
||||
"category": "motor",
|
||||
"total_count": 100,
|
||||
"total_amount": 500000
|
||||
}
|
||||
],
|
||||
"timestamp": 1703123456
|
||||
}
|
||||
```
|
||||
|
||||
**Access:** Viewer, Operator, Admin
|
||||
|
||||
---
|
||||
|
||||
### Hourly Summary
|
||||
|
||||
#### Get Hourly Summary
|
||||
**GET** `/retribusi/v1/summary/hourly`
|
||||
|
||||
Get hourly summary data untuk chart (24 jam).
|
||||
|
||||
**Query Parameters:**
|
||||
- `date` (required, format: YYYY-MM-DD)
|
||||
- `location_code` (optional, filter)
|
||||
- `gate_code` (optional, filter)
|
||||
|
||||
**Response (200):**
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"data": {
|
||||
"labels": ["00", "01", "02", ..., "23"],
|
||||
"series": {
|
||||
"total_count": [10, 15, 20, ..., 5],
|
||||
"total_amount": [50000, 75000, 100000, ..., 25000]
|
||||
}
|
||||
},
|
||||
"timestamp": 1703123456
|
||||
}
|
||||
```
|
||||
|
||||
**Access:** Viewer, Operator, Admin
|
||||
|
||||
---
|
||||
|
||||
## Retribusi - Dashboard
|
||||
|
||||
Semua endpoint di bawah ini memerlukan **JWT Authentication**.
|
||||
|
||||
### Daily Chart
|
||||
**GET** `/retribusi/v1/dashboard/daily`
|
||||
|
||||
Get daily chart data (line chart).
|
||||
|
||||
**Query Parameters:**
|
||||
- `start_date` (required, format: YYYY-MM-DD)
|
||||
- `end_date` (required, format: YYYY-MM-DD)
|
||||
- `location_code` (optional, filter)
|
||||
- `gate_code` (optional, filter)
|
||||
|
||||
**Response (200):**
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"data": {
|
||||
"labels": ["2025-12-01", "2025-12-02", "2025-12-03"],
|
||||
"series": {
|
||||
"total_count": [100, 150, 200],
|
||||
"total_amount": [500000, 750000, 1000000]
|
||||
}
|
||||
},
|
||||
"timestamp": 1703123456
|
||||
}
|
||||
```
|
||||
|
||||
**Access:** Viewer, Operator, Admin
|
||||
|
||||
---
|
||||
|
||||
### By Category Chart
|
||||
**GET** `/retribusi/v1/dashboard/by-category`
|
||||
|
||||
Get chart data grouped by category (bar/donut chart).
|
||||
|
||||
**Query Parameters:**
|
||||
- `date` (required, format: YYYY-MM-DD)
|
||||
- `location_code` (optional, filter)
|
||||
- `gate_code` (optional, filter)
|
||||
|
||||
**Response (200):**
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"data": {
|
||||
"labels": ["person_walk", "motor", "car"],
|
||||
"series": {
|
||||
"total_count": [50, 100, 30],
|
||||
"total_amount": [100000, 500000, 300000]
|
||||
}
|
||||
},
|
||||
"timestamp": 1703123456
|
||||
}
|
||||
```
|
||||
|
||||
**Access:** Viewer, Operator, Admin
|
||||
|
||||
---
|
||||
|
||||
### Summary Statistics
|
||||
**GET** `/retribusi/v1/dashboard/summary`
|
||||
|
||||
Get summary statistics (stat cards).
|
||||
|
||||
**Query Parameters:**
|
||||
- `date` (required, format: YYYY-MM-DD)
|
||||
- `location_code` (optional, filter)
|
||||
|
||||
**Response (200):**
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"data": {
|
||||
"total_count_today": 180,
|
||||
"total_amount_today": 900000,
|
||||
"by_gate": [
|
||||
{
|
||||
"gate_code": "gate01",
|
||||
"total_count": 100,
|
||||
"total_amount": 500000
|
||||
}
|
||||
],
|
||||
"by_category": [
|
||||
{
|
||||
"category": "motor",
|
||||
"total_count": 100,
|
||||
"total_amount": 500000
|
||||
}
|
||||
]
|
||||
},
|
||||
"timestamp": 1703123456
|
||||
}
|
||||
```
|
||||
|
||||
**Access:** Viewer, Operator, Admin
|
||||
|
||||
---
|
||||
|
||||
## Retribusi - Realtime
|
||||
|
||||
Semua endpoint di bawah ini memerlukan **JWT Authentication**.
|
||||
|
||||
### SSE Stream
|
||||
**GET** `/retribusi/v1/realtime/stream`
|
||||
|
||||
Server-Sent Events (SSE) stream untuk real-time updates.
|
||||
|
||||
**Headers:**
|
||||
```
|
||||
Authorization: Bearer <jwt-token>
|
||||
Accept: text/event-stream
|
||||
```
|
||||
|
||||
**Query Parameters:**
|
||||
- `last_id` (optional, untuk resume dari event tertentu)
|
||||
- `location_code` (optional, filter)
|
||||
|
||||
**Response (200):**
|
||||
```
|
||||
Content-Type: text/event-stream
|
||||
Cache-Control: no-cache
|
||||
Connection: keep-alive
|
||||
|
||||
id: 12345
|
||||
event: ingest
|
||||
data: {"location_code":"kerkof_01","gate_code":"gate01","category":"motor","event_time":1703123456}
|
||||
|
||||
id: 12346
|
||||
event: ingest
|
||||
data: {"location_code":"kerkof_01","gate_code":"gate01","category":"car","event_time":1703123457}
|
||||
|
||||
...
|
||||
```
|
||||
|
||||
**Access:** Viewer, Operator, Admin
|
||||
|
||||
**Note:** Connection akan tetap terbuka dan mengirim event setiap ada ingest baru. Ping dikirim setiap 10 detik jika tidak ada data.
|
||||
|
||||
---
|
||||
|
||||
### Snapshot
|
||||
**GET** `/retribusi/v1/realtime/snapshot`
|
||||
|
||||
Get snapshot data untuk real-time dashboard cards.
|
||||
|
||||
**Query Parameters:**
|
||||
- `date` (optional, default: today, format: YYYY-MM-DD)
|
||||
- `location_code` (optional, filter)
|
||||
|
||||
**Response (200):**
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"data": {
|
||||
"total_count_today": 180,
|
||||
"total_amount_today": 900000,
|
||||
"by_gate": [
|
||||
{
|
||||
"gate_code": "gate01",
|
||||
"total_count": 100,
|
||||
"total_amount": 500000
|
||||
}
|
||||
],
|
||||
"by_category": [
|
||||
{
|
||||
"category": "motor",
|
||||
"total_count": 100,
|
||||
"total_amount": 500000
|
||||
}
|
||||
]
|
||||
},
|
||||
"timestamp": 1703123456
|
||||
}
|
||||
```
|
||||
|
||||
**Access:** Viewer, Operator, Admin
|
||||
|
||||
---
|
||||
|
||||
## Error Responses
|
||||
|
||||
Semua endpoint mengembalikan error dalam format konsisten:
|
||||
|
||||
### 401 Unauthorized
|
||||
```json
|
||||
{
|
||||
"error": "unauthorized",
|
||||
"message": "Invalid or expired token"
|
||||
}
|
||||
```
|
||||
|
||||
### 403 Forbidden
|
||||
```json
|
||||
{
|
||||
"error": "forbidden",
|
||||
"message": "Insufficient permissions"
|
||||
}
|
||||
```
|
||||
|
||||
### 404 Not Found
|
||||
```json
|
||||
{
|
||||
"error": "not_found",
|
||||
"message": "Resource not found"
|
||||
}
|
||||
```
|
||||
|
||||
### 409 Conflict
|
||||
```json
|
||||
{
|
||||
"error": "conflict",
|
||||
"message": "Resource already exists"
|
||||
}
|
||||
```
|
||||
|
||||
### 422 Validation Error
|
||||
```json
|
||||
{
|
||||
"error": "validation_error",
|
||||
"fields": {
|
||||
"location_code": "Field is required",
|
||||
"price": "Must be >= 0"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 500 Server Error
|
||||
```json
|
||||
{
|
||||
"error": "server_error",
|
||||
"message": "Internal server error"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Authentication & Authorization
|
||||
|
||||
### JWT Token
|
||||
- **Algorithm:** HS256
|
||||
- **TTL:** Configurable via `JWT_TTL_SECONDS` (default: 3600 seconds)
|
||||
- **Header:** `Authorization: Bearer <token>`
|
||||
|
||||
### Roles
|
||||
- **viewer** - Read-only access
|
||||
- **operator** - Read + Write (POST, PUT)
|
||||
- **admin** - Full access (Read + Write + Delete)
|
||||
|
||||
### API Key (Ingest)
|
||||
- **Header:** `X-API-KEY: <api-key>`
|
||||
- **Config:** `RETRIBUSI_API_KEY` in `.env`
|
||||
|
||||
---
|
||||
|
||||
## Rate Limiting
|
||||
|
||||
Saat ini tidak ada rate limiting. Untuk production, pertimbangkan untuk menambahkan rate limiting middleware.
|
||||
|
||||
---
|
||||
|
||||
## Pagination
|
||||
|
||||
Semua list endpoints mendukung pagination:
|
||||
|
||||
- `page` - Page number (default: 1)
|
||||
- `limit` - Items per page (default: 20, max: 100)
|
||||
|
||||
Response selalu include `meta` object dengan:
|
||||
- `page` - Current page
|
||||
- `limit` - Items per page
|
||||
- `total` - Total items
|
||||
- `pages` - Total pages
|
||||
|
||||
---
|
||||
|
||||
## Timestamps
|
||||
|
||||
Semua response include `timestamp` field (Unix timestamp).
|
||||
|
||||
Untuk date parameters, gunakan format: `YYYY-MM-DD`
|
||||
|
||||
Untuk datetime, gunakan format: `YYYY-MM-DD HH:MM:SS` atau Unix timestamp (integer).
|
||||
|
||||
---
|
||||
|
||||
## Support
|
||||
|
||||
Untuk pertanyaan atau issue, silakan hubungi tim development.
|
||||
|
||||
**Last Updated:** 2025-12-17
|
||||
|
||||
Reference in New Issue
Block a user