cargo-platform/docs/index.html
teguh nugroho 39265bfcb1
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
oerubahan
2026-09-05 14:31:03 +07:00

253 lines
46 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Cargo ERP Backend API Documentation</title>
<style>
*{margin:0;padding:0;box-sizing:border-box}
:root{--bg:#0f172a;--bg2:#1e293b;--bg3:#334155;--text:#e2e8f0;--text2:#94a3b8;--border:#475569;--get:#3b82f6;--post:#22c55e;--put:#f59e0b;--delete:#ef4444;--accent:#60a5fa;--green:#86efac;--red:#fca5a5;--yellow:#fde68a}
body{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,monospace;background:var(--bg);color:var(--text);display:flex;min-height:100vh}
.sidebar{width:280px;background:var(--bg2);border-right:1px solid var(--border);position:fixed;top:0;left:0;bottom:0;overflow-y:auto;padding:16px 0;z-index:10}
.sidebar h2{padding:0 16px 12px;font-size:16px;color:var(--accent);border-bottom:1px solid var(--border);margin-bottom:8px}
.sidebar .info{padding:0 16px 8px;font-size:11px;color:var(--text2)}
.sidebar .search{margin:8px 16px 12px}
.sidebar input{width:100%;padding:8px 12px;border-radius:6px;border:1px solid var(--border);background:var(--bg);color:var(--text);font-size:13px;outline:none}
.sidebar input:focus{border-color:var(--accent)}
.sidebar nav a{display:flex;align-items:center;gap:8px;padding:5px 16px;color:var(--text2);text-decoration:none;font-size:12px;border-left:3px solid transparent;transition:.15s}
.sidebar nav a:hover{background:var(--bg3);color:var(--text)}
.sidebar nav a .dot{width:8px;height:8px;border-radius:50%;flex-shrink:0}
.sidebar nav .cat{font-size:12px;font-weight:700;color:var(--text);padding:14px 16px 4px;text-transform:uppercase;letter-spacing:.5px}
.sidebar nav .count{font-size:10px;color:var(--text2);font-weight:400;margin-left:auto}
.main{margin-left:280px;flex:1;padding:24px 32px;max-width:960px}
.main h1{font-size:24px;margin-bottom:4px}
.main .subtitle{color:var(--text2);margin-bottom:20px;font-size:13px;line-height:1.5}
.server-bar{display:flex;gap:10px;margin-bottom:20px;flex-wrap:wrap}
.server-bar .srv{padding:6px 12px;border-radius:6px;background:var(--bg2);border:1px solid var(--border);font-size:12px;cursor:pointer;transition:.15s;color:var(--text2)}
.server-bar .srv.active{border-color:var(--accent);color:var(--accent)}
.server-bar .srv:hover{border-color:var(--accent)}
.stats{display:flex;gap:16px;margin-bottom:24px;flex-wrap:wrap}
.stat{padding:10px 16px;border-radius:8px;background:var(--bg2);border:1px solid var(--border);font-size:12px;color:var(--text2)}
.stat strong{color:var(--text);font-size:18px;display:block}
.cat-section{margin-top:28px}
.cat-title{font-size:18px;font-weight:700;color:var(--accent);margin-bottom:12px;padding-bottom:8px;border-bottom:1px solid var(--border)}
.endpoints{display:flex;flex-direction:column;gap:8px}
.ep{background:var(--bg2);border:1px solid var(--border);border-radius:8px;overflow:hidden;transition:border-color .15s}
.ep:hover{border-color:var(--text2)}
.ep-head{display:flex;align-items:center;gap:10px;padding:10px 14px;cursor:pointer}
.ep-head:hover{background:var(--bg3)}
.method{padding:2px 8px;border-radius:4px;font-size:11px;font-weight:700;color:#fff;min-width:56px;text-align:center;text-transform:uppercase;flex-shrink:0}
.method.get{background:var(--get)}.method.post{background:var(--post)}.method.put{background:var(--put)}.method.delete{background:var(--delete)}
.ep-path{font-size:13px;font-family:monospace;color:var(--text);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.ep-path .param{color:var(--accent)}
.ep-summary{color:var(--text2);font-size:11px;margin-left:auto;white-space:nowrap}
.ep-body{display:none;padding:14px;border-top:1px solid var(--border);font-size:12px;line-height:1.6}
.ep.open .ep-body{display:block}
.section-label{color:var(--accent);font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;margin:10px 0 4px}
.section-label:first-child{margin-top:0}
.params table{width:100%;border-collapse:collapse;margin-bottom:8px}
.params td,.params th{text-align:left;padding:5px 8px;border-bottom:1px solid var(--border);font-size:12px}
.params th{color:var(--text2);font-size:10px;text-transform:uppercase}
.badge-r{color:var(--red)}.badge-o{color:var(--text2)}
.req-fields{margin-bottom:8px}
.req-fields table{width:100%;border-collapse:collapse;margin-bottom:8px}
.req-fields td,.req-fields th{text-align:left;padding:6px 10px;border-bottom:1px solid var(--border);font-size:12px}
.req-fields th{color:var(--text2);font-size:10px;text-transform:uppercase}
.req-fields .required-val{color:var(--red)}
pre{background:var(--bg);border:1px solid var(--border);border-radius:6px;padding:10px 14px;overflow-x:auto;font-size:11px;line-height:1.5;margin-bottom:8px;color:var(--text2);white-space:pre-wrap;word-break:break-all}
pre .k{color:#93c5fd}pre .s{color:#86efac}pre .n{color:#fbbf24}pre .b{color:#c084fc}
.footer{text-align:center;padding:32px;color:var(--text2);font-size:11px}
@media(max-width:768px){.sidebar{display:none}.main{margin-left:0;padding:16px}}
</style>
</head>
<body>
<div class="sidebar">
<h2>Cargo ERP API</h2>
<div class="info">67 endpoints across 8 modules</div>
<div class="search"><input type="text" id="search" placeholder="Search endpoints..."></div>
<nav id="nav"></nav>
</div>
<div class="main">
<h1>Cargo ERP Backend API Documentation</h1>
<p class="subtitle">Complete reference for all API endpoints. No authentication required for testing.</p>
<div class="server-bar">
<div class="srv active" onclick="setBase(0)">Local (localhost:8080)</div>
<div class="srv" onclick="setBase(1)">VPS (145.79.11.200:8080)</div>
</div>
<div class="stats" id="stats"></div>
<div id="content"></div>
<div class="footer">Cargo ERP Backend API Documentation</div>
</div>
<script>
const URLS=["http://localhost:8080","http://145.79.11.200:8080"];
let BASE=URLS[0];
function setBase(i){BASE=URLS[i];document.querySelectorAll(".srv").forEach((s,j)=>s.classList.toggle("active",j===i));render()}
const E=[
{cat:"Auth",m:"get",p:"/ping",s:"Health check",q:[],rb:null,rbe:"{\n \"message\": \"pong\"\n}",rf:[]},
{cat:"Auth",m:"post",p:"/login",s:"Login — get session token",q:[],rb:"{\n \"email\": \"admin@example.com\",\n \"password\": \"secret123\"\n}",rbe:"{\n \"success\": true,\n \"data\": {\n \"token\": \"eyJhbGciOiJIUzI1NiJ9...\"\n }\n}",rf:["email","password"]},
{cat:"Auth",m:"post",p:"/logout",s:"Logout — destroy session",q:[],rb:null,rbe:"{\n \"success\": true,\n \"message\": \"You are logged out\"\n}",rf:[]},
{cat:"Master Data / Province",m:"get",p:"/master-data/provinces/",s:"Get all provinces",q:[{n:"name",t:"string",req:false,d:"Filter by name"},{n:"id",t:"string",req:false,d:"Filter by ID"}],rb:null,rbe:"{\\n \"success\": true,\\n \"data\": [\\n { ... }\\n ]\\n}",rf:[]},
{cat:"Master Data / Province",m:"post",p:"/master-data/provinces/list",s:"Province list (DataTable pagination)",q:[],rb:"_DT_",rbe:"{\n \"success\": true,\n \"data\": {\n \"draw\": 1,\n \"recordsTotal\": 34,\n \"recordsFiltered\": 34,\n \"data\": [\n { \"id\": \"01HXYZ123456789012345678\", \"name\": \"...\" }\n ]\n }\n}",rf:[]},
{cat:"Master Data / Province",m:"get",p:"/master-data/provinces/:id",s:"Get province by ID",q:[{n:"id",t:"string",req:true,d:"Province ID (26-char ULID)"}],rb:null,rbe:"{\n \"success\": true,\n \"data\": {\n \"id\": \"01HXYZ123456789012345678\",\n \"name\": \"Jawa Barat\",\n \"merchant_id\": \"01HXYZ123456789012345678\"\n }\n}",rf:[]},
{cat:"Master Data / Province",m:"post",p:"/master-data/provinces/",s:"Create province",q:[],rb:"{\n \"name\": \"Jawa Barat\"\n}",rbe:"{\n \"success\": true,\n \"data\": {\n \"id\": \"01HXYZ123456789012345678\",\n \"name\": \"Jawa Barat\",\n \"merchant_id\": \"01HXYZ123456789012345678\"\n }\n}",rf:["name"]},
{cat:"Master Data / Province",m:"put",p:"/master-data/provinces/:id",s:"Update province",q:[{n:"id",t:"string",req:true,d:"Province ID"}],rb:"{\n \"name\": \"Jawa Barat\"\n}",rbe:"{\n \"success\": true,\n \"data\": {\n \"id\": \"01HXYZ123456789012345678\",\n \"name\": \"Jawa Barat\",\n \"merchant_id\": \"01HXYZ123456789012345678\"\n }\n}",rf:["name"]},
{cat:"Master Data / Province",m:"delete",p:"/master-data/provinces/:id",s:"Delete province",q:[{n:"id",t:"string",req:true,d:"Province ID"}],rb:null,rbe:"{\n \"success\": true,\n \"message\": \"province deleted\"\n}",rf:[]},
{cat:"Master Data / Province",m:"get",p:"/master-data/provinces/template",s:"Download province CSV template",q:[],rb:null,rbe:"<i>Returns CSV file (Content-Type: text/csv)</i>",rf:[]},
{cat:"Master Data / Province",m:"post",p:"/master-data/provinces/import",s:"Import provinces from CSV",q:[],rb:"_MULTIPART_",rbe:"{\n \"success\": true,\n \"data\": {\n \"job_id\": \"job_abc123def456\",\n \"total_rows\": 100,\n \"imported\": 95,\n \"skipped\": 5,\n \"logs\": [\n {\n \"row\": 2,\n \"status\": \"skipped\",\n \"data\": \"Jawa Barat\",\n \"message\": \"duplicate\"\n }\n ],\n \"errors\": [],\n \"is_async\": false\n }\n}",rf:[]},
{cat:"Master Data / Province",m:"post",p:"/master-data/provinces/import/stop",s:"Stop province import job",q:[],rb:"{\n \"job_id\": \"job_abc123def456\"\n}",rbe:"{\n \"success\": true,\n \"message\": \"Job stopped\"\n}",rf:["job_id"]},
{cat:"Master Data / Province",m:"get",p:"/master-data/provinces/import/status/:jobId",s:"Check province import job status",q:[{n:"jobId",t:"string",req:true,d:"Async job ID"}],rb:null,rbe:"{\n \"success\": true,\n \"data\": {\n \"job\": {\n \"id\": \"job_abc123def456\",\n \"status\": \"completed\",\n \"total\": 100,\n \"imported\": 95,\n \"skipped\": 5\n },\n \"logs\": []\n }\n}",rf:[]},
{cat:"Master Data / City",m:"get",p:"/master-data/cities/",s:"Get all citys",q:[{n:"name",t:"string",req:false,d:"Filter by name"},{n:"province_id",t:"string",req:false,d:"Filter by province"}],rb:null,rbe:"{\\n \"success\": true,\\n \"data\": [\\n { ... }\\n ]\\n}",rf:[]},
{cat:"Master Data / City",m:"post",p:"/master-data/cities/list",s:"City list (DataTable pagination)",q:[],rb:"_DT_",rbe:"{\n \"success\": true,\n \"data\": {\n \"draw\": 1,\n \"recordsTotal\": 34,\n \"recordsFiltered\": 34,\n \"data\": [\n { \"id\": \"01HXYZ123456789012345678\", \"name\": \"...\" }\n ]\n }\n}",rf:[]},
{cat:"Master Data / City",m:"get",p:"/master-data/cities/:id",s:"Get city by ID",q:[{n:"id",t:"string",req:true,d:"City ID (26-char ULID)"}],rb:null,rbe:"{\n \"success\": true,\n \"data\": {\n \"id\": \"01HXYZ123456789012345678\",\n \"name\": \"Kota Bandung\",\n \"province_id\": \"01HXYZ123456789012345678\",\n \"port\": \"01HXYZ123456789012345678\",\n \"merchant_id\": \"01HXYZ123456789012345678\",\n \"port\": \"BDO\"\n }\n}",rf:[]},
{cat:"Master Data / City",m:"post",p:"/master-data/cities/",s:"Create city",q:[],rb:"{\n \"name\": \"Kota Bandung\",\n \"province_id\": \"01HXYZ123456789012345678\",\n \"port\": \"BDO\"\n}",rbe:"{\n \"success\": true,\n \"data\": {\n \"id\": \"01HXYZ123456789012345678\",\n \"name\": \"Kota Bandung\",\n \"province_id\": \"01HXYZ123456789012345678\",\n \"port\": \"01HXYZ123456789012345678\",\n \"merchant_id\": \"01HXYZ123456789012345678\",\n \"port\": \"BDO\"\n }\n}",rf:["name","province_id"]},
{cat:"Master Data / City",m:"put",p:"/master-data/cities/:id",s:"Update city",q:[{n:"id",t:"string",req:true,d:"City ID"}],rb:"{\n \"name\": \"Kota Bandung\",\n \"province_id\": \"01HXYZ123456789012345678\",\n \"port\": \"BDO\"\n}",rbe:"{\n \"success\": true,\n \"data\": {\n \"id\": \"01HXYZ123456789012345678\",\n \"name\": \"Kota Bandung\",\n \"province_id\": \"01HXYZ123456789012345678\",\n \"port\": \"01HXYZ123456789012345678\",\n \"merchant_id\": \"01HXYZ123456789012345678\",\n \"port\": \"BDO\"\n }\n}",rf:["name","province_id"]},
{cat:"Master Data / City",m:"delete",p:"/master-data/cities/:id",s:"Delete city",q:[{n:"id",t:"string",req:true,d:"City ID"}],rb:null,rbe:"{\n \"success\": true,\n \"message\": \"city deleted\"\n}",rf:[]},
{cat:"Master Data / City",m:"get",p:"/master-data/cities/template",s:"Download city CSV template",q:[],rb:null,rbe:"<i>Returns CSV file (Content-Type: text/csv)</i>",rf:[]},
{cat:"Master Data / City",m:"post",p:"/master-data/cities/import",s:"Import citys from CSV",q:[],rb:"_MULTIPART_",rbe:"{\n \"success\": true,\n \"data\": {\n \"job_id\": \"job_abc123def456\",\n \"total_rows\": 100,\n \"imported\": 95,\n \"skipped\": 5,\n \"logs\": [\n {\n \"row\": 2,\n \"status\": \"skipped\",\n \"data\": \"Jawa Barat\",\n \"message\": \"duplicate\"\n }\n ],\n \"errors\": [],\n \"is_async\": false\n }\n}",rf:[]},
{cat:"Master Data / City",m:"post",p:"/master-data/cities/import/stop",s:"Stop city import job",q:[],rb:"{\n \"job_id\": \"job_abc123def456\"\n}",rbe:"{\n \"success\": true,\n \"message\": \"Job stopped\"\n}",rf:["job_id"]},
{cat:"Master Data / City",m:"get",p:"/master-data/cities/import/status/:jobId",s:"Check city import job status",q:[{n:"jobId",t:"string",req:true,d:"Async job ID"}],rb:null,rbe:"{\n \"success\": true,\n \"data\": {\n \"job\": {\n \"id\": \"job_abc123def456\",\n \"status\": \"completed\",\n \"total\": 100,\n \"imported\": 95,\n \"skipped\": 5\n },\n \"logs\": []\n }\n}",rf:[]},
{cat:"Master Data / District",m:"get",p:"/master-data/districts/",s:"Get all districts",q:[{n:"name",t:"string",req:false,d:"Filter by name"},{n:"city_id",t:"string",req:false,d:"Filter by city"}],rb:null,rbe:"{\\n \"success\": true,\\n \"data\": [\\n { ... }\\n ]\\n}",rf:[]},
{cat:"Master Data / District",m:"post",p:"/master-data/districts/list",s:"District list (DataTable pagination)",q:[],rb:"_DT_",rbe:"{\n \"success\": true,\n \"data\": {\n \"draw\": 1,\n \"recordsTotal\": 34,\n \"recordsFiltered\": 34,\n \"data\": [\n { \"id\": \"01HXYZ123456789012345678\", \"name\": \"...\" }\n ]\n }\n}",rf:[]},
{cat:"Master Data / District",m:"get",p:"/master-data/districts/:id",s:"Get district by ID",q:[{n:"id",t:"string",req:true,d:"District ID (26-char ULID)"}],rb:null,rbe:"{\n \"success\": true,\n \"data\": {\n \"id\": \"01HXYZ123456789012345678\",\n \"name\": \"Kabupaten Bandung\",\n \"province_id\": \"01HXYZ123456789012345678\",\n \"city_id\": \"01HXYZ123456789012345678\",\n \"merchant_id\": \"01HXYZ123456789012345678\"\n }\n}",rf:[]},
{cat:"Master Data / District",m:"post",p:"/master-data/districts/",s:"Create district",q:[],rb:"{\n \"name\": \"Kabupaten Bandung\",\n \"province_id\": \"01HXYZ123456789012345678\",\n \"city_id\": \"01HXYZ123456789012345678\"\n}",rbe:"{\n \"success\": true,\n \"data\": {\n \"id\": \"01HXYZ123456789012345678\",\n \"name\": \"Kabupaten Bandung\",\n \"province_id\": \"01HXYZ123456789012345678\",\n \"city_id\": \"01HXYZ123456789012345678\",\n \"merchant_id\": \"01HXYZ123456789012345678\"\n }\n}",rf:["name","province_id","city_id"]},
{cat:"Master Data / District",m:"put",p:"/master-data/districts/:id",s:"Update district",q:[{n:"id",t:"string",req:true,d:"District ID"}],rb:"{\n \"name\": \"Kabupaten Bandung\",\n \"province_id\": \"01HXYZ123456789012345678\",\n \"city_id\": \"01HXYZ123456789012345678\"\n}",rbe:"{\n \"success\": true,\n \"data\": {\n \"id\": \"01HXYZ123456789012345678\",\n \"name\": \"Kabupaten Bandung\",\n \"province_id\": \"01HXYZ123456789012345678\",\n \"city_id\": \"01HXYZ123456789012345678\",\n \"merchant_id\": \"01HXYZ123456789012345678\"\n }\n}",rf:["name","province_id","city_id"]},
{cat:"Master Data / District",m:"delete",p:"/master-data/districts/:id",s:"Delete district",q:[{n:"id",t:"string",req:true,d:"District ID"}],rb:null,rbe:"{\n \"success\": true,\n \"message\": \"district deleted\"\n}",rf:[]},
{cat:"Master Data / District",m:"get",p:"/master-data/districts/template",s:"Download district CSV template",q:[],rb:null,rbe:"<i>Returns CSV file (Content-Type: text/csv)</i>",rf:[]},
{cat:"Master Data / District",m:"post",p:"/master-data/districts/import",s:"Import districts from CSV",q:[],rb:"_MULTIPART_",rbe:"{\n \"success\": true,\n \"data\": {\n \"job_id\": \"job_abc123def456\",\n \"total_rows\": 100,\n \"imported\": 95,\n \"skipped\": 5,\n \"logs\": [\n {\n \"row\": 2,\n \"status\": \"skipped\",\n \"data\": \"Jawa Barat\",\n \"message\": \"duplicate\"\n }\n ],\n \"errors\": [],\n \"is_async\": false\n }\n}",rf:[]},
{cat:"Master Data / District",m:"post",p:"/master-data/districts/import/stop",s:"Stop district import job",q:[],rb:"{\n \"job_id\": \"job_abc123def456\"\n}",rbe:"{\n \"success\": true,\n \"message\": \"Job stopped\"\n}",rf:["job_id"]},
{cat:"Master Data / District",m:"get",p:"/master-data/districts/import/status/:jobId",s:"Check district import job status",q:[{n:"jobId",t:"string",req:true,d:"Async job ID"}],rb:null,rbe:"{\n \"success\": true,\n \"data\": {\n \"job\": {\n \"id\": \"job_abc123def456\",\n \"status\": \"completed\",\n \"total\": 100,\n \"imported\": 95,\n \"skipped\": 5\n },\n \"logs\": []\n }\n}",rf:[]},
{cat:"Master Data / Subdistrict",m:"get",p:"/master-data/subdistricts/",s:"Get all subdistricts",q:[{n:"name",t:"string",req:false,d:"Filter by name"},{n:"district_id",t:"string",req:false,d:"Filter by district"}],rb:null,rbe:"{\\n \"success\": true,\\n \"data\": [\\n { ... }\\n ]\\n}",rf:[]},
{cat:"Master Data / Subdistrict",m:"post",p:"/master-data/subdistricts/list",s:"Subdistrict list (DataTable pagination)",q:[],rb:"_DT_",rbe:"{\n \"success\": true,\n \"data\": {\n \"draw\": 1,\n \"recordsTotal\": 34,\n \"recordsFiltered\": 34,\n \"data\": [\n { \"id\": \"01HXYZ123456789012345678\", \"name\": \"...\" }\n ]\n }\n}",rf:[]},
{cat:"Master Data / Subdistrict",m:"get",p:"/master-data/subdistricts/:id",s:"Get subdistrict by ID",q:[{n:"id",t:"string",req:true,d:"Subdistrict ID (26-char ULID)"}],rb:null,rbe:"{\n \"success\": true,\n \"data\": {\n \"id\": \"01HXYZ123456789012345678\",\n \"name\": \"Kecamatan Bandung Wetan\",\n \"province_id\": \"01HXYZ123456789012345678\",\n \"city_id\": \"01HXYZ123456789012345678\",\n \"district_id\": \"01HXYZ123456789012345678\",\n \"merchant_id\": \"01HXYZ123456789012345678\"\n }\n}",rf:[]},
{cat:"Master Data / Subdistrict",m:"post",p:"/master-data/subdistricts/",s:"Create subdistrict",q:[],rb:"{\n \"name\": \"Kecamatan Bandung Wetan\",\n \"province_id\": \"01HXYZ123456789012345678\",\n \"city_id\": \"01HXYZ123456789012345678\",\n \"district_id\": \"01HXYZ123456789012345678\"\n}",rbe:"{\n \"success\": true,\n \"data\": {\n \"id\": \"01HXYZ123456789012345678\",\n \"name\": \"Kecamatan Bandung Wetan\",\n \"province_id\": \"01HXYZ123456789012345678\",\n \"city_id\": \"01HXYZ123456789012345678\",\n \"district_id\": \"01HXYZ123456789012345678\",\n \"merchant_id\": \"01HXYZ123456789012345678\"\n }\n}",rf:["name","province_id","city_id","district_id"]},
{cat:"Master Data / Subdistrict",m:"put",p:"/master-data/subdistricts/:id",s:"Update subdistrict",q:[{n:"id",t:"string",req:true,d:"Subdistrict ID"}],rb:"{\n \"name\": \"Kecamatan Bandung Wetan\",\n \"province_id\": \"01HXYZ123456789012345678\",\n \"city_id\": \"01HXYZ123456789012345678\",\n \"district_id\": \"01HXYZ123456789012345678\"\n}",rbe:"{\n \"success\": true,\n \"data\": {\n \"id\": \"01HXYZ123456789012345678\",\n \"name\": \"Kecamatan Bandung Wetan\",\n \"province_id\": \"01HXYZ123456789012345678\",\n \"city_id\": \"01HXYZ123456789012345678\",\n \"district_id\": \"01HXYZ123456789012345678\",\n \"merchant_id\": \"01HXYZ123456789012345678\"\n }\n}",rf:["name","province_id","city_id","district_id"]},
{cat:"Master Data / Subdistrict",m:"delete",p:"/master-data/subdistricts/:id",s:"Delete subdistrict",q:[{n:"id",t:"string",req:true,d:"Subdistrict ID"}],rb:null,rbe:"{\n \"success\": true,\n \"message\": \"subdistrict deleted\"\n}",rf:[]},
{cat:"Master Data / Subdistrict",m:"get",p:"/master-data/subdistricts/template",s:"Download subdistrict CSV template",q:[],rb:null,rbe:"<i>Returns CSV file (Content-Type: text/csv)</i>",rf:[]},
{cat:"Master Data / Subdistrict",m:"post",p:"/master-data/subdistricts/import",s:"Import subdistricts from CSV",q:[],rb:"_MULTIPART_",rbe:"{\n \"success\": true,\n \"data\": {\n \"job_id\": \"job_abc123def456\",\n \"total_rows\": 100,\n \"imported\": 95,\n \"skipped\": 5,\n \"logs\": [\n {\n \"row\": 2,\n \"status\": \"skipped\",\n \"data\": \"Jawa Barat\",\n \"message\": \"duplicate\"\n }\n ],\n \"errors\": [],\n \"is_async\": false\n }\n}",rf:[]},
{cat:"Master Data / Subdistrict",m:"post",p:"/master-data/subdistricts/import/stop",s:"Stop subdistrict import job",q:[],rb:"{\n \"job_id\": \"job_abc123def456\"\n}",rbe:"{\n \"success\": true,\n \"message\": \"Job stopped\"\n}",rf:["job_id"]},
{cat:"Master Data / Subdistrict",m:"get",p:"/master-data/subdistricts/import/status/:jobId",s:"Check subdistrict import job status",q:[{n:"jobId",t:"string",req:true,d:"Async job ID"}],rb:null,rbe:"{\n \"success\": true,\n \"data\": {\n \"job\": {\n \"id\": \"job_abc123def456\",\n \"status\": \"completed\",\n \"total\": 100,\n \"imported\": 95,\n \"skipped\": 5\n },\n \"logs\": []\n }\n}",rf:[]},
{cat:"Master Data / Postal Code",m:"get",p:"/master-data/postal-codes/",s:"Get all postal codes",q:[{n:"postal_code",t:"string",req:false,d:"Filter by postal code"},{n:"city_id",t:"string",req:false,d:"Filter by city"}],rb:null,rbe:"{\\n \"success\": true,\\n \"data\": [\\n { ... }\\n ]\\n}",rf:[]},
{cat:"Master Data / Postal Code",m:"post",p:"/master-data/postal-codes/list",s:"Postal Code list (DataTable pagination)",q:[],rb:"_DT_",rbe:"{\n \"success\": true,\n \"data\": {\n \"draw\": 1,\n \"recordsTotal\": 34,\n \"recordsFiltered\": 34,\n \"data\": [\n { \"id\": \"01HXYZ123456789012345678\", \"name\": \"...\" }\n ]\n }\n}",rf:[]},
{cat:"Master Data / Postal Code",m:"get",p:"/master-data/postal-codes/:id",s:"Get postal code by ID",q:[{n:"id",t:"string",req:true,d:"Postal Code ID (26-char ULID)"}],rb:null,rbe:"{\n \"success\": true,\n \"data\": {\n \"id\": \"01HXYZ123456789012345678\",\n \"postal_code\": \"01HXYZ123456789012345678\",\n \"province_id\": \"01HXYZ123456789012345678\",\n \"city_id\": \"01HXYZ123456789012345678\",\n \"district_id\": \"01HXYZ123456789012345678\",\n \"subdistrict_id\": \"01HXYZ123456789012345678\",\n \"merchant_id\": \"01HXYZ123456789012345678\"\n }\n}",rf:[]},
{cat:"Master Data / Postal Code",m:"post",p:"/master-data/postal-codes/",s:"Create postal code",q:[],rb:"{\n \"postal_code\": \"40111\",\n \"province_id\": \"01HXYZ123456789012345678\",\n \"city_id\": \"01HXYZ123456789012345678\",\n \"district_id\": \"01HXYZ123456789012345678\",\n \"subdistrict_id\": \"01HXYZ123456789012345678\"\n}",rbe:"{\n \"success\": true,\n \"data\": {\n \"id\": \"01HXYZ123456789012345678\",\n \"postal_code\": \"01HXYZ123456789012345678\",\n \"province_id\": \"01HXYZ123456789012345678\",\n \"city_id\": \"01HXYZ123456789012345678\",\n \"district_id\": \"01HXYZ123456789012345678\",\n \"subdistrict_id\": \"01HXYZ123456789012345678\",\n \"merchant_id\": \"01HXYZ123456789012345678\"\n }\n}",rf:["postal_code","province_id","city_id","district_id","subdistrict_id"]},
{cat:"Master Data / Postal Code",m:"put",p:"/master-data/postal-codes/:id",s:"Update postal code",q:[{n:"id",t:"string",req:true,d:"Postal Code ID"}],rb:"{\n \"postal_code\": \"40111\",\n \"province_id\": \"01HXYZ123456789012345678\",\n \"city_id\": \"01HXYZ123456789012345678\",\n \"district_id\": \"01HXYZ123456789012345678\",\n \"subdistrict_id\": \"01HXYZ123456789012345678\"\n}",rbe:"{\n \"success\": true,\n \"data\": {\n \"id\": \"01HXYZ123456789012345678\",\n \"postal_code\": \"01HXYZ123456789012345678\",\n \"province_id\": \"01HXYZ123456789012345678\",\n \"city_id\": \"01HXYZ123456789012345678\",\n \"district_id\": \"01HXYZ123456789012345678\",\n \"subdistrict_id\": \"01HXYZ123456789012345678\",\n \"merchant_id\": \"01HXYZ123456789012345678\"\n }\n}",rf:["postal_code","province_id","city_id","district_id","subdistrict_id"]},
{cat:"Master Data / Postal Code",m:"delete",p:"/master-data/postal-codes/:id",s:"Delete postal code",q:[{n:"id",t:"string",req:true,d:"Postal Code ID"}],rb:null,rbe:"{\n \"success\": true,\n \"message\": \"postal code deleted\"\n}",rf:[]},
{cat:"Master Data / Postal Code",m:"get",p:"/master-data/postal-codes/template",s:"Download postal code CSV template",q:[],rb:null,rbe:"<i>Returns CSV file (Content-Type: text/csv)</i>",rf:[]},
{cat:"Master Data / Postal Code",m:"post",p:"/master-data/postal-codes/import",s:"Import postal codes from CSV",q:[],rb:"_MULTIPART_",rbe:"{\n \"success\": true,\n \"data\": {\n \"job_id\": \"job_abc123def456\",\n \"total_rows\": 100,\n \"imported\": 95,\n \"skipped\": 5,\n \"logs\": [\n {\n \"row\": 2,\n \"status\": \"skipped\",\n \"data\": \"Jawa Barat\",\n \"message\": \"duplicate\"\n }\n ],\n \"errors\": [],\n \"is_async\": false\n }\n}",rf:[]},
{cat:"Master Data / Postal Code",m:"post",p:"/master-data/postal-codes/import/stop",s:"Stop postal code import job",q:[],rb:"{\n \"job_id\": \"job_abc123def456\"\n}",rbe:"{\n \"success\": true,\n \"message\": \"Job stopped\"\n}",rf:["job_id"]},
{cat:"Master Data / Postal Code",m:"get",p:"/master-data/postal-codes/import/status/:jobId",s:"Check postal code import job status",q:[{n:"jobId",t:"string",req:true,d:"Async job ID"}],rb:null,rbe:"{\n \"success\": true,\n \"data\": {\n \"job\": {\n \"id\": \"job_abc123def456\",\n \"status\": \"completed\",\n \"total\": 100,\n \"imported\": 95,\n \"skipped\": 5\n },\n \"logs\": []\n }\n}",rf:[]},
{cat:"Master Data / Cost Component",m:"get",p:"/master-data/cost-components/",s:"Get all cost components",q:[{n:"name",t:"string",req:false,d:"Filter by name"},{n:"code",t:"string",req:false,d:"Filter by code"},{n:"component_type",t:"integer",req:false,d:"Filter by type (0=Input, 1=Formula)"}],rb:null,rbe:"{\n \"success\": true,\n \"data\": [\n {\n \"id\": \"01HXYZ123456789012345678\",\n \"name\": \"Biaya Pengiriman\",\n \"code\": \"SHIP\",\n \"inc\": 1,\n \"value\": \"15000\",\n \"component_type\": 0,\n \"unit_type\": 0,\n \"merchant_id\": \"01HXYZ123456789012345678\"\n }\n ]\n}",rf:[]},
{cat:"Master Data / Cost Component",m:"post",p:"/master-data/cost-components/list",s:"Cost component list (DataTable)",q:[],rb:"_DT_",rbe:"{\n \"success\": true,\n \"data\": {\n \"draw\": 1,\n \"recordsTotal\": 34,\n \"recordsFiltered\": 34,\n \"data\": [\n { \"id\": \"01HXYZ123456789012345678\", \"name\": \"...\" }\n ]\n }\n}",rf:[]},
{cat:"Master Data / Cost Component",m:"get",p:"/master-data/cost-components/:id",s:"Get cost component by ID",q:[{n:"id",t:"string",req:true,d:"Cost component ID"}],rb:null,rbe:"{\n \"success\": true,\n \"data\": {\n \"id\": \"01HXYZ123456789012345678\",\n \"name\": \"Biaya Pengiriman\",\n \"code\": \"SHIP\",\n \"inc\": 1,\n \"value\": \"15000\",\n \"component_type\": 0,\n \"unit_type\": 0,\n \"merchant_id\": \"01HXYZ123456789012345678\"\n }\n}",rf:[]},
{cat:"Master Data / Cost Component",m:"post",p:"/master-data/cost-components/",s:"Create cost component",q:[],rb:"{\n \"name\": \"Biaya Pengiriman\",\n \"code\": \"SHIP\",\n \"value\": \"15000\",\n \"component_type\": 0,\n \"unit_type\": 0\n}",rbe:"{\n \"success\": true,\n \"data\": {\n \"id\": \"01HXYZ123456789012345678\",\n \"name\": \"Biaya Pengiriman\",\n \"code\": \"SHIP\",\n \"inc\": 1,\n \"value\": \"15000\",\n \"component_type\": 0,\n \"unit_type\": 0,\n \"merchant_id\": \"01HXYZ123456789012345678\"\n }\n}",rf:["name","code","value"]},
{cat:"Master Data / Cost Component",m:"put",p:"/master-data/cost-components/:id",s:"Update cost component",q:[{n:"id",t:"string",req:true,d:"Cost component ID"}],rb:"{\n \"name\": \"Biaya Pengiriman Updated\",\n \"code\": \"SHIP\",\n \"value\": \"20000\",\n \"component_type\": 0,\n \"unit_type\": 0\n}",rbe:"{\n \"success\": true,\n \"data\": {\n \"id\": \"01HXYZ123456789012345678\",\n \"name\": \"Biaya Pengiriman Updated\",\n \"code\": \"SHIP\",\n \"inc\": 1,\n \"value\": \"20000\",\n \"component_type\": 0,\n \"unit_type\": 0,\n \"merchant_id\": \"01HXYZ123456789012345678\"\n }\n}",rf:["name","code","value"]},
{cat:"Master Data / Cost Component",m:"delete",p:"/master-data/cost-components/:id",s:"Delete cost component",q:[{n:"id",t:"string",req:true,d:"Cost component ID"}],rb:null,rbe:"{\n \"success\": true,\n \"message\": \"cost component deleted\"\n}",rf:[]},
{cat:"Master Data / Cost Component",m:"post",p:"/master-data/cost-components/sortup",s:"Move cost component up in sort order",q:[],rb:"{\n \"id\": \"01HXYZ123456789012345678\"\n}",rbe:"{\n \"success\": true,\n \"message\": \"Sorting Up Success\"\n}",rf:["id"]},
{cat:"Master Data / Cost Component",m:"post",p:"/master-data/cost-components/sortdown",s:"Move cost component down in sort order",q:[],rb:"{\n \"id\": \"01HXYZ123456789012345678\"\n}",rbe:"{\n \"success\": true,\n \"message\": \"Sorting Down Success\"\n}",rf:["id"]},
{cat:"Basic Pricing",m:"get",p:"/basic-pricings/",s:"Get all basic pricings",q:[{n:"province_source_id",t:"string",req:false,d:"Source province ID"},{n:"city_source_id",t:"string",req:false,d:"Source city ID"},{n:"package_type_id",t:"string",req:false,d:"Package type ID"},{n:"moda_id",t:"string",req:false,d:"Transport mode ID"}],rb:null,rbe:"{\\n \"success\": true,\\n \"data\": [\\n { ... }\\n ]\\n}",rf:[]},
{cat:"Basic Pricing",m:"post",p:"/basic-pricings/list",s:"Basic pricing list (DataTable)",q:[],rb:"_DT_",rbe:"{\n \"success\": true,\n \"data\": {\n \"draw\": 1,\n \"recordsTotal\": 34,\n \"recordsFiltered\": 34,\n \"data\": [\n { \"id\": \"01HXYZ123456789012345678\", \"name\": \"...\" }\n ]\n }\n}",rf:[]},
{cat:"Basic Pricing",m:"get",p:"/basic-pricings/:id",s:"Get basic pricing by ID",q:[{n:"id",t:"string",req:true,d:"Basic pricing ID"}],rb:null,rbe:"{\n \"success\": true,\n \"data\": {\n \"id\": \"01HXYZ123456789012345678\",\n \"province_source_id\": \"01HXYZ123456789012345678\",\n \"city_source_id\": \"01HXYZ123456789012345678\",\n \"district_source_id\": \"01HXYZ123456789012345678\",\n \"subdistrict_source_id\": \"01HXYZ123456789012345678\",\n \"postal_code_source_id\": \"01HXYZ123456789012345678\",\n \"province_destination_id\": \"01HXYZ123456789012345678\",\n \"city_destination_id\": \"01HXYZ123456789012345678\",\n \"district_destination_id\": \"01HXYZ123456789012345678\",\n \"subdistrict_destination_id\": \"01HXYZ123456789012345678\",\n \"postal_code_destination_id\": \"01HXYZ123456789012345678\",\n \"package_type_id\": \"01HXYZ123456789012345678\",\n \"moda_id\": \"01HXYZ123456789012345678\",\n \"lead_time\": \"2-3 days\",\n \"minimum_weight\": 1.0,\n \"merchant_id\": \"01HXYZ123456789012345678\",\n \"components\": [\n {\n \"id\": \"01HXYZ123456789012345678\",\n \"cost_component_id\": \"01HXYZ123456789012345678\",\n \"value\": \"15000\"\n }\n ]\n }\n}",rf:[]},
{cat:"Basic Pricing",m:"post",p:"/basic-pricings/match",s:"Match basic pricing by ID",q:[],rb:"{\n \"id\": \"01HXYZ123456789012345678\"\n}",rbe:"{\n \"success\": true,\n \"data\": {\n \"id\": \"01HXYZ123456789012345678\",\n \"components\": [\n {\n \"id\": \"01HXYZ123456789012345678\",\n \"cost_component_id\": \"01HXYZ123456789012345678\",\n \"value\": \"15000\"\n }\n ]\n }\n}",rf:["id"]},
{cat:"Basic Pricing",m:"post",p:"/basic-pricings/",s:"Create basic pricing",q:[],rb:"{\n \"province_source_id\": \"01HXYZ123456789012345678\",\n \"city_source_id\": \"01HXYZ123456789012345678\",\n \"district_source_id\": \"01HXYZ123456789012345678\",\n \"subdistrict_source_id\": \"01HXYZ123456789012345678\",\n \"postal_code_source_id\": \"01HXYZ123456789012345678\",\n \"province_destination_id\": \"01HXYZ123456789012345678\",\n \"city_destination_id\": \"01HXYZ123456789012345678\",\n \"district_destination_id\": \"01HXYZ123456789012345678\",\n \"subdistrict_destination_id\": \"01HXYZ123456789012345678\",\n \"postal_code_destination_id\": \"01HXYZ123456789012345678\",\n \"package_type_id\": \"01HXYZ123456789012345678\",\n \"moda_id\": \"01HXYZ123456789012345678\",\n \"lead_time\": \"2-3 days\",\n \"minimum_weight\": 1.0,\n \"components\": [\n {\n \"cost_component_id\": \"01HXYZ123456789012345678\",\n \"value\": \"15000\"\n }\n ]\n}",rbe:"{\n \"success\": true,\n \"data\": {\n \"id\": \"01HXYZ123456789012345678\",\n \"province_source_id\": \"01HXYZ123456789012345678\",\n \"city_source_id\": \"01HXYZ123456789012345678\",\n \"district_source_id\": \"01HXYZ123456789012345678\",\n \"subdistrict_source_id\": \"01HXYZ123456789012345678\",\n \"postal_code_source_id\": \"01HXYZ123456789012345678\",\n \"province_destination_id\": \"01HXYZ123456789012345678\",\n \"city_destination_id\": \"01HXYZ123456789012345678\",\n \"district_destination_id\": \"01HXYZ123456789012345678\",\n \"subdistrict_destination_id\": \"01HXYZ123456789012345678\",\n \"postal_code_destination_id\": \"01HXYZ123456789012345678\",\n \"package_type_id\": \"01HXYZ123456789012345678\",\n \"moda_id\": \"01HXYZ123456789012345678\",\n \"lead_time\": \"2-3 days\",\n \"minimum_weight\": 1.0,\n \"merchant_id\": \"01HXYZ123456789012345678\",\n \"components\": [\n {\n \"id\": \"01HXYZ123456789012345678\",\n \"cost_component_id\": \"01HXYZ123456789012345678\",\n \"value\": \"15000\"\n }\n ]\n }\n}",rf:["name"]},
{cat:"Basic Pricing",m:"put",p:"/basic-pricings/:id",s:"Update basic pricing",q:[{n:"id",t:"string",req:true,d:"Basic pricing ID"}],rb:"{\n \"province_source_id\": \"01HXYZ123456789012345678\",\n \"city_source_id\": \"01HXYZ123456789012345678\",\n \"district_source_id\": \"01HXYZ123456789012345678\",\n \"subdistrict_source_id\": \"01HXYZ123456789012345678\",\n \"postal_code_source_id\": \"01HXYZ123456789012345678\",\n \"province_destination_id\": \"01HXYZ123456789012345678\",\n \"city_destination_id\": \"01HXYZ123456789012345678\",\n \"district_destination_id\": \"01HXYZ123456789012345678\",\n \"subdistrict_destination_id\": \"01HXYZ123456789012345678\",\n \"postal_code_destination_id\": \"01HXYZ123456789012345678\",\n \"package_type_id\": \"01HXYZ123456789012345678\",\n \"moda_id\": \"01HXYZ123456789012345678\",\n \"lead_time\": \"2-3 days\",\n \"minimum_weight\": 1.0,\n \"components\": [\n {\n \"cost_component_id\": \"01HXYZ123456789012345678\",\n \"value\": \"15000\"\n }\n ]\n}",rbe:"{\n \"success\": true,\n \"data\": {\n \"id\": \"01HXYZ123456789012345678\",\n \"province_source_id\": \"01HXYZ123456789012345678\",\n \"city_source_id\": \"01HXYZ123456789012345678\",\n \"district_source_id\": \"01HXYZ123456789012345678\",\n \"subdistrict_source_id\": \"01HXYZ123456789012345678\",\n \"postal_code_source_id\": \"01HXYZ123456789012345678\",\n \"province_destination_id\": \"01HXYZ123456789012345678\",\n \"city_destination_id\": \"01HXYZ123456789012345678\",\n \"district_destination_id\": \"01HXYZ123456789012345678\",\n \"subdistrict_destination_id\": \"01HXYZ123456789012345678\",\n \"postal_code_destination_id\": \"01HXYZ123456789012345678\",\n \"package_type_id\": \"01HXYZ123456789012345678\",\n \"moda_id\": \"01HXYZ123456789012345678\",\n \"lead_time\": \"2-3 days\",\n \"minimum_weight\": 1.0,\n \"merchant_id\": \"01HXYZ123456789012345678\",\n \"components\": [\n {\n \"id\": \"01HXYZ123456789012345678\",\n \"cost_component_id\": \"01HXYZ123456789012345678\",\n \"value\": \"15000\"\n }\n ]\n }\n}",rf:["name"]},
{cat:"Basic Pricing",m:"delete",p:"/basic-pricings/:id",s:"Delete basic pricing",q:[{n:"id",t:"string",req:true,d:"Basic pricing ID"}],rb:null,rbe:"{\n \"success\": true,\n \"message\": \"basic pricing deleted\"\n}",rf:[]},
{cat:"Master Data / Package Type",m:"get",p:"/master-data/package-types/",s:"Get all package types",q:[{n:"id",t:"string",req:false,d:"Filter by ID"},{n:"name",t:"string",req:false,d:"Filter by name"},{n:"merchant_id",t:"string",req:false,d:"Filter by merchant"}],rb:null,rbe:"{\n \"success\": true,\n \"data\": [\n {\n \"id\": \"01HXYZ123456789012345678\",\n \"name\": \"Reguler\",\n \"merchant_id\": \"01HXYZ123456789012345678\"\n }\n ]\n}",rf:[]},
{cat:"Master Data / Package Type",m:"post",p:"/master-data/package-types/list",s:"Package type list (DataTable)",q:[],rb:"_DT_",rbe:"{\n \"success\": true,\n \"data\": {\n \"draw\": 1,\n \"recordsTotal\": 10,\n \"recordsFiltered\": 10,\n \"data\": [\n { \"id\": \"01HXYZ123456789012345678\", \"name\": \"Reguler\" }\n ]\n }\n}",rf:[]},
{cat:"Master Data / Package Type",m:"get",p:"/master-data/package-types/:id",s:"Get package type by ID",q:[{n:"id",t:"string",req:true,d:"Package type ID"}],rb:null,rbe:"{\n \"success\": true,\n \"data\": {\n \"id\": \"01HXYZ123456789012345678\",\n \"name\": \"Reguler\",\n \"merchant_id\": \"01HXYZ123456789012345678\"\n }\n}",rf:[]},
{cat:"Master Data / Package Type",m:"post",p:"/master-data/package-types/",s:"Create package type",q:[],rb:"{\n \"name\": \"Reguler\"\n}",rbe:"{\n \"success\": true,\n \"data\": {\n \"id\": \"01HXYZ123456789012345678\",\n \"name\": \"Reguler\",\n \"merchant_id\": \"01HXYZ123456789012345678\"\n }\n}",rf:["name"]},
{cat:"Master Data / Package Type",m:"put",p:"/master-data/package-types/:id",s:"Update package type",q:[{n:"id",t:"string",req:true,d:"Package type ID"}],rb:"{\n \"name\": \"Express\"\n}",rbe:"{\n \"success\": true,\n \"data\": {\n \"id\": \"01HXYZ123456789012345678\",\n \"name\": \"Express\",\n \"merchant_id\": \"01HXYZ123456789012345678\"\n }\n}",rf:["name"]},
{cat:"Master Data / Package Type",m:"delete",p:"/master-data/package-types/:id",s:"Delete package type",q:[{n:"id",t:"string",req:true,d:"Package type ID"}],rb:null,rbe:"{\n \"success\": true,\n \"message\": \"package type deleted\"\n}",rf:[]},
{cat:"Master Data / Moda",m:"get",p:"/master-data/modas/",s:"Get all modas",q:[{n:"id",t:"string",req:false,d:"Filter by ID"},{n:"name",t:"string",req:false,d:"Filter by name"},{n:"merchant_id",t:"string",req:false,d:"Filter by merchant"}],rb:null,rbe:"{\n \"success\": true,\n \"data\": [\n {\n \"id\": \"01HXYZ123456789012345678\",\n \"name\": \"Darat\",\n \"merchant_id\": \"01HXYZ123456789012345678\"\n }\n ]\n}",rf:[]},
{cat:"Master Data / Moda",m:"post",p:"/master-data/modas/list",s:"Moda list (DataTable)",q:[],rb:"_DT_",rbe:"{\n \"success\": true,\n \"data\": {\n \"draw\": 1,\n \"recordsTotal\": 5,\n \"recordsFiltered\": 5,\n \"data\": [\n { \"id\": \"01HXYZ123456789012345678\", \"name\": \"Darat\" }\n ]\n }\n}",rf:[]},
{cat:"Master Data / Moda",m:"get",p:"/master-data/modas/:id",s:"Get moda by ID",q:[{n:"id",t:"string",req:true,d:"Moda ID"}],rb:null,rbe:"{\n \"success\": true,\n \"data\": {\n \"id\": \"01HXYZ123456789012345678\",\n \"name\": \"Darat\",\n \"merchant_id\": \"01HXYZ123456789012345678\"\n }\n}",rf:[]},
{cat:"Master Data / Moda",m:"post",p:"/master-data/modas/",s:"Create moda",q:[],rb:"{\n \"name\": \"Darat\"\n}",rbe:"{\n \"success\": true,\n \"data\": {\n \"id\": \"01HXYZ123456789012345678\",\n \"name\": \"Darat\",\n \"merchant_id\": \"01HXYZ123456789012345678\"\n }\n}",rf:["name"]},
{cat:"Master Data / Moda",m:"put",p:"/master-data/modas/:id",s:"Update moda",q:[{n:"id",t:"string",req:true,d:"Moda ID"}],rb:"{\n \"name\": \"Udara\"\n}",rbe:"{\n \"success\": true,\n \"data\": {\n \"id\": \"01HXYZ123456789012345678\",\n \"name\": \"Udara\",\n \"merchant_id\": \"01HXYZ123456789012345678\"\n }\n}",rf:["name"]},
{cat:"Master Data / Moda",m:"delete",p:"/master-data/modas/:id",s:"Delete moda",q:[{n:"id",t:"string",req:true,d:"Moda ID"}],rb:null,rbe:"{\n \"success\": true,\n \"message\": \"moda deleted\"\n}",rf:[]},
{cat:"Activity Log",m:"get",p:"/activity-logs/",s:"Get all activity logs",q:[{n:"table_name",t:"string",req:false,d:"Filter by table name"},{n:"record_id",t:"string",req:false,d:"Filter by record ID"},{n:"action",t:"string",req:false,d:"Filter by action (CREATE, UPDATE, DELETE, REVERT)"},{n:"user_id",t:"string",req:false,d:"Filter by user ID"},{n:"date_from",t:"string",req:false,d:"Filter from date"},{n:"date_to",t:"string",req:false,d:"Filter to date"}],rb:null,rbe:"{\n \"success\": true,\n \"data\": [\n {\n \"id\": \"01HXYZ123456789012345678\",\n \"table_name\": \"province\",\n \"record_id\": \"01HXYZ123456789012345678\",\n \"action\": \"DELETE\",\n \"old_data\": \"{...}\",\n \"new_data\": null,\n \"cascade_data\": \"[{...}]\",\n \"user_id\": \"01HXYZ123456789012345678\",\n \"user_name\": \"Admin Utama\",\n \"created_on\": \"2026-09-05 10:30:00\",\n \"cascade_count\": 1102\n }\n ]\n}",rf:[]},
{cat:"Activity Log",m:"post",p:"/activity-logs/list",s:"Activity log list (DataTable)",q:[],rb:"_DT_",rbe:"{\n \"success\": true,\n \"data\": {\n \"draw\": 1,\n \"recordsTotal\": 42,\n \"recordsFiltered\": 42,\n \"data\": []\n }\n}",rf:[]},
{cat:"Activity Log",m:"get",p:"/activity-logs/:id",s:"Get activity log by ID",q:[{n:"id",t:"string",req:true,d:"Activity log ID"}],rb:null,rbe:"{\n \"success\": true,\n \"data\": {\n \"id\": \"01HXYZ123456789012345678\",\n \"table_name\": \"province\",\n \"record_id\": \"01HXYZ123456789012345678\",\n \"action\": \"DELETE\",\n \"old_data\": \"{...}\",\n \"cascade_data\": \"[{...}]\",\n \"user_id\": \"01HXYZ123456789012345678\",\n \"user_name\": \"Admin Utama\",\n \"created_on\": \"2026-09-05 10:30:00\",\n \"cascade_count\": 1102\n }\n}",rf:[]},
{cat:"Activity Log",m:"post",p:"/activity-logs/:id/revert",s:"Revert activity log action",q:[{n:"id",t:"string",req:true,d:"Activity log ID"}],rb:null,rbe:"{\n \"success\": true,\n \"message\": \"action reverted successfully\"\n}",rf:["id"]}
];
function fmtMethod(m){return m.toUpperCase()}
function methodColor(m){return{get:"var(--get)",post:"var(--post)",put:"var(--put)",delete:"var(--delete)"}[m]||"var(--text2)"}
function fmtPath(p){return p.replace(/\{([^}]+)\}/g,'<span class="param">:$1</span>')}
function render(){
const q=document.getElementById("search").value.toLowerCase();
const cats={};let order=[];
E.forEach((e,i)=>{
if(q&&!e.p.toLowerCase().includes(q)&&!e.s.toLowerCase().includes(q)&&!e.cat.toLowerCase().includes(q))return;
if(!cats[e.cat]){cats[e.cat]=[];order.push(e.cat)}
cats[e.cat].push({...e,idx:i});
});
let html="";
const stats=document.getElementById("stats");
let counts={};E.forEach(e=>{counts[e.m]=(counts[e.m]||0)+1});
stats.innerHTML='<div class="stat"><strong>'+E.length+'</strong>Total Endpoints</div>'+
'<div class="stat"><strong>'+(counts.get||0)+'</strong><span style="color:var(--get)">GET</span></div>'+
'<div class="stat"><strong>'+(counts.post||0)+'</strong><span style="color:var(--post)">POST</span></div>'+
'<div class="stat"><strong>'+(counts.put||0)+'</strong><span style="color:var(--put)">PUT</span></div>'+
'<div class="stat"><strong>'+(counts.delete||0)+'</strong><span style="color:var(--delete)">DELETE</span></div>';
order.forEach(cat=>{
html+='<div class="cat-section"><div class="cat-title">'+esc(cat)+'</div><div class="endpoints">';
cats[cat].forEach(e=>{
let body="";
// Params
if(e.q&&e.q.length){
body+='<div class="section-label">Parameters</div><div class="params"><table><tr><th>Name</th><th>Type</th><th>Required</th><th>Description</th></tr>';
e.q.forEach(p=>{
body+='<tr><td><code>'+esc(p.n)+'</code></td><td>'+esc(p.t)+'</td><td>'+(p.req?'<span class="badge-r">required</span>':'<span class="badge-o">optional</span>')+'</td><td>'+esc(p.d)+'</td></tr>';
});
body+='</table></div>';
}
// Request body
if(e.rb){
body+='<div class="section-label">Request Body</div>';
if(e.rf&&e.rf.length){
body+='<div class="req-fields"><table><tr><th>Name</th><th>Type</th><th>Required</th><th>Description</th></tr>';
e.rf.forEach(f=>{
body+='<tr><td><code>'+esc(f)+'</code></td><td>string</td><td><span class="required-val">required</span></td><td></td></tr>';
});
body+='</table></div>';
}
if(e.rb==="_DT_"){
body+='<pre>'+esc(DT_BODY)+'</pre>';
}else if(e.rb==="_MULTIPART_"){
body+='<pre>Content-Type: multipart/form-data\nfield: file (CSV file upload)</pre>';
}else{
body+='<pre>'+esc(e.rb)+'</pre>';
}
}
// Response
body+='<div class="section-label">Response (200)</div>';
if(e.rbe){
body+='<pre>'+esc(e.rbe)+'</pre>';
}else{
body+='<pre>{\n "success": true,\n "data": { ... }\n}</pre>';
}
html+='<div class="ep" id="ep-'+e.idx+'"><div class="ep-head" onclick="document.getElementById(\'ep-'+e.idx+'\').classList.toggle(\'open\')"><span class="method '+e.m+'" style="background:'+methodColor(e.m)+'">'+fmtMethod(e.m)+'</span><span class="ep-path">'+fmtPath(esc(e.p))+'</span><span class="ep-summary">'+esc(e.s)+'</span></div><div class="ep-body">'+body+'</div></div>';
});
html+='</div></div>';
});
document.getElementById("content").innerHTML=html;
// nav
let navHtml='';
order.forEach(cat=>{
navHtml+='<div class="cat">'+esc(cat)+'<span class="count">'+cats[cat].length+'</span></div>';
cats[cat].forEach(e=>{
navHtml+='<a href="#ep-'+e.idx+'"><span class="dot" style="background:'+methodColor(e.m)+'"></span>'+fmtMethod(e.m)+' '+esc(e.p.split('/').pop()||'/')+'</a>';
});
});
document.getElementById("nav").innerHTML=navHtml;
}
function esc(s){return String(s).replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}
document.getElementById("search").addEventListener("input",render);
const DT_BODY="{\n \"draw\": 1,\n \"start\": 0,\n \"length\": 10,\n \"search\": { \"value\": \"\" },\n \"order\": [{ \"column\": 0, \"dir\": \"asc\" }],\n \"columns\": [{\n \"data\": \"name\",\n \"searchable\": true,\n \"orderable\": true,\n \"search\": { \"value\": \"\" }\n }]\n}";
render();
</script>
</body>
</html>