API Documentation

Base URL: /api

Semua request dan response menggunakan format JSON. Authentication menggunakan JWT Bearer token.

Response Format

{
  "success": true,
  "message": "OK",
  "data": { /* payload */ }
}

List Response (dengan pagination)

{
  "success": true,
  "data": [ /* items */ ],
  "pagination": {
    "total": 100, "page": 1, "per_page": 10, "total_pages": 10
  }
}

Error Response

{
  "success": false,
  "message": "Validasi gagal",
  "errors": { "name": "Name wajib diisi" }
}

HTTP Status Codes

  • 200 OK
  • 201 Created
  • 400 Bad Request
  • 401 Unauthorized (token invalid/expired)
  • 403 Forbidden (tidak punya permission)
  • 404 Not Found
  • 422 Unprocessable Entity (validasi gagal)
  • 500 Internal Server Error

Auth Header

Authorization: Bearer {jwt_token}

Authentication

POST /api/auth/login

Login dengan username (email) dan password.

Request Body
{
  "username": "[email protected]",
  "password": "Admin@123"
}
Response
{
  "success": true,
  "message": "Login berhasil",
  "data": {
    "token": "eyJ...",
    "expires_in": 86400,
    "user": { "id": 1, "name": "Administrator", "username": "[email protected]",
              "role_id": 1, "role_name": "Super Admin" },
    "permissions": {
      "users": { "view":1, "create":1, "edit":1, "delete":1, "export":1 }
    }
  }
}
POST /api/auth/logout

Logout (butuh auth).

GET /api/auth/me

Info user yang sedang login (butuh auth).

Users

GET /api/users users.view

List users dengan pagination.

Query params: page, per_page, search, role_id, status

POST /api/users users.create
{
  "name": "John Doe",
  "username": "[email protected]",
  "password": "secret123",
  "role_id": 2,
  "status": "active"
}
GET /api/users/{id} users.view
PUT /api/users/{id} users.edit

Field password opsional saat update.

DELETE /api/users/{id} users.delete

Soft delete. Tidak bisa hapus user yang sedang login.

Roles

GET /api/roles roles.view
POST /api/roles roles.create
{
  "name": "Editor",
  "description": "Akses edit saja",
  "status": "active",
  "permissions": {
    "users": { "view": 1, "create": 0, "edit": 1, "delete": 0, "export": 0 },
    "templates": { "view": 1, "create": 1, "edit": 1, "delete": 0, "export": 1 }
  }
}
GET /api/roles/{id}
PUT /api/roles/{id}
DELETE /api/roles/{id}

Tidak bisa hapus role Super Admin (id=1) atau role yang masih digunakan user.

Audit Logs

GET /api/audit-logs audit_log.view

Query params: user_id, username, method, status (2xx/3xx/4xx/5xx atau angka), endpoint, date_start, date_end

GET /api/audit-logs/{id}
GET /api/audit-logs/export audit_log.export

Export CSV dengan filter yang sama seperti list endpoint.

Categories

GET /api/categories categories.view
POST /api/categories
{"name":"Monthly","description":"...","status":"active"}
GET /api/categories/{id}
PUT /api/categories/{id}
DELETE /api/categories/{id}

Clients

GET /api/clients clients.view
POST /api/clients
{"name":"ABC Corp","description":"...","status":"active"}
GET /api/clients/{id}
PUT /api/clients/{id}
DELETE /api/clients/{id}

Projects

GET /api/projects projects.view

Query params: client_id untuk filter by client.

POST /api/projects
{"name":"Campaign Q4","client_id":1,"status":"active"}
GET /api/projects/{id}
PUT /api/projects/{id}
DELETE /api/projects/{id}

Slides

GET /api/slides slides.view

Query: search (judul atau file_name), status, page, per_page. Tiap item memuat thumbnail_path dan file_name.

GET /api/slides/active

List semua slide aktif (untuk popup pilih slide di template). Tiap item menyertakan thumbnail_path (URL relatif, mis. /uploads/slides/... atau null) dan file_name untuk preview kartu & zoom gambar di UI template.

POST /api/slides slides.create

JSON (Content-Type: application/json) atau multipart/form-data (field teks + file thumbnail).

Field: title (wajib), status (active|inactive), description, html_content, sort_order, variables (array JSON, atau string koma di multipart), file_name (opsional, acuan unik, contoh slide_2.html — huruf/angka, _, -, ., harus berakhiran .html), thumbnail (file gambar multipart), atau thumbnail_path (JSON saja, path publik yang sudah ada di /uploads/slides/...).

Thumbnail multipart: JPEG/PNG/WebP/GIF, maks. 2MB. Tersimpan di server dengan path publik /uploads/slides/slide_{id}_xxxxxxxx.ext.

{
  "title": "Overview",
  "description": "...",
  "file_name": "slide_overview.html",
  "html_content": "<div class=\"slide-container\">...</div>",
  "variables": ["client_name","date_range"],
  "status": "active",
  "sort_order": 1
}
GET /api/slides/{id}
PUT /api/slides/{id} slides.edit

Update dengan body JSON (sama field seperti POST). Jika thumbnail_path dikirim kosong/null, thumbnail di DB dihapus (file lama dihapus dari disk). Jika key tidak dikirim, thumbnail lama dipertahankan.

POST /api/slides/{id}/update slides.edit

Sama seperti PUT tetapi untuk multipart/form-data agar field thumbnail (file) terisi di PHP. Field teks sama seperti create. Tanpa file thumbnail, gambar yang ada tidak diubah.

DELETE /api/slides/{id}

Report Templates

GET /api/templates templates.view
POST /api/templates
{
  "name": "Monthly SM Report",
  "category_id": 1,
  "description": "...",
  "status": "active",
  "slide_ids": [1, 2, 3]
}

Urutan slide_ids menentukan urutan slide di template.

GET /api/templates/{id}

Detail template termasuk array slides berurutan: id, title, description, thumbnail_path, file_name, variables, sort_order.

GET /api/templates/{id}/slides

Slide aktif milik template (untuk generate report): html_content, variables, sort_order, serta thumbnail_path dan file_name bila perlu di sisi klien.

PUT /api/templates/{id}
DELETE /api/templates/{id}
POST /api/templates/{id}/duplicate

Reports

GET /api/reports reports.view
POST /api/reports
{
  "name": "Report Jan 2026",
  "template_id": 1,
  "client_id": 1,
  "project_ids": [1, 2],
  "channel": "Twitter",
  "sentiment": "all",
  "date_start": "2026-01-01",
  "date_end": "2026-01-31"
}
GET /api/reports/{id}
PUT /api/reports/{id}

Hanya name, channel, sentiment, date_start, date_end yang bisa diubah.

DELETE /api/reports/{id}
GET /api/reports/{id}/slides

Ambil slides dari report (berdasarkan template yang dipakai).

Configuration

GET /api/config configuration.view
POST /api/config
{
  "config_key": "max_upload_size",
  "config_value": "10485760",
  "config_type": "number",
  "label": "Max Upload Size",
  "group_name": "system"
}

config_type boleh: text, number, boolean, textarea, select.

PUT /api/config

Batch update semua config values sekaligus.

{
  "values": {
    "app_name": "Report Generator",
    "items_per_page": "10",
    "maintenance_mode": "0"
  }
}
DELETE /api/config/{id}