Files
api-btekno/API_ENDPOINTS.md

14 KiB

API Endpoints Documentation

Dokumentasi lengkap semua endpoint yang tersedia di API Btekno.

Base URL: https://api.btekno.cloud


📋 Daftar Isi


Public Endpoints

Health Check

GET /health

Health check endpoint untuk monitoring.

Response:

{
  "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:

{
  "username": "admin",
  "password": "password123"
}

Response (200):

{
  "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:

{
  "timestamp": 1703123456,
  "location_code": "kerkof_01",
  "gate_code": "gate01",
  "category": "motor"
}

Response (200):

{
  "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):

{
  "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:

{
  "code": "kerkof_02",
  "name": "Kerkof 02",
  "type": "kerkof",
  "is_active": 1
}

Response (201):

{
  "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:

{
  "name": "Kerkof 02 Updated",
  "type": "kerkof",
  "is_active": 1
}

Response (200):

{
  "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):

{
  "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):

{
  "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:

{
  "location_code": "kerkof_01",
  "gate_code": "gate02",
  "name": "Gate 02",
  "direction": "out",
  "is_active": 1
}

Response (201):

{
  "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:

{
  "name": "Gate 02 Updated",
  "direction": "out",
  "is_active": 1
}

Response (200):

{
  "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):

{
  "success": true,
  "data": {
    "deleted": true
  },
  "timestamp": 1703123456
}

Access: Admin only


Tariffs

Create Tariff

POST /retribusi/v1/frontend/tariffs

Create new tariff.

Request Body:

{
  "location_code": "kerkof_01",
  "gate_code": "gate01",
  "category": "motor",
  "price": 5000
}

Response (201):

{
  "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:

{
  "price": 6000
}

Response (200):

{
  "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):

{
  "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):

{
  "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:

{
  "date": "2025-12-16"
}

Response (200):

{
  "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):

{
  "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):

{
  "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):

{
  "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):

{
  "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):

{
  "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):

{
  "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

{
  "error": "unauthorized",
  "message": "Invalid or expired token"
}

403 Forbidden

{
  "error": "forbidden",
  "message": "Insufficient permissions"
}

404 Not Found

{
  "error": "not_found",
  "message": "Resource not found"
}

409 Conflict

{
  "error": "conflict",
  "message": "Resource already exists"
}

422 Validation Error

{
  "error": "validation_error",
  "fields": {
    "location_code": "Field is required",
    "price": "Must be >= 0"
  }
}

500 Server Error

{
  "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