32 KiB
{ "openapi": "3.0.0", "info": { "title": "API Retribusi", "description": "API Retribusi BAPENDA Kabupaten Garut untuk monitoring Retribusi", "version": "1.0.0", "contact": { "name": "BTekno Development Team" } }, "servers": [ { "url": "https://api.btekno.cloud", "description": "Production Server" }, { "url": "http://localhost", "description": "Local Development" } ], "tags": [ { "name": "Health", "description": "Health check endpoint" }, { "name": "Authentication", "description": "JWT authentication" }, { "name": "Ingest", "description": "Event ingestion (mesin YOLO)" }, { "name": "Frontend", "description": "Frontend CRUD operations" }, { "name": "Summary", "description": "Data summary & aggregation" }, { "name": "Dashboard", "description": "Dashboard visualization data" }, { "name": "Realtime", "description": "Real-time events (SSE)" } ], "components": { "securitySchemes": { "BearerAuth": { "type": "http", "scheme": "bearer", "bearerFormat": "JWT", "description": "JWT token untuk frontend API" }, "ApiKeyAuth": { "type": "apiKey", "in": "header", "name": "X-API-KEY", "description": "API Key untuk ingest endpoint" } }, "schemas": { "Error": { "type": "object", "properties": { "error": { "type": "string", "description": "Error code" }, "message": { "type": "string", "description": "Error message" }, "fields": { "type": "object", "description": "Validation errors (optional)" } } }, "Success": { "type": "object", "properties": { "success": { "type": "boolean", "example": true }, "data": { "type": "object" }, "timestamp": { "type": "integer", "description": "Unix timestamp" } } } } }, "paths": { "/health": { "get": { "tags": ["Health"], "summary": "Health check", "description": "Check API health status", "responses": { "200": { "description": "API is healthy", "content": { "application/json": { "schema": { "type": "object", "properties": { "status": { "type": "string", "example": "ok" }, "time": { "type": "integer", "example": 1735123456 } } } } } } } } }, "/auth/v1/login": { "post": { "tags": ["Authentication"], "summary": "Login", "description": "Authenticate user dan dapatkan JWT token", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["username", "password"], "properties": { "username": { "type": "string", "example": "admin" }, "password": { "type": "string", "format": "password", "example": "password123" } } } } } }, "responses": { "200": { "description": "Login successful", "content": { "application/json": { "schema": { "allOf": [ {"$ref": "#/components/schemas/Success"}, { "type": "object", "properties": { "data": { "type": "object", "properties": { "token": { "type": "string" }, "expires_in": { "type": "integer" }, "user": { "type": "object", "properties": { "id": {"type": "integer"}, "username": {"type": "string"}, "role": {"type": "string"} } } } } } } ] } } } }, "401": { "description": "Unauthorized", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "403": { "description": "Forbidden (user inactive)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } }, "/retribusi/v1/ingest": { "post": { "tags": ["Ingest"], "summary": "Ingest event data", "description": "Masukkan event data dari mesin YOLO", "security": [ { "ApiKeyAuth": [] } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["timestamp", "location_code", "gate_code", "category"], "properties": { "timestamp": { "type": "integer", "description": "Unix timestamp", "example": 1735123456 }, "location_code": { "type": "string", "example": "kerkof_01" }, "gate_code": { "type": "string", "example": "gate01" }, "category": { "type": "string", "example": "motor" } } } } } }, "responses": { "200": { "description": "Event stored successfully", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Success" } } } }, "401": { "description": "Unauthorized (invalid API key)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "404": { "description": "Not found (location/gate/tariff not found)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "422": { "description": "Validation error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } }, "/retribusi/v1/frontend/locations": { "get": { "tags": ["Frontend"], "summary": "Get locations list", "description": "Mendapatkan daftar lokasi dengan pagination", "security": [ { "BearerAuth": [] } ], "parameters": [ { "name": "page", "in": "query", "schema": { "type": "integer", "default": 1, "minimum": 1 }, "description": "Page number" }, { "name": "limit", "in": "query", "schema": { "type": "integer", "default": 20, "minimum": 1, "maximum": 100 }, "description": "Items per page" } ], "responses": { "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Success" } } } }, "401": { "description": "Unauthorized", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } }, "post": { "tags": ["Frontend"], "summary": "Create location", "description": "Membuat lokasi baru (operator/admin only)", "security": [ { "BearerAuth": [] } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["code", "name", "type", "is_active"], "properties": { "code": { "type": "string", "example": "kerkof_01" }, "name": { "type": "string", "example": "Kerkof Garut" }, "type": { "type": "string", "example": "parkir" }, "is_active": { "type": "integer", "enum": [0, 1], "example": 1 } } } } } }, "responses": { "201": { "description": "Location created", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Success" } } } }, "401": { "description": "Unauthorized", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "403": { "description": "Forbidden (insufficient permissions)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "409": { "description": "Conflict (code already exists)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } }, "/retribusi/v1/summary/daily": { "get": { "tags": ["Summary"], "summary": "Get daily summary", "description": "Mendapatkan rekap harian", "security": [ { "BearerAuth": [] } ], "parameters": [ { "name": "date", "in": "query", "required": true, "schema": { "type": "string", "format": "date", "example": "2025-01-01" }, "description": "Date (Y-m-d format)" }, { "name": "location_code", "in": "query", "schema": { "type": "string" } }, { "name": "gate_code", "in": "query", "schema": { "type": "string" } } ], "responses": { "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Success" } } } } } } }, "/retribusi/v1/summary/hourly": { "get": { "tags": ["Summary"], "summary": "Get hourly summary", "description": "Mendapatkan rekap per jam untuk chart (24 jam)", "security": [ { "BearerAuth": [] } ], "parameters": [ { "name": "date", "in": "query", "required": true, "schema": { "type": "string", "format": "date", "example": "2025-01-01" } }, { "name": "location_code", "in": "query", "schema": { "type": "string" } }, { "name": "gate_code", "in": "query", "schema": { "type": "string" } } ], "responses": { "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Success" } } } } } } }, "/retribusi/v1/dashboard/daily": { "get": { "tags": ["Dashboard"], "summary": "Get daily chart data", "description": "Data untuk line chart harian", "security": [ { "BearerAuth": [] } ], "parameters": [ { "name": "start_date", "in": "query", "required": true, "schema": { "type": "string", "format": "date" } }, { "name": "end_date", "in": "query", "required": true, "schema": { "type": "string", "format": "date" } }, { "name": "location_code", "in": "query", "schema": { "type": "string" } }, { "name": "gate_code", "in": "query", "schema": { "type": "string" } } ], "responses": { "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Success" } } } } } } }, "/retribusi/v1/dashboard/by-category": { "get": { "tags": ["Dashboard"], "summary": "Get by category chart data", "description": "Data chart grouped by category (bar/donut chart)", "security": [ { "BearerAuth": [] } ], "parameters": [ { "name": "date", "in": "query", "required": true, "schema": { "type": "string", "format": "date" } }, { "name": "location_code", "in": "query", "schema": { "type": "string" } }, { "name": "gate_code", "in": "query", "schema": { "type": "string" } } ], "responses": { "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Success" } } } } } } }, "/retribusi/v1/dashboard/summary": { "get": { "tags": ["Dashboard"], "summary": "Get summary statistics", "description": "Mendapatkan summary statistics (stat cards)", "security": [ { "BearerAuth": [] } ], "parameters": [ { "name": "date", "in": "query", "required": true, "schema": { "type": "string", "format": "date" } }, { "name": "location_code", "in": "query", "schema": { "type": "string" } } ], "responses": { "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Success" } } } } } } }, "/retribusi/v1/realtime/stream": { "get": { "tags": ["Realtime"], "summary": "SSE Stream", "description": "Server-Sent Events stream untuk real-time updates", "security": [ { "BearerAuth": [] } ], "parameters": [ { "name": "last_id", "in": "query", "schema": { "type": "integer" }, "description": "Last event ID received" }, { "name": "location_code", "in": "query", "schema": { "type": "string" } } ], "responses": { "200": { "description": "SSE stream", "content": { "text/event-stream": { "schema": { "type": "string" } } } }, "401": { "description": "Unauthorized", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } }, "/retribusi/v1/frontend/locations/{code}": { "get": { "tags": ["Frontend"], "summary": "Get location detail", "description": "Mendapatkan detail location berdasarkan code", "security": [ { "BearerAuth": [] } ], "parameters": [ { "name": "code", "in": "path", "required": true, "schema": { "type": "string" }, "description": "Location code" } ], "responses": { "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Success" } } } }, "404": { "description": "Location not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } }, "put": { "tags": ["Frontend"], "summary": "Update location", "description": "Update location (code tidak bisa diubah)", "security": [ { "BearerAuth": [] } ], "parameters": [ { "name": "code", "in": "path", "required": true, "schema": { "type": "string" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "properties": { "name": { "type": "string" }, "type": { "type": "string" }, "is_active": { "type": "integer", "enum": [0, 1] } } } } } }, "responses": { "200": { "description": "Location updated", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Success" } } } }, "404": { "description": "Location not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } }, "delete": { "tags": ["Frontend"], "summary": "Delete location", "description": "Soft delete location (admin only)", "security": [ { "BearerAuth": [] } ], "parameters": [ { "name": "code", "in": "path", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "Location deleted", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Success" } } } }, "403": { "description": "Forbidden (admin only)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } }, "/retribusi/v1/frontend/gates": { "get": { "tags": ["Frontend"], "summary": "Get gates list", "description": "Mendapatkan daftar gates dengan pagination", "security": [ { "BearerAuth": [] } ], "parameters": [ { "name": "page", "in": "query", "schema": { "type": "integer", "default": 1, "minimum": 1 } }, { "name": "limit", "in": "query", "schema": { "type": "integer", "default": 20, "minimum": 1, "maximum": 100 } }, { "name": "location_code", "in": "query", "schema": { "type": "string" } } ], "responses": { "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Success" } } } } } }, "post": { "tags": ["Frontend"], "summary": "Create gate", "description": "Membuat gate baru (operator/admin only)", "security": [ { "BearerAuth": [] } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["location_code", "gate_code", "name", "direction", "is_active"], "properties": { "location_code": { "type": "string", "example": "kerkof_01" }, "gate_code": { "type": "string", "example": "gate01" }, "name": { "type": "string", "example": "Gate 01" }, "direction": { "type": "string", "enum": ["in", "out"], "example": "in" }, "camera": { "type": "string", "description": "Camera URL (HLS, RTSP, HTTP) atau camera ID", "example": "https://example.com/stream.m3u8", "maxLength": 500 }, "is_active": { "type": "integer", "enum": [0, 1], "example": 1 } } } } } }, "responses": { "201": { "description": "Gate created", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Success" } } } }, "409": { "description": "Conflict (gate already exists)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } }, "/retribusi/v1/frontend/gates/{location_code}/{gate_code}": { "get": { "tags": ["Frontend"], "summary": "Get gate detail", "description": "Mendapatkan detail gate berdasarkan location_code dan gate_code", "security": [ { "BearerAuth": [] } ], "parameters": [ { "name": "location_code", "in": "path", "required": true, "schema": { "type": "string" } }, { "name": "gate_code", "in": "path", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Success" } } } }, "404": { "description": "Gate not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } }, "put": { "tags": ["Frontend"], "summary": "Update gate", "description": "Update gate (location_code dan gate_code tidak bisa diubah)", "security": [ { "BearerAuth": [] } ], "parameters": [ { "name": "location_code", "in": "path", "required": true, "schema": { "type": "string" } }, { "name": "gate_code", "in": "path", "required": true, "schema": { "type": "string" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "properties": { "name": { "type": "string" }, "direction": { "type": "string", "enum": ["in", "out"] }, "camera": { "type": "string", "description": "Camera URL (HLS, RTSP, HTTP) atau camera ID", "maxLength": 500 }, "is_active": { "type": "integer", "enum": [0, 1] } } } } } }, "responses": { "200": { "description": "Gate updated", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Success" } } } }, "404": { "description": "Gate not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } }, "delete": { "tags": ["Frontend"], "summary": "Delete gate", "description": "Soft delete gate (admin only)", "security": [ { "BearerAuth": [] } ], "parameters": [ { "name": "location_code", "in": "path", "required": true, "schema": { "type": "string" } }, { "name": "gate_code", "in": "path", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "Gate deleted", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Success" } } } } } } }, "/retribusi/v1/frontend/tariffs": { "get": { "tags": ["Frontend"], "summary": "Get tariffs list", "description": "Mendapatkan daftar tariffs dengan pagination", "security": [ { "BearerAuth": [] } ], "parameters": [ { "name": "page", "in": "query", "schema": { "type": "integer", "default": 1, "minimum": 1 } }, { "name": "limit", "in": "query", "schema": { "type": "integer", "default": 20, "minimum": 1, "maximum": 100 } }, { "name": "location_code", "in": "query", "schema": { "type": "string" } }, { "name": "gate_code", "in": "query", "schema": { "type": "string" } } ], "responses": { "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Success" } } } } } }, "post": { "tags": ["Frontend"], "summary": "Create tariff", "description": "Membuat tariff baru (operator/admin only)", "security": [ { "BearerAuth": [] } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["location_code", "gate_code", "category", "price"], "properties": { "location_code": { "type": "string" }, "gate_code": { "type": "string" }, "category": { "type": "string", "enum": ["person_walk", "motor", "car"] }, "price": { "type": "integer", "minimum": 0 } } } } } }, "responses": { "201": { "description": "Tariff created", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Success" } } } } } } }, "/retribusi/v1/frontend/tariffs/{location_code}/{gate_code}/{category}": { "get": { "tags": ["Frontend"], "summary": "Get tariff detail", "description": "Mendapatkan detail tariff berdasarkan location_code, gate_code, dan category", "security": [ { "BearerAuth": [] } ], "parameters": [ { "name": "location_code", "in": "path", "required": true, "schema": { "type": "string" } }, { "name": "gate_code", "in": "path", "required": true, "schema": { "type": "string" } }, { "name": "category", "in": "path", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Success" } } } }, "404": { "description": "Tariff not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } }, "put": { "tags": ["Frontend"], "summary": "Update tariff", "description": "Update tariff price (operator/admin only)", "security": [ { "BearerAuth": [] } ], "parameters": [ { "name": "location_code", "in": "path", "required": true, "schema": { "type": "string" } }, { "name": "gate_code", "in": "path", "required": true, "schema": { "type": "string" } }, { "name": "category", "in": "path", "required": true, "schema": { "type": "string" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["price"], "properties": { "price": { "type": "integer", "minimum": 0 } } } } } }, "responses": { "200": { "description": "Tariff updated", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Success" } } } } } }, "delete": { "tags": ["Frontend"], "summary": "Delete tariff", "description": "Hard delete tariff (admin only)", "security": [ { "BearerAuth": [] } ], "parameters": [ { "name": "location_code", "in": "path", "required": true, "schema": { "type": "string" } }, { "name": "gate_code", "in": "path", "required": true, "schema": { "type": "string" } }, { "name": "category", "in": "path", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "Tariff deleted", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Success" } } } } } } }, "/retribusi/v1/frontend/audit-logs": { "get": { "tags": ["Frontend"], "summary": "Get audit logs", "description": "Mendapatkan audit trail history dengan pagination dan filter", "security": [ { "BearerAuth": [] } ], "parameters": [ { "name": "page", "in": "query", "schema": { "type": "integer", "default": 1, "minimum": 1 } }, { "name": "limit", "in": "query", "schema": { "type": "integer", "default": 20, "minimum": 1, "maximum": 100 } }, { "name": "entity", "in": "query", "schema": { "type": "string", "enum": ["locations", "gates", "tariffs"] } }, { "name": "action", "in": "query", "schema": { "type": "string", "enum": ["create", "update", "delete"] } }, { "name": "entity_key", "in": "query", "schema": { "type": "string" } }, { "name": "start_date", "in": "query", "schema": { "type": "string", "format": "date" } }, { "name": "end_date", "in": "query", "schema": { "type": "string", "format": "date" } } ], "responses": { "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Success" } } } } } } }, "/retribusi/v1/frontend/entry-events": { "get": { "tags": ["Frontend"], "summary": "Get entry events", "description": "Mendapatkan daftar raw entry events (data mentah dari mesin)", "security": [ { "BearerAuth": [] } ], "parameters": [ { "name": "page", "in": "query", "schema": { "type": "integer", "default": 1, "minimum": 1 } }, { "name": "limit", "in": "query", "schema": { "type": "integer", "default": 20, "minimum": 1, "maximum": 100 } }, { "name": "location_code", "in": "query", "schema": { "type": "string" } }, { "name": "gate_code", "in": "query", "schema": { "type": "string" } }, { "name": "category", "in": "query", "schema": { "type": "string" } }, { "name": "start_date", "in": "query", "schema": { "type": "string", "format": "date" } }, { "name": "end_date", "in": "query", "schema": { "type": "string", "format": "date" } } ], "responses": { "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Success" } } } } } } }, "/retribusi/v1/frontend/streams": { "get": { "tags": ["Frontend"], "summary": "Get streams list", "description": "Get list of streams (alias untuk gates)", "security": [ { "BearerAuth": [] } ], "parameters": [ { "name": "page", "in": "query", "schema": { "type": "integer", "default": 1, "minimum": 1 } }, { "name": "limit", "in": "query", "schema": { "type": "integer", "default": 20, "minimum": 1, "maximum": 100 } }, { "name": "location_code", "in": "query", "schema": { "type": "string" } } ], "responses": { "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Success" } } } } } } }, "/retribusi/v1/realtime/snapshot": { "get": { "tags": ["Realtime"], "summary": "Get snapshot", "description": "Mendapatkan snapshot data untuk dashboard cards", "security": [ { "BearerAuth": [] } ], "parameters": [ { "name": "date", "in": "query", "schema": { "type": "string", "format": "date" }, "description": "Date (default: today)" }, { "name": "location_code", "in": "query", "schema": { "type": "string" } } ], "responses": { "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Success" } } } } } } }, "/retribusi/v1/realtime/events": { "get": { "tags": ["Realtime"], "summary": "Get realtime events list", "description": "Mendapatkan daftar realtime events (history untuk SSE)", "security": [ { "BearerAuth": [] } ], "parameters": [ { "name": "page", "in": "query", "schema": { "type": "integer", "default": 1, "minimum": 1 } }, { "name": "limit", "in": "query", "schema": { "type": "integer", "default": 20, "minimum": 1, "maximum": 100 } }, { "name": "location_code", "in": "query", "schema": { "type": "string" } }, { "name": "gate_code", "in": "query", "schema": { "type": "string" } }, { "name": "category", "in": "query", "schema": { "type": "string" } }, { "name": "start_date", "in": "query", "schema": { "type": "string", "format": "date" } }, { "name": "end_date", "in": "query", "schema": { "type": "string", "format": "date" } } ], "responses": { "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Success" } } } } } } } } }