API integrasi untuk sistem eksternal

Gunakan API ini untuk menghubungkan Kliniktech Cloud dengan sistem billing lain, CRM, NOC dashboard, BI/reporting, helpdesk eksternal, middleware, atau automasi internal.

Base URL: https://apps.ion.net.id/apiVersion: external/v1Auth: Bearer TokenFormat: JSON

Overview

Endpoint eksternal berada di prefix /api/external/v1. Endpoint ini tenant-scoped, artinya token hanya dapat membaca atau menulis data tenant yang tercantum pada ability token.

Kontrak awal API menyediakan data pelanggan, paket, invoice, tiket, OLT, dan ONU. Operasi tulis dibatasi untuk membuat pelanggan dan tiket agar integrasi awal tetap aman.
Jika tenant ditandai sebagai Mode Demo Aman, operasi tulis/berisiko dapat ditolak dengan response 403 dan kode demo_guard_blocked. Gunakan tenant normal untuk integrasi produksi.

Akses baca

Token read dapat membaca data operasional tanpa mengubah database.

Akses tulis

Token read_write dapat membaca data, membuat pelanggan, dan membuat tiket dari sistem eksternal.

Autentikasi

Semua request external API wajib mengirim header:

Authorization: Bearer <TOKEN_API_INTEGRASI>
Accept: application/json
Content-Type: application/json

Token dibuat dari panel Netadmin/API internal oleh admin tenant. Token hanya ditampilkan satu kali saat dibuat, jadi simpan di secret manager sistem eksternal.

curl https://apps.ion.net.id/api/external/v1/health \
  -H "Authorization: Bearer 1|TOKEN..." \
  -H "Accept: application/json"

Manajemen Token Integrasi

Endpoint ini dipakai oleh admin tenant yang sudah login ke aplikasi. Di UI, admin dapat mengelola token dari Pengaturan → API Integrasi. Jangan dipakai oleh sistem eksternal untuk membuat token sendiri.

Daftar token bersifat tenant-wide: admin tenant dapat melihat dan revoke token integrasi milik tenant aktif, termasuk token yang dibuat admin lain.

MethodEndpointKeterangan
GET/api/integrations/api-tokensList token integrasi milik user admin untuk tenant aktif.
POST/api/integrations/api-tokensBuat token baru. Body: { "name": "CRM", "access": "read_write", "expires_at": "2026-12-31T23:59:59+08:00" }
DELETE/api/integrations/api-tokens/{id}Cabut token integrasi.
curl -X POST https://apps.ion.net.id/api/integrations/api-tokens \
  -H "Authorization: Bearer <TOKEN_LOGIN_ADMIN>" \
  -H "Content-Type: application/json" \
  -d '{"name":"CRM Production","access":"read_write"}'

Filter & Pagination

Endpoint list memakai pagination Laravel. Parameter umum:

  • per_page: jumlah data per halaman, maksimum 100.
  • page: halaman yang diminta.
  • search: pencarian teks sesuai endpoint.
  • updated_since: ambil data yang berubah sejak waktu ISO 8601 tertentu.
GET /api/external/v1/customers?search=budi&status=active&per_page=25&page=1
GET /api/external/v1/invoices?status=unpaid&updated_since=2026-06-01T00:00:00+08:00

Daftar Endpoint External v1

MethodEndpointAksesKeterangan
GET/api/external/v1/healthreadCek token, tenant, dan status API.
GET/api/external/v1/mereadInfo tenant, user pemilik token, dan ability token.
GET/api/external/v1/customersreadList pelanggan. Filter: search, status, updated_since.
POST/api/external/v1/customerswriteBuat pelanggan baru dari sistem eksternal. Untuk pelanggan DHCP/Static, MAC valid dapat dikirim sebagai AA:BB:CC:DD:EE:FF, AABB.CCDD.EEFF, atau AABBCCDDEEFF; server menyimpan sebagai format kolon uppercase.
GET/api/external/v1/customers/{id}readDetail pelanggan, termasuk invoice dan tiket terbaru.
GET/api/external/v1/packagesreadList paket layanan. Filter: search, is_active.
GET/api/external/v1/invoicesreadList invoice. Filter: search, status, customer_id, updated_since.
GET/api/external/v1/invoices/{id}readDetail invoice.
GET/api/external/v1/ticketsreadList tiket. Filter: search, status, priority, customer_id.
POST/api/external/v1/ticketswriteBuat tiket dari CRM/helpdesk/NOC eksternal.
GET/api/external/v1/tickets/{id}readDetail tiket.
GET/api/external/v1/oltsreadList OLT. Filter: search, status.
GET/api/external/v1/onusreadList ONU aktif. Filter: search, status, customer_id, olt_id.

Endpoint Admin Ticketing

Endpoint Netadmin POST /api/tickets/resolve-all menyelesaikan tiket aktif yang sudah memenuhi syarat proses dan dokumentasi penanganan. Request menerima field resolution untuk catatan resolusi massal.

Reopen tiket selesai hanya boleh dilakukan oleh Administrator atau Super Admin. Jika user teknisi mencoba mengubah tiket resolved/closed kembali ke open atau inprogress, API mengembalikan validasi jelas agar reopen dilakukan lewat admin.

Jika tidak ada tiket yang memenuhi syarat, endpoint mengembalikan 422 dengan pesan Tidak ada tiket yang diselesaikan, detail resolution_requirements, dan instruksi agar operator memproses tiket atau menambahkan catatan, komentar, lampiran/foto, atau check-in lapangan.

Endpoint Admin Absensi

Endpoint ini dipakai menu Netadmin Absensi untuk check-in/check-out dengan GPS dan selfie, multi Home Base per staff, jadwal fleksibel, gaji pokok/THP, pengajuan izin/cuti/sakit/koreksi, kuota cuti, notifikasi approval WA/Telegram, payroll Absensi, audit trail, work log jadwal/tiket, approval lembur, export CSV, dan pengaturan jam kerja tenant.

Semua endpoint memakai Bearer token user tenant. Baca data membutuhkan permission schedules.view, sedangkan simpan setting, check-in/out staff lain, dan approval lembur membutuhkan schedules.manage.
Jika tabel absensi belum tersedia, endpoint data mengembalikan 503 attendance_schema_missing dengan nama tabel yang hilang dan instruksi menjalankan migration backend.
MethodEndpointKeterangan
GET/api/attendance/dashboardKPI hadir, work log aktif, lembur pending, menit approved, dan nominal periode.
GET/api/attendanceDaftar absensi karyawan dengan filter tanggal dan user.
POST/api/attendance/clock-in / /api/attendance/clock-outCheck-in/check-out dengan latitude, longitude, accuracy, selfie base64, dan catatan opsional. Khusus check-in wajib mengirim selfie_source= camera dari kamera langsung; upload galeri/file ditolak. Jika radius aktif, lokasi di luar radius ditolak; jika akurasi GPS lebih buruk dari 50 meter, absensi juga ditolak.
GET/api/attendance/mobile/status / /api/attendance/mobile/historyEndpoint portal /absensi untuk status hari ini, roster, setting bukti, status device, KPI bulan berjalan, request terbaru, skor risiko, dan riwayat pribadi staff.
POST/api/attendance/mobile/device / /api/attendance/mobile/clock-in / /api/attendance/mobile/clock-outRegistrasi device mobile dan check-in/out staff dengan kamera langsung, GPS, device_uid, fingerprint_hash, camera_meta, mock GPS flag, dan pesan error anti-fraud yang spesifik.
GET/api/attendance/mobile/calendar / /api/attendance/mobile/payroll / /api/attendance/mobile/approvals / /api/attendance/mobile/incentivesKalender shift mobile, ringkasan payroll pribadi, estimasi/status bonus teknisi, dan daftar approval pending untuk admin/koordinator. Jika user tidak berhak approve, response validasi menjelaskan permission yang kurang.
POST/api/attendance/mobile/offline-batchMengirim ulang antrian absensi offline maksimal 10 item dengan offline_id agar retry tidak membuat duplikasi.
POST/api/attendance/mobile/site-code/verify / /api/attendance/mobile/site-work/start / /api/attendance/mobile/site-work/finishVerifikasi QR/NFC lokasi, mulai visit/site work, dan selesai visit/site work dengan GPS, foto, catatan, serta work log lembur otomatis.
GET/api/attendance/mobile/tracking/statusStatus GPS Tracking mobile: setting aktif, interval, akurasi maksimal, visit aktif, titik terakhir, dan status stale.
POST/api/attendance/mobile/tracking/pointSimpan titik GPS Tracking untuk visit/site work aktif. Payload minimal latitude, longitude, accuracy, captured_at, device_uid, dan work_log_id bila ada.
GET/api/attendance/mobile/tracking/historyAmbil riwayat titik GPS Tracking milik user login, dapat difilter dengan work_log_id.
GET/api/attendance/mobile/technician/tasksData portal teknisi: jadwal hari ini, tiket aktif, dan work log aktif untuk user login.
GET/api/attendance/mobile/technician/ticketsKPI dan riwayat tiket pribadi teknisi untuk `/absensi`, dapat difilter dengan period, status, from, to, q, dan limit.
POST/api/attendance/mobile/tickets/{ticketId}/process / /progress / /reschedule / /resolveAksi tiket dari `/absensi`: proses tiket, tambah progress dengan foto opsional, jadwalkan ulang tiket aktif, dan selesaikan tiket dengan catatan jelas, GPS opsional, serta validasi agar tiket tidak ditutup tanpa dokumentasi.
GET POST PUT/api/attendance/mobile/tickets/{ticketId}/psb-checklistChecklist PSB mobile: baca draft, autosave foto wajib yang sudah di-resize dari HP, simpan material terpakai, pilih ONT/SN dari Request Barang terkait, dan blokir resolve jika checklist belum lengkap.
GET/api/attendance/mobile/money-requests / /api/attendance/mobile/inventory/requestsRiwayat Request Uang dan Request Barang milik teknisi dari `/absensi`.
POST/api/attendance/mobile/money-requestsBuat Request Uang operasional/reimbursement/bensin/pembelian/advance dengan bukti/struk base64 wajib maksimal 5 MB.
GET/api/attendance/mobile/inventory/catalogKatalog Request Barang mobile teknisi. Daftar Gudang Asal (source_locations) memakai mapping resmi Home Base → Gudang bila Home Base teknisi sudah dipetakan; jika belum, fallback ke pencocokan otomatis nama wilayah. Query source_location_id memfilter item agar hanya berisi stok tersedia di Gudang Asal/POP tersebut, sekaligus mengembalikan pilihan referensi tiket/jadwal user login.
POST/api/home-bases/{id}/inventory-locationsSet mapping Gudang Asal resmi untuk sebuah Home Base (butuh permission homebase.manage). Body inventory_location_ids[] (integer, tipe gudang/POP). Kirim array kosong untuk menghapus mapping dan kembali ke pencocokan otomatis. Field inventory_location_ids juga diterima oleh POST/PUT /api/home-bases.
POST/api/attendance/mobile/inventory/requestsBuat Request Barang multi-item dari `/absensi` memakai modul Gudang existing. Body memakai items[], satu Gudang Asal, dan satu Referensi. Backend memvalidasi Gudang Asal sesuai Home Base, item tidak duplikat, quantity tersedia di gudang tersebut, serta referensi tiket/jadwal memang terkait teknisi.
POST/api/attendance/mobile/requestsBuat pengajuan izin/cuti/sakit/koreksi dari portal mobile dengan source=mobile.
GET/api/attendance/work-logsWork log teknisi dari jadwal/tiket, termasuk kategori regular, overtime, emergency, atau on-call.
GET/api/attendance/overtimeDaftar pengajuan lembur dan status approval.
GET/api/attendance/requestsDaftar pengajuan izin, cuti, sakit, dan koreksi absensi. Jika migration belum dijalankan, respons 503 attendance_requests_schema_missing.
POST/api/attendance/requestsBuat pengajuan izin/cuti/sakit berdasarkan periode, atau koreksi jam check-in/check-out tanggal tertentu.
POST/api/attendance/requests/{attendanceRequest}/approveSetujui pengajuan dan terapkan status/jam koreksi ke data absensi.
POST/api/attendance/requests/{attendanceRequest}/rejectTolak pengajuan dengan alasan wajib.
GET/api/attendance/leave-balancesDaftar saldo cuti tahunan, terpakai, penyesuaian, dan sisa cuti per karyawan/tahun.
PUT/api/attendance/leave-balancesUbah saldo cuti tahunan atau penyesuaian cuti karyawan.
GET/api/attendance/payroll-reportRekap hadir, telat per hari/jam/menit, menit telat, telat dianggap tidak masuk, izin, cuti, sakit, lembur approved, kategori potongan lain, dan nominal payroll.
GET/api/attendance/audit-logsAudit trail Absensi: pengajuan dibuat, approval/reject, koreksi, notifikasi, dan update kuota cuti.
GET/api/attendance/export-payrollExport CSV payroll Absensi sesuai filter periode.
GET/api/attendance/staff-policiesDaftar policy Absensi/Payroll per staff: status Staff Absensi, Home Base, jadwal, mode potongan telat, batas telat dianggap tidak masuk, gaji, tunjangan, dan kategori potongan lain.
PUT/api/attendance/staff-policiesSimpan policy multi Home Base, toggle Staff Absensi/Payroll, status kerja, jadwal, gaji pokok, tunjangan, mode potongan telat, batas telat dianggap tidak masuk, kategori potongan lain, dan catatan staff.
GET/api/attendance/devices / /api/attendance/shifts / /api/attendance/rosters / /api/attendance/approval-flowsData full suite NetAdmin untuk Device & Fraud, Shift/Roster, dan Approval Flow. Jika migration full suite belum dijalankan, respons 503 attendance_full_suite_schema_missing.
POST/api/attendance/devices/{id}/status / /api/attendance/shifts / /api/attendance/rosters / /api/attendance/approval-flowsSimpan status trusted/blocked device, template shift, assignment roster, dan approval flow berjenjang.
GET/api/attendance/incentives/settings / /api/attendance/incentives/reviewBaca aturan Insentif Teknisi tenant, draft bonus dari tiket/jadwal/work log, status review, payout, dan riwayat.
PUT/api/attendance/incentives/settingsSimpan aturan bonus/punishment, nominal, satuan, pembagian, hold pencairan, syarat, deskripsi, dan status aktif/nonaktif per tenant.
POST/api/attendance/incentives/review / /api/attendance/incentives/payoutReview draft insentif menjadi pending/approved/rejected dan tandai payout yang sudah dibayar. Pesan validasi menjelaskan item, nominal, status, atau permission yang salah.
POST/api/attendance/overtime/{approval}/approveSetujui menit lembur dan hitung nominal payroll.
POST/api/attendance/overtime/{approval}/rejectTolak pengajuan lembur dengan alasan wajib.
GET/api/attendance/settingsBaca hari kerja, jam kerja, cutoff retail, tarif, pembulatan, keyword emergency, kewajiban GPS/selfie/liveness, titik absensi, radius, batas akurasi GPS, device trusted, mock GPS, skor minimal liveness, serta branding/theme `/absensi`.
PUT/api/attendance/settingsSimpan pengaturan absensi tenant termasuk radius kantor/home base, liveness, dan tampilan `/absensi`: mode theme, judul brand, subtitle, judul hero, warna aksen, warna hero, dan toggle ilustrasi.
GET/api/attendance/exportExport rekap lembur CSV.

OLT Device FiberHome

Modul OLT Device mendukung vendor fiberhome untuk FiberHome GPON AN5516/AN5506. Form Netadmin memakai endpoint OLT SNMP existing: GET /api/olt-snmp/profiles, GET /api/olt-snmp, POST /api/olt-snmp, dan PUT /api/olts/{id}/snmp.

Field vendor_hint menerima fiberhome. FiberHome membutuhkan community SNMP v2c dan credential Telnet untuk polling detail ONU.
Migration menambahkan kolom olts.snmp_oid_base untuk menyimpan auto-detect OID base: fh, hw, atau none. Command polling: php artisan olt:poll --vendor=fiberhome --type=status dan php artisan olt:poll --vendor=all --type=all.

Endpoint Admin Email Setting Akun

Endpoint ini dipakai Netadmin untuk konfigurasi email client per user pada menu Akun Saya. Incoming memakai IMAP/POP3 untuk menarik email ke Inbox lokal, outgoing memakai SMTP akun untuk reply email. Email asli tetap disimpan di server; delete Inbox/Outbox hanya menghapus salinan lokal.

Membutuhkan tabel external_email_accounts dan ekstensi PHP IMAP untuk sync incoming.
MethodEndpointKeterangan
GET/api/auth/email-settingsMelihat Email Setting akun aktif beserta default Virtualmin yang dimask.
PUT/api/auth/email-settingsMenyimpan IMAP/POP3 dan SMTP akun. Password disimpan terenkripsi; leave_on_server dipaksa aktif.
POST/api/auth/email-settings/test-incomingTest koneksi incoming dan sync maksimal 1 email sebagai verifikasi.
POST/api/auth/email-settings/syncSinkron email masuk dari IMAP/POP3 ke communication_messages channel email.
POST/api/communications/{id}/reply-emailReply email masuk memakai SMTP dari Email Setting akun aktif, lalu mencatat hasil di Outbox.

Endpoint Admin Sesi Login Akun

Endpoint ini dipakai Netadmin pada menu Akun Saya > Keamanan untuk mengatur Login Multi Device, batas maksimal device aktif, daftar sesi NetAdmin, dan pencabutan sesi/device lain.

Membutuhkan permission account.security. Jika migration kolom multi-device di tabel users belum dijalankan, penyimpanan setting akan mengembalikan pesan jelas agar migration backend dijalankan terlebih dahulu.
MethodEndpointKeterangan
GET/api/auth/sessionsMelihat setting Login Multi Device dan daftar sesi/device NetAdmin akun aktif.
PUT/api/auth/sessions/settingsMenyimpan multi_device_enabled dan multi_device_limit. Saat nonaktif, sesi lain dicabut agar hanya device saat ini yang aktif.
DELETE/api/auth/sessions/{tokenId}Mencabut sesi/device tertentu milik akun aktif. Device yang sedang dipakai tidak bisa dicabut dari daftar ini.
POST/api/auth/sessions/revoke-othersMencabut semua sesi/device lain dan mempertahankan sesi yang sedang dipakai.

Endpoint Admin Penjualan

Endpoint ini dipakai Netadmin untuk modul Penjualan. Modul bersifat tenant-scoped dan membutuhkan permission sales.* serta module tenant sales aktif.

Alur utama: Lead/Prospek → Penawaran → Sales Order → Invoice / Request Stok / Jadwal Teknisi → Fulfillment → Laporan Penjualan.
Jika response 503 menyebut migration belum dijalankan, jalankan migration backend setelah approval production. Jika response 403, aktifkan modul Sales di Platform Admin atau periksa permission role user.
MethodEndpointPermissionKeterangan
GET/api/sales/dashboardsales.viewKPI lead, quote, order, omzet bulan ini, margin, dan data terbaru.
GET/api/sales/optionssales.viewDaftar status, tipe item, dan tipe order untuk UI.
GET/api/sales/leadssales.viewList lead/prospek. Filter: search, status, customer_id, per_page.
POST/api/sales/leadssales.createBuat lead pelanggan atau non-pelanggan.
PUT/api/sales/leads/{lead}sales.updateEdit lead dan status follow-up.
POST/api/sales/leads/{lead}/quotesales.createBuat penawaran dari lead.
GET/api/sales/quotessales.viewList penawaran.
POST/api/sales/quotessales.createBuat penawaran dengan item jasa/barang.
PUT/api/sales/quotes/{quote}sales.updateEdit penawaran yang belum diterima/converted.
POST/api/sales/quotes/{quote}/ordersales.createConvert penawaran menjadi sales order.
GET/api/sales/orderssales.viewList sales order.
POST/api/sales/orderssales.createBuat sales order langsung untuk pelanggan atau non-pelanggan one-time.
POST/api/sales/orders/{order}/confirmsales.approveKonfirmasi sales order.
POST/api/sales/orders/{order}/invoicesales.invoiceBuat invoice tipe sales dari order.
POST/api/sales/orders/{order}/stock-outsales.fulfillMembuat request stok keluar reference_type=sales_order dan tetap menunggu approval Gudang.
POST/api/sales/orders/{order}/schedulesales.fulfillMembuat jadwal teknisi dari order jasa/lapangan.
POST/api/sales/orders/{order}/fulfillsales.fulfillMenandai order selesai.
POST/api/sales/orders/{order}/cancelsales.fulfillMembatalkan order dengan alasan opsional.
{
  "title": "Penjualan ONU + Jasa Tarik Kabel FO",
  "customer_type": "non_customer",
  "company_name": "PT Contoh Integrasi",
  "contact_name": "Bapak Andi",
  "phone": "081234567890",
  "order_type": "fo_installation",
  "items": [
    {"item_type": "service", "name": "Jasa tarik kabel FO", "quantity": 1, "unit": "paket", "unit_price": 2500000},
    {"item_type": "goods", "inventory_item_id": 12, "name": "ONU", "quantity": 10, "unit": "unit", "unit_price": 180000}
  ]
}

Endpoint Admin Data Keuangan

Endpoint ini dipakai Netadmin untuk modul Data Keuangan tenant. Akses lihat memakai permission invoices.view, sedangkan input akun, kategori, dan transaksi memakai invoices.manage. Endpoint pelunasan invoice dapat mengirim finance_account_id agar payment record direkonsiliasi ke akun Kas/Bank.

Jika response menyebut tabel finance_accounts, finance_categories, atau finance_transactions belum ada, jalankan migration backend sebelum modul digunakan.
MethodEndpointKeterangan
GET/api/finance/summaryRingkasan periode: pendapatan invoice lunas, income manual, pengeluaran, laba rugi, piutang, akun, kategori, dan transaksi terbaru.
GET/api/finance/receivablesDaftar piutang invoice dari tagihan berstatus unpaid/overdue.
GET/api/finance/payablesDaftar hutang supplier/operasional. Membutuhkan tabel finance_payables.
POST/api/finance/payablesTambah hutang baru dengan judul, supplier opsional, kategori pengeluaran, nominal, jatuh tempo, dan catatan.
PUT/api/finance/payables/{id}Edit hutang yang belum lunas.
DELETE/api/finance/payables/{id}Hapus hutang yang belum lunas.
POST/api/finance/payables/{id}/payTandai hutang lunas dan buat transaksi pengeluaran dari akun Kas/Bank yang dipilih.
GET/api/finance/accountsDaftar akun Kas/Bank/Payment Gateway tenant.
POST/api/finance/accountsTambah akun kas/bank manual dengan nama, tipe, kode, dan saldo awal.
GET/api/finance/accounts/{id}Detail akun Kas/Bank beserta saldo berjalan.
PUT/api/finance/accounts/{id}Edit akun Kas/Bank. Nama akun harus unik dalam tenant.
DELETE/api/finance/accounts/{id}Hapus akun jika belum dipakai; jika sudah memiliki transaksi, akun dinonaktifkan agar riwayat saldo tetap aman.
GET/api/finance/categoriesDaftar kategori income dan pengeluaran.
POST/api/finance/categoriesTambah kategori income atau pengeluaran.
GET/api/finance/categories/{id}Detail kategori keuangan.
PUT/api/finance/categories/{id}Edit kategori income/pengeluaran.
DELETE/api/finance/categories/{id}Hapus kategori manual jika belum dipakai; kategori sistem atau sudah dipakai akan dinonaktifkan.
GET/api/finance/transactionsDaftar transaksi finance dengan filter from, to, type, account_id, category_id, source, search, dan pagination per_page default 20.
POST/api/finance/transactionsCatat income manual, pengeluaran, atau transfer antar akun. Untuk transfer gunakan type=transfer, account_id sebagai akun asal, dan destination_account_id sebagai akun tujuan. Untuk upload bukti, kirim multipart receipt_file JPG/PNG/WEBP/PDF maksimal 5 MB.
GET/api/finance/transactions/{id}Detail transaksi finance. Transaksi otomatis tetap bisa dibuka untuk audit.
PUT/api/finance/transactions/{id}Edit transaksi manual. Transaksi otomatis dari invoice, stok, atau transfer akan ditolak agar saldo aman.
DELETE/api/finance/transactions/{id}Hapus transaksi manual. Transaksi otomatis ditolak dan operator diminta membuat transaksi koreksi.
GET/api/finance/transactions/{id}/receiptDownload bukti transfer/nota transaksi finance. Mengembalikan pesan jelas jika file belum ada atau migration kolom bukti belum dijalankan.
POST/api/customers/{id}/email-accountGenerate mailbox Virtualmin untuk pelanggan existing, simpan email ke data pelanggan, dan kembalikan password awal jika mailbox baru dibuat. Error menjelaskan masalah permission, domain, format email, koneksi, login, atau respon Virtualmin.
POST/api/customers/import/sisbro/previewPreview import pelanggan dari CSV Sisbro delimiter ;. Mengabaikan baris kosong, memvalidasi No Pelanggan, paket, telepon, username PPPoE, dan memberi solusi error per baris.
POST/api/customers/import/sisbro/commitCommit import pelanggan Sisbro setelah preview bersih. Default aman untuk migrasi: tanpa provisioning dan tanpa invoice awal kecuali opsi dikirim eksplisit.
POST/api/invoices/{id}/payCatat pelunasan invoice. Kirim finance_account_id opsional untuk membuat transaksi income otomatis di Data Keuangan.
POST/api/customers/{customer}/invoices/{invoice}/payCatat pelunasan invoice dari detail pelanggan dengan opsi rekonsiliasi finance_account_id.
GET/api/paypoint/bootstrapBootstrap portal mobile /paypoint: user kasir, tenant, home base, akun Kas POP, dan summary transaksi hari ini. Membutuhkan paypoint.view.
GET/api/paypoint/search?q=...Cari pelanggan atau invoice untuk kasir POP berdasarkan kode, nama, HP, email, atau nomor invoice. Mengembalikan tagihan unpaid/overdue.
POST/api/paypoint/invoices/{invoice}/cashTerima pembayaran cash dari POP. Body: finance_account_id, cash_received, payment_ref opsional, dan notes. Memakai InvoicePaymentService agar invoice lunas, payment record, Data Keuangan, masa aktif, dan unblock isolir konsisten.
GET/api/paypoint/transactionsDaftar transaksi Paypoint hari ini untuk dashboard/closing kasir POP.
POST/api/inventory/{id}/stock-inCatat stok masuk. Kirim finance_paid=true, finance_account_id, unit_cost, dan quantity untuk mencatat pembayaran pembelian stok sebagai pengeluaran Perangkat / Gudang.
GET/api/office-assetsDaftar Aset Kantor dengan filter status, condition, category, search, dan per_page. Membutuhkan office_assets.view.
POST/api/office-assetsTambah aset kantor. Field utama: name wajib, asset_code opsional auto-generate, kategori, lokasi, PIC, status, kondisi, harga beli, garansi, dokumen, dan catatan. Error validasi menyebut field yang perlu diperbaiki.
POST/api/office-assets/{id}/moveCatat mutasi lokasi/PIC aset kantor. location wajib agar audit jelas; PIC harus user tenant aktif.
POST/api/office-assets/{id}/maintenanceCatat maintenance aset kantor dengan kondisi akhir, biaya, catatan wajib, dan jadwal maintenance berikutnya.
POST/api/office-assets/{id}/auditCatat opname aset kantor: kondisi aktual, lokasi aktual, PIC aktual, dan catatan selisih bila ada.

Endpoint Request Uang

Endpoint ini dipakai Netadmin untuk request dana operasional, reimbursement/claim uang pribadi staff, uang bensin, pembelian barang, dan kasbon/advance. Staff dapat membuat dan melihat request sendiri; Administrator/Super Admin dapat melihat semua request dan melakukan approval/pembayaran.

Jika response menyebut tabel money_requests belum ada, jalankan migration backend sebelum modul digunakan. Form request wajib memakai multipart dan field receipt_file.
MethodEndpointKeterangan
GET/api/money-requests/pending-countJumlah Request Uang yang perlu perhatian untuk badge sidebar NetAdmin. Admin: pending + disetujui; staff: request pending milik sendiri.
GET/api/money-requestsDaftar Request Uang dengan filter status, type, q, mine, dan pagination per_page default 20.
POST/api/money-requestsBuat Request Uang baru. Wajib kirim multipart type, title, amount, description, dan receipt_file JPG/PNG/WEBP/PDF maksimal 5 MB.
GET/api/money-requests/{id}Detail Request Uang. Staff non-admin hanya bisa membuka request miliknya sendiri.
GET/api/money-requests/{id}/receiptDownload bukti/nota Request Uang.
POST/api/money-requests/{id}/approveSetujui request pending. Hanya Administrator/Super Admin dengan permission finance manage.
POST/api/money-requests/{id}/rejectTolak request pending dengan approval_notes wajib agar staff mendapat alasan jelas.
POST/api/money-requests/{id}/payCatat pembayaran request yang sudah disetujui. Kirim finance_account_id; sistem membuat transaksi pengeluaran di Data Keuangan dengan sumber money_request.
POST/api/money-requests/{id}/cancelBatalkan request pending oleh pemilik request atau admin.

Endpoint Internal Provisioning Tenant

Endpoint ini dipakai Platform Admin untuk merencanakan provisioning tenant multi-database: database tenant, DNS Cloudflare, mailbox Virtualmin, dan storage prefix.

Versi awal ini bersifat preview/draft. Endpoint tidak membuat database production, tidak mengubah DNS, dan tidak membuat mailbox sampai side effect diaktifkan dengan approval eksplisit.

Gunakan endpoint ini untuk pilot tenant baru terlebih dahulu. Jangan migrasi tenant existing sebelum dynamic connection, migration tenant, backup, dan runbook failover selesai diuji.
MethodEndpointKeterangan
GET/api/platform/provisioning/readinessMelihat readiness checklist global untuk dry-run/pilot provisioning: tabel metadata, DB admin credential, Cloudflare, Virtualmin, storage, dan backup.
GET/api/platform/provisioning/credentialsMelihat status credential provisioning yang sudah dimask, termasuk hasil test terakhir.
PUT/api/platform/provisioning/credentialsMenyimpan credential provisioning terenkripsi. Production provisioning tetap terkunci.
POST/api/platform/provisioning/credentials/test/{provider}Test credential read-only untuk tenant_db, cloudflare, virtualmin, storage, atau backup.
GET/api/platform/tenants/{tenant}/provisioningMelihat metadata database, domain, mailbox, dan draft job provisioning tenant.
POST/api/platform/tenants/{tenant}/provisioning/previewMembuat preview rencana provisioning tanpa menyimpan job dan tanpa side effect production. Tenant non-master default memakai mailbox root domain kliniktech.com, misalnya demo@kliniktech.com.
POST/api/platform/tenants/{tenant}/provisioning/draftMenyimpan draft job provisioning. Draft belum menjalankan Cloudflare, Virtualmin, create DB, atau migration tenant.
POST/api/platform/tenants/{tenant}/provisioning/subscriber-domain/provisionProvision DNS subscriber dan mailbox Virtualmin dengan frasa PROVISION SUBSCRIBER DOMAIN. Domain tenant baru aktif hanya bila DNS berhasil.
POST/api/platform/tenants/{tenant}/provisioning/subscriber-domain/regenerate-previewGenerate kandidat domain subscriber otomatis dari slug tenant, cek konflik dan job provisioning berjalan, lalu kembalikan preview aman sebelum apply. Tidak membuat DNS atau mengubah domain.
POST/api/platform/tenants/{tenant}/provisioning/subscriber-domain/change-previewPreview ganti domain subscriber: domain lama, domain baru, konflik tenant lain, status TXT/A/CNAME custom domain, dan kandidat cleanup DNS lama.
POST/api/platform/tenants/{tenant}/provisioning/subscriber-domain/change-applyAktifkan domain baru dengan frasa CHANGE SUBSCRIBER DOMAIN. DNS lama tidak dihapus otomatis agar rollback/manual check tetap aman.
POST/api/platform/tenants/{tenant}/provisioning/subscriber-domain/cleanup-oldHapus record Cloudflare domain lama setelah domain baru verified, memakai frasa DELETE OLD SUBSCRIBER DNS. Endpoint menolak jika domain lama masih primary atau bukan Cloudflare managed.
POST/api/platform/tenants/{tenant}/provisioning/pilot-db/previewPreview DB-only pilot untuk tenant demo/pilot, termasuk rollback plan. Tidak membuat database/user.
POST/api/platform/tenants/{tenant}/provisioning/pilot-db/runMenjalankan DB-only pilot setelah frasa RUN DB PILOT. Membuat database/user dummy dan metadata; tidak membuat DNS/mailbox.
POST/api/platform/tenants/{tenant}/provisioning/pilot-db/rollbackRollback DB-only pilot setelah frasa ROLLBACK DB PILOT. Hanya untuk metadata pilot.
POST/api/platform/tenants/{tenant}/provisioning/tenant-db/testTest dynamic connection tenant DB read-only dari metadata. Tidak menjalankan migration.
GET/api/platform/tenants/{tenant}/provisioning/tenant-db/read-sampleRead-sample shared DB vs tenant DB pilot untuk users/customers/invoices/tickets. Tidak menulis data dan belum cutover production.
GET/api/platform/tenants/{tenant}/provisioning/tenant-db/usersPilot routing read-only users. Membaca dari tenant DB hanya jika flag use_tenant_db_read aktif dan schema sudah migrated.
GET/api/platform/tenants/{tenant}/provisioning/tenant-db/customersPilot routing read-only customers. Belum cutover modul pelanggan production.
GET/api/tenant-db-pilot/tenants/{tenant}/customersSmoke route khusus token pilot dengan ability pilot:tenant-db-login dan tenant:{id}.
GET/api/platform/tenants/{tenant}/provisioning/tenant-db/invoicesPilot routing read-only invoices. Belum cutover modul Billing production.
GET/api/platform/tenants/{tenant}/provisioning/tenant-db/ticketsPilot routing read-only tickets. Belum cutover modul Ticket production.
GET/api/platform/tenants/{tenant}/provisioning/tenant-db/demo-flowRead-only validasi demo flow DEMO-CUST-001DEMO-INV-001DEMO-TICK-001 dari tenant DB pilot.
GET/api/platform/tenants/{tenant}/provisioning/tenant-db/pilot-healthRead-only ringkasan pilot health: flag, schema, koneksi, count tabel, demo flow, dan token pilot aktif.
GET/api/platform/tenants/{tenant}/provisioning/tenant-db/shadow-readRead-only parity shared DB vs tenant DB untuk users/customers/invoices/tickets. Tidak mengubah routing production.
GET/api/platform/tenants/{tenant}/provisioning/tenant-db/reconciliationRead-only reconciliation report dengan severity per tabel dan total missing/extra/mismatch. Extra row pilot DEMO-* yang valid tampil sebagai accepted_pilot_extra; extra lain tetap blocking_extra_key_count.
GET/api/platform/tenants/{tenant}/provisioning/tenant-db/cutover-gateRead-only gate report untuk memblokir/menandai readiness cutover production. Tidak menjalankan cutover; gate hijau pilot tetap membutuhkan approval production eksplisit.
GET/api/platform/tenants/{tenant}/provisioning/tenant-db/readiness-snapshotRead-only evidence snapshot HA/MTDB yang menggabungkan pilot health, reconciliation, write-plan, dan cutover gate. Tidak menjalankan cutover; production_cutover.allowed tetap false. Response menyertakan evidence.fingerprint, evidence.fingerprint_command, evidence.summary_command, evidence.status_command, evidence.commands_command, evidence.verify_command, evidence.verify_summary_command, evidence.verify_status_command, evidence.decision_command, dan evidence.operator_action_command; tenant master kliniktech dijaga sebagai shared_db_master.
GET/api/platform/tenants/{tenant}/provisioning/tenant-db/readiness-snapshot/verify?fingerprint={sha256}Read-only verifikasi fingerprint evidence terhadap readiness snapshot terbaru. Mengembalikan matched=true/false, decision, dan operator_action; tetap tidak menjalankan cutover, dan production_cutover_allowed=false.
GET/api/platform/tenants/{tenant}/provisioning/tenant-db/production-statusRead-only status post-cutover tenant DB: cutover status, approval, module routing, feature flags, dan rollback readiness. Tidak menulis perubahan.
POST/api/platform/tenants/{tenant}/provisioning/tenant-db/approve-productionMencatat approval production setelah fingerprint readiness valid. Wajib field fingerprint, approver, maintenance_window, rollback_owner, monitoring_owner, reason, dan frasa APPROVE TENANT DB PRODUCTION. Belum menjalankan cutover.
POST/api/platform/tenants/{tenant}/provisioning/tenant-db/cutover-productionMenjalankan guarded cutover production setelah approval ID dan fingerprint cocok. Wajib frasa CUTOVER TENANT DB PRODUCTION. Tenant master kliniktech tetap diblokir.
POST/api/platform/tenants/{tenant}/provisioning/tenant-db/rollback-productionRollback feature flag production cutover memakai approval_id. Mode dry_run=true tidak menulis perubahan; rollback aktual wajib frasa ROLLBACK TENANT DB PRODUCTION.
GET/api/platform/tenants/{tenant}/provisioning/tenant-db/module-read/{module}Controlled module read pilot untuk users, customers, invoices, atau tickets. Default fallback shared DB.
GET/api/platform/tenants/{tenant}/provisioning/tenant-db/write-planRead-only dry-run planner untuk jalur write customers/invoices/tickets sebelum dual-write pilot. Jalur komentar/lampiran tiket baru siap jika schema tenant memiliki ticket_comments dan ticket_attachments.
POST/api/platform/tenants/{tenant}/provisioning/tenant-db/dual-write/runRun dual-write pilot terbatas untuk row demo DEMO-* di tenant DB. Wajib frasa RUN TENANT DB DUAL WRITE PILOT.
POST/api/platform/tenants/{tenant}/provisioning/tenant-db/dual-write/rollbackRollback snapshot dual-write pilot. Wajib frasa ROLLBACK TENANT DB DUAL WRITE PILOT.
POST/api/platform/tenants/{tenant}/provisioning/tenant-db/demo-seedSeed data demo customer/invoice/ticket ke tenant DB pilot dengan frasa SEED TENANT DB DEMO DATA.
POST/api/platform/tenants/{tenant}/provisioning/tenant-db/demo-seed/rollbackRollback row demo DEMO-* dari tenant DB pilot dengan frasa ROLLBACK TENANT DB DEMO DATA.
GET/api/tenant-db-pilot/tenants/{tenant}/invoicesSmoke route invoices khusus token pilot.
GET/api/tenant-db-pilot/tenants/{tenant}/ticketsSmoke route tickets khusus token pilot.
GET/api/tenant-db-pilot/tenants/{tenant}/demo-flowSmoke route demo flow khusus token pilot.
POST/api/platform/tenants/{tenant}/provisioning/tenant-db/auth-checkAuth-check read-only terhadap tenant DB pilot. Memverifikasi hash password tanpa membuat token/session dan tanpa mengganti /auth/login.
POST/api/platform/tenants/{tenant}/provisioning/tenant-db/pilot-loginPilot login internal dengan frasa PILOT TENANT DB LOGIN. Membuat token pilot tanpa mengubah login production atau menghapus token lain.
GET/api/platform/tenants/{tenant}/provisioning/tenant-db/pilot-token/statusStatus token pilot untuk email user tenant. Read-only.
POST/api/platform/tenants/{tenant}/provisioning/tenant-db/pilot-token/revokeRevoke token pilot dengan frasa REVOKE TENANT DB PILOT TOKEN. Hanya token pilot yang dihapus.
GET/api/platform/tenants/{tenant}/provisioning/tenant-schema/previewPreview migration schema minimal tenant pilot.
POST/api/platform/tenants/{tenant}/provisioning/tenant-schema/runRun migration schema minimal dengan frasa RUN TENANT SCHEMA. Tidak memindahkan data production.
POST/api/platform/tenants/{tenant}/provisioning/data-copy/dry-runDry-run copy data minimal users/customers/invoices/tickets. Menghitung mapping dan collision tanpa menulis data tenant DB.
POST/api/platform/tenants/{tenant}/provisioning/data-copy/runCopy data pilot setelah frasa COPY TENANT DATA PILOT. Menulis data minimal ke tenant DB pilot jika dry-run collision 0.
POST/api/platform/tenants/{tenant}/provisioning/data-copy/rollbackRollback data pilot setelah frasa ROLLBACK TENANT DATA PILOT. Menghapus row hasil copy pilot terakhir.

Endpoint Internal WhatsApp Bot

Endpoint ini dipakai panel Netadmin tenant yang sudah login, bukan token external API. Konfigurasi bersifat tenant-scoped.

Untuk provider Wablas, WatZap, BalesOtomatis.id, dan Pancake, settings.base_url dapat diisi manual oleh tenant. WatZap memakai default https://api.watzap.id/v1 jika Base URL kosong.

Provider WatZap memakai wa_token sebagai API Key dan endpoint kirim POST /send_message dengan payload api_key, number, dan message.

Provider Pancake memakai wa_token sebagai Page Access Token, wa_secret_key sebagai Page ID, dan endpoint https://pages.fm/api/public_api/v1. Test/kirim Pancake memakai Conversation ID, bukan nomor HP biasa.

Default pengiriman WhatsApp Bot adalah settings.max_messages_per_minute = 3 dan settings.message_delay_seconds = 10. Gunakan nilai 0 jika tenant ingin tanpa batas atau tanpa jeda.

WhatsApp Bot mendukung banyak akun per provider melalui settings.accounts. Pengiriman memakai routing otomatis: satu akun aktif memakai akun tersebut, sedangkan beberapa akun aktif dikirim bergantian round-robin. Pesan gagal tidak dialihkan otomatis ke akun lain dan dapat dikirim ulang manual dari Outbox.

Endpoint POST /api/wabot/test menerima account_id opsional agar panel dapat mengetes koneksi dan kirim pesan memakai akun provider tertentu, bukan test global provider aktif. Untuk Wablas, field is_group=true dapat dipakai bersama Group ID sebagai phone untuk test kirim ke grup.

Endpoint POST /api/wabot/sync-status mengecek report realtime Wablas untuk pesan pending tanpa retry. Jika API Wablas sedang membalas error sementara, endpoint tetap mengembalikan HTTP 200 dengan warning=true agar polling halaman tidak terganggu dan sistem bisa mencoba lagi otomatis.

Endpoint POST /api/wabot/sync-device-status mengecek status device Wablas langsung dari API device info agar panel tidak hanya bergantung pada webhook device.

Semua provider menampilkan webhook_url untuk pesan masuk. Tempel URL ini di dashboard provider agar pesan inbound masuk ke bot Kliniktech.

Statistik dan log WhatsApp Bot membaca communication_messages channel WhatsApp agar Inbox/Outbox dari webhook, notifikasi, test kirim, provider, dan akun pengirim tetap konsisten. Sinkron status tidak melakukan retry pesan gagal.

MethodEndpointKeterangan
GET/api/wabot/configAmbil provider aktif, status credential, webhook URL inbound, akun provider, dan setting WhatsApp Bot tenant.
PUT/api/wabot/configSimpan provider, nomor pengirim, credential, Base URL, akun provider, limit per akun, routing load balance, fallback, cooldown, dan opsi auto-register webhook Wablas.
POST/api/wabot/testTest koneksi atau kirim pesan test. Isi account_id untuk mengetes akun provider tertentu; untuk Wablas, isi is_group=true dan Group ID pada phone untuk test grup.
POST/api/wabot/sync-statusCek report realtime Wablas untuk Outbox pending yang punya Message ID. Tidak mengirim ulang pesan; provider error sementara dikembalikan sebagai warning.
POST/api/wabot/sync-device-statusCek status device Wablas dari API provider dan simpan status terakhir per akun untuk panel NetAdmin.
POST/api/wabot/inbound/{tenant_slug}Webhook inbound untuk provider WhatsApp yang meneruskan pesan masuk ke bot tenant.
Jika Base URL atau credential kosong, response test/kirim akan menjelaskan field yang wajib diisi, misalnya Base URL Wablas wajib diisi atau Page Access Token dan Page ID Pancake wajib diisi.

Endpoint Internal Mitra

Endpoint ini dipakai panel Netadmin yang sudah login dengan permission Mitra. Detail Mitra dapat menampilkan pelanggan internet terhubung, invoice, pembayaran, tiket, kontrak, dan dokumen.

Paket khusus Mitra ditandai dari modul Paket Internet melalui field is_partner_package. Saat membuat pelanggan dari Mitra, sistem mewajibkan paket khusus Mitra agar harga layanan partner tidak bercampur dengan paket pelanggan umum.

MethodEndpointKeterangan
GET/api/mitra/{id}Detail Mitra, termasuk layanan internet, invoice, pembayaran, tiket, kontrak, dan dokumen.
POST/api/mitra/{id}/customers/linkTautkan pelanggan existing ke Mitra. Body: { "customer_id": 123 }.
POST/api/mitra/{id}/customersBuat pelanggan dari data Mitra. Body minimal: phone, package_id, service_type, dan nas_key.
DELETE/api/mitra/{id}/customers/{customerId}Lepas tautan pelanggan dari Mitra tanpa menghapus pelanggan, invoice, atau tiket.

Endpoint Internal Inventory Supplier

Endpoint ini dipakai panel Netadmin tenant yang sudah login dengan permission inventory. Import barang supplier selalu memakai alur preview dulu agar data katalog tidak langsung masuk tanpa pengecekan operator.

Request Barang multi-item memakai header request dan baris item. Status workflow: draft, pending, deferred, approved, rejected, processing, completed, dan cancelled. Saat diproses, sistem membuat mutasi inventaris per item.

File yang didukung: CSV, TXT, XLSX, dan PDF. PDF diparse best-effort sehingga hasil preview wajib dicek dan dikoreksi sebelum import.

Import membuat atau memperbarui master barang, lalu menautkan harga beli ke supplier. Import tidak menambah stok gudang; stok tetap masuk melalui flow Stok Masuk.

MethodEndpointKeterangan
GET/api/inventory/requests/pending-countJumlah Request Barang yang perlu perhatian untuk badge sidebar NetAdmin. Admin gudang: pending/ditangguhkan/disetujui + mutasi legacy pending; staff: request pending/ditangguhkan milik sendiri.
GET/api/inventory/requestsDaftar Request Barang multi-item dengan detail pemohon, gudang, item, dan riwayat approval. Filter: status, type, per_page.
GET/api/inventory/requests/{id}Detail Request Barang untuk modal/drawer clickable.
POST/api/inventory/requestsBuat Request Barang. Body wajib: type, gudang sesuai tipe, dan items[] berisi item_id, quantity, serta catatan item opsional.
PUT/api/inventory/requests/{id}Edit request status draft, pending, atau deferred.
POST/api/inventory/requests/{id}/approveSetujui request pending/ditangguhkan.
POST/api/inventory/requests/{id}/rejectTolak request dengan field reason wajib.
POST/api/inventory/requests/{id}/deferTangguhkan request dengan field reason wajib agar bisa dilanjutkan nanti.
POST/api/inventory/requests/{id}/resumeLanjutkan request ditangguhkan menjadi pending.
POST/api/inventory/requests/{id}/processProses request disetujui dan catat mutasi stok per item.
POST/api/inventory/requests/{id}/completeTandai request yang sudah diproses menjadi selesai.
POST/api/inventory/requests/{id}/cancelBatalkan request oleh pemohon/admin.
POST/api/suppliers/{supplier}/items/import-previewUpload multipart field file untuk membaca katalog supplier dan mengembalikan baris preview, status valid, action, dan item yang cocok.
POST/api/suppliers/{supplier}/items/importImport baris preview terpilih. Body: items[] berisi nama, SKU, kategori, satuan, harga beli, harga jual, dan selected.

Endpoint Internal File Manager Tenant

Endpoint ini dipakai panel Netadmin yang sudah login. File Manager memisahkan file tenant menjadi private untuk folder pribadi user dan shared untuk folder umum tenant.

Admin tenant dapat melihat semua folder user dalam tenantnya. Superadmin atau tenant master dapat memakai query tenant_id untuk audit/support lintas tenant.

Endpoint ini bukan external API publik. Gunakan hanya dari sesi admin Netadmin dengan permission file_manager.view, file_manager.upload, file_manager.delete, atau file_manager.admin.
MethodEndpointKeterangan
GET/api/file-managerList file tenant. Query opsional: scope, folder, search, owner_user_id, tenant_id.
POST/api/file-managerUpload file multipart. Field: file, visibility, folder, owner_user_id, description. Maksimal 100 MB.
GET/api/file-manager/{id}/downloadDownload file yang dapat diakses user. Aksi tercatat di audit log.
DELETE/api/file-manager/{id}Hapus metadata dan file fisik dari storage sesuai permission. Aksi tercatat di audit log.

Endpoint Internal File Share Master

Endpoint ini dipakai panel Netadmin yang sudah login di tenant master. File Share berfungsi sebagai repository file internal untuk dokumen, APK, laporan, export, template, dan arsip verifikasi backup.

Jika S3 Object Storage tenant master aktif, file disimpan ke S3. Jika belum aktif, sistem menggunakan local fallback dan tetap menampilkan label storage yang jelas.

File Share hanya tersedia untuk tenant master. Tenant subscriber akan menerima response 403 dengan pesan bahwa fitur hanya tersedia untuk tenant master.
MethodEndpointKeterangan
GET/api/master/file-sharesList file share tenant master. Query opsional: folder, search.
POST/api/master/file-sharesUpload file multipart. Field: file, folder, description, is_public. Maksimal 100 MB.
GET/api/master/file-shares/{id}/downloadDownload file. Aksi tercatat di audit log.
DELETE/api/master/file-shares/{id}Hapus metadata dan file fisik dari storage. Aksi tercatat di audit log.

Endpoint Internal Tiket & Incident

Endpoint ini dipakai NetAdmin untuk menjaga akses tiket teknisi, rekomendasi assign manual, dan incident massal. Role teknisi hanya melihat tiket yang ditugaskan, diklaim, atau mencatat dirinya sebagai anggota tim.

Endpoint POST /api/tickets/incidents menerima field tambahan home_base_id, severity, estimated_recovery_at, impact_area, root_cause_initial, impact_ticket_description, group_message, auto_link_tickets, create_impact_tickets, schedule_impact_tickets, notify_customers, notify_whatsapp_groups, auto_link_limit, dan impact_ticket_limit. Jika auto-link atau create-ticket aktif tanpa OLT/Home Base yang bisa dipetakan ke ONU, backend melewati proses massal agar tidak menautkan/membuat tiket untuk semua pelanggan.

Notifikasi group memakai event ticket_incident_created / label Incident Massal. Atur group tujuan dari WhatsApp Bot dengan mencentang event tersebut pada group NOC/teknisi.

MethodEndpointKeterangan
GET/api/tickets/incidentsDaftar incident aktif dengan jumlah tiket anak dan metadata incident.
POST/api/tickets/incidentsBuat incident massal. Body minimal description; opsional scope OLT/Home Base, severity, ETA, auto-link tiket terbuka, pembuatan tiket pelanggan terdampak dari ONU, sinkron jadwal teknisi, broadcast WA opt-in ke pelanggan, dan notifikasi WA group event `Incident Massal`.
GET/api/tickets/{id}/assignment-candidatesDaftar kandidat teknisi untuk assign manual, termasuk available, nearest_home_base, busy_reasons, distance_km, score, dan warning.
POST/api/tickets/{id}/manual-assignBody: assigned_to, reason, clear_claim, dan opsional allow_override. Tanpa override, backend menolak teknisi sibuk atau bukan dari home base terdekat.
POST/api/tickets/{id}/link-incidentTautkan tiket biasa ke incident aktif dengan parent_ticket_id.
POST/api/tickets/{id}/unlink-incidentLepas tiket biasa dari incident tanpa menghapus histori tiket.
curl -X POST https://apps.ion.net.id/api/tickets/incidents \
  -H "Authorization: Bearer <TOKEN_LOGIN_ADMIN>" \
  -H "Content-Type: application/json" \
  -d '{
    "description": "OLT-CORE-01 down, pelanggan area Batam Center terdampak",
    "olt_id": 12,
    "home_base_id": 3,
    "severity": "major",
    "estimated_recovery_at": "2026-06-29T22:00:00+08:00",
    "impact_area": "Batam Center Cluster A-B",
    "root_cause_initial": "Indikasi uplink putus",
    "impact_ticket_description": "Tiket otomatis dari incident {incident_number}.\n\nRingkasan gangguan:\n{incident_description}\n\nPelanggan terdampak: {customer_name}\nONU/SN: {onu_sn}\nArea terdampak: {impact_area}\nEstimasi pulih: {eta}",
    "group_message": "*INCIDENT MASSAL*\n\nArea terdampak: Batam Center Cluster A-B\nSeverity: Major\nMohon NOC dan koordinator teknisi memantau tiket incident sampai normal.",
    "auto_link_tickets": true,
    "create_impact_tickets": true,
    "schedule_impact_tickets": true,
    "notify_customers": true,
    "notify_whatsapp_groups": true,
    "auto_link_limit": 50,
    "impact_ticket_limit": 50
  }'

Endpoint Internal Settings AI

Endpoint ini dipakai NetAdmin yang sudah login dengan permission settings.view / settings.manage. Field ai_assistant_enabled mengatur visibilitas tombol Bantuan AI per tenant dan defaultnya false.

MethodEndpointKeterangan
GET/api/settingsResponse menyertakan ai_assistant_enabled, ai_provider (anthropic, openai, gemini, deepseek, aksita), ai_providers, ai_model, ai_key_sets, serta ops_settings.ai_assistant_enabled untuk status tampil/sembunyi tombol Bantuan AI.
PUT/api/settingsSimpan konfigurasi AI dengan body { "ai_provider": "deepseek", "ai_model": "deepseek-v4-flash", "ai_api_key": "sk-...", "ops_settings": { "ai_assistant_enabled": true, "ai_preferences": { ... } } }. Provider aktif dipakai untuk fitur teks AI (chat, AI Center analisis, heatmap, copilot). OCR/vision dan aksi teknis AI tetap memakai ops_settings.ai_anthropic_api_key terpisah.
POST/api/settings/test-aiTest koneksi provider AI aktif atau sementara (ai_provider: anthropic, openai, gemini, deepseek, aksita). Body opsional: ai_api_key, ai_model.
GET/api/ai/balance?provider=deepseekCek status balance provider AI. DeepSeek tidak menyediakan endpoint balance publik; response supported=false dengan pesan cek dashboard billing DeepSeek.

Endpoint Portal Pelanggan

Endpoint ini dipakai oleh UI portal pelanggan setelah login pelanggan. Reopen tiket dari portal hanya aktif jika admin mengizinkan di Pengaturan → SLA Tiket → Opsi Reopen Tiket Selesai.

MethodEndpointKeterangan
POST/api/portal/tickets/{id}/reopenPelanggan membuka kembali tiket miliknya yang sudah resolved/closed. Body: { "reason": "Internet masih putus sejak tadi pagi" }. Alasan wajib minimal 10 karakter.

Endpoint Internal APK Builder

Endpoint ini dipakai panel Netadmin yang sudah login dengan permission APK Builder. Konfigurasi bersifat tenant-scoped dan app type yang didukung adalah portal, netadmin, partner, dan absensi.

Untuk absensi, isi base_url dengan domain utama aplikasi. Builder otomatis mengarahkan Capacitor server URL ke /absensi/, sehingga theme, login, kamera, liveness, GPS, dan fitur teknisi mengikuti portal Absensi yang sudah ada.

Pesan error dibuat eksplisit untuk app type tidak valid, Base URL tidak valid, Package ID tidak valid/duplikat, warna theme bukan HEX, keystore release belum siap, environment build belum lengkap, dan file APK/keystore yang hilang dari storage.
MethodEndpointKeterangan
GET/api/android-apkAmbil konfigurasi semua app type, riwayat build terakhir, dan health environment build.
GET/api/android-apk/healthCek Node.js, npm, Java/keytool, Android SDK, dan permission storage.
PUT/api/android-apk/configs/{appType}Simpan konfigurasi APK. {appType}: portal, netadmin, partner, atau absensi.
POST/api/android-apk/configs/{appType}/buildsMasukkan build APK ke antrian. Body: { "build_type": "debug" } atau { "build_type": "release" }.
GET/api/android-apk/builds/{id}/downloadDownload APK jika status build sudah sukses.

Contoh Integrasi

Ambil pelanggan aktif

curl "https://apps.ion.net.id/api/external/v1/customers?status=active&per_page=50" \
  -H "Authorization: Bearer 1|TOKEN..." \
  -H "Accept: application/json"

Buat pelanggan baru

curl -X POST https://apps.ion.net.id/api/external/v1/customers \
  -H "Authorization: Bearer 1|TOKEN_READ_WRITE" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Budi Santoso",
    "phone": "081234567890",
    "email": "budi@example.com",
    "address": "Jl. Merdeka No. 10",
    "package_id": 12,
    "service_type": "pppoe",
    "billing_cycle": "prepaid"
  }'

Buat tiket gangguan

curl -X POST https://apps.ion.net.id/api/external/v1/tickets \
  -H "Authorization: Bearer 1|TOKEN_READ_WRITE" \
  -H "Content-Type: application/json" \
  -d '{
    "customer_id": 101,
    "type": "Internet lambat",
    "priority": "medium",
    "description": "Dilaporkan dari CRM eksternal",
    "contact_name": "Budi",
    "contact_phone": "081234567890",
    "external_id": "CRM-88991"
  }'

Contoh response list

{
  "current_page": 1,
  "data": [
    {
      "id": 101,
      "code": "CST-21017890",
      "name": "Budi Santoso",
      "phone": "081234567890",
      "status": "active",
      "package": {"id": 12, "name": "Home 30 Mbps"}
    }
  ],
  "per_page": 50,
  "total": 1
}

VyOS DHCP Binding

Flow ini dipakai saat operator membuat pelanggan DHCP/Static tanpa mengetahui MAC ONU/CPE. Pelanggan disimpan dulu, kemudian lease DHCP dari VyOS yang sudah online dihubungkan ke pelanggan.

MethodEndpointFungsi
GET/api/network/vyos-dhcp-leases?refresh=1Menampilkan lease DHCP VyOS dengan status bound, unbound, atau isolated.
POST/api/network/vyos-dhcp-leases/bindMenghubungkan lease ke pelanggan DHCP/Static dan menjalankan provisioning atau isolir sesuai status pelanggan.
{
  "customer_id": 123,
  "mac_address": "aa:bb:cc:dd:ee:ff",
  "address": "10.10.20.15",
  "router_id": 2,
  "sync": true
}
Jika pelanggan sedang isolir/telat bayar, binding dengan sync=true langsung memasukkan IP lease ke address-group VyOS KT_ISOLATED_CUSTOMERS. Pastikan firewall VyOS sudah memakai group ini untuk allow DNS/payment portal dan blok internet umum.

Error 422 dibuat eksplisit: lease tanpa MAC/IP valid, pelanggan bukan tipe DHCP/Static, MAC sudah dipakai pelanggan lain, atau NAS VyOS tidak aktif.

Skema Data Ringkas

Customer

id, code, name, email, phone, status, service_type, customer_tier, address, latitude, longitude, billing_cycle, billing_day, package, onu, created_at, updated_at

Invoice

id, invoice_number, customer_id, customer, package_id, amount, status, due_date, paid_at, period_start, period_end, created_at

Ticket

id, ticket_number, source, customer_id, customer, onu, assigned_to, assignee, type, priority, status, description, sla_breached, due dates

ONU

id, customer_id, customer, olt, serial_number, pon_port, rx_power, tx_power, bandwidth_pct, status, uptime, last_seen

Error Codes

StatusArtiSolusi
401Token kosong, salah, expired, dicabut, atau sesi login NetAdmin/portal tidak valid. Response API mengembalikan JSON dengan code: UNAUTHENTICATED, bukan redirect halaman login.Buat token baru, login ulang, dan kirim header Authorization.
403Token tidak punya tenant atau hanya read untuk operasi write.Gunakan token tenant yang benar dan akses read_write jika perlu menulis.
403demo_guard_blocked: tenant berjalan dalam Mode Demo Aman dan aksi diblokir.Jalankan aksi di tenant produksi/normal, atau minta platform owner menonaktifkan mode demo jika memang sudah siap digunakan.
404Data tidak ditemukan di tenant token.Pastikan ID berasal dari tenant yang sama.
422Payload validasi gagal.Baca field errors pada response JSON.
429Terlalu banyak request jika rate limit aktif.Terapkan retry dengan backoff.
500Error server.Hubungi admin dan sertakan timestamp request.
Jangan kirim credential pelanggan, password PPPoE, token payment gateway, atau secret lain ke API kecuali endpoint memang mendukung dan terdokumentasi.