API Documentation
Dokumentasi lengkap RESTful API untuk sistem manajemen Lazizah. Semua endpoint di-prefix dengan /api/v1 dan mengembalikan JSON kecuali di endpoint download laporan.
Pengantar & Autentikasi
Base URL
https://<domain>/api/v1
Format
Request body: application/json atau multipart/form-data (jika ada upload file)
Header Autentikasi
Authorization: Bearer <token> Accept: application/json
Struktur Response
{
"success": true,
"message": "string",
"data": {} | [],
"meta": // pagination (jika ada)
}
Hierarki Role
- cashier Level terendah — kasir, POS
- staff Akses inventory, resep, expense
- manager Cash book, analytics, laporan
- owner Manajemen user & settings
- superuser Akses penuh termasuk hapus user
HTTP Status Codes
- 200 OK — sukses
- 201 Created — data berhasil dibuat
- 401 Unauthorized — token tidak valid / salah login
- 403 Forbidden — role tidak cukup / akun nonaktif
- 404 Not Found — resource tidak ditemukan
- 422 Unprocessable — validasi gagal / stok kurang
- 429 Too Many Requests — rate limit tercapai
- 500 Server Error
Pagination
Endpoint list mendukung parameter per_page (default bervariasi). Response meta berisi current_page, per_page, total, last_page.
ID Format
Semua resource menggunakan UUID sebagai public ID (bukan integer ID database). Kirim UUID di path parameter dan request body untuk reference ke resource lain.
Auth
Login dengan username/email dan password. Mengembalikan access token. Throttle: 5 attempt/menit per identifier, 60 request/menit per IP.
| Field | Tipe | Wajib | Keterangan |
|---|---|---|---|
| login | string | cond. | Username atau email (gunakan login atau email) |
| string | cond. | Alternatif field login | |
| password | string | required | |
| remember_me | boolean | optional | Jika true, response menyertakan refresh_token |
{
"success": true,
"message": "Login successful.",
"data": {
"user": {
"id": "uuid",
"name": "string",
"username": "string|null",
"initials": "string|null",
"email": "string",
"role": 1,
"role_label": "Cashier",
"phone": "string|null",
"is_active": true
},
"token": "1|accessToken...",
"refresh_token": "2|refreshToken..." // hanya jika remember_me
}
}
Merotasi pasangan token. Kirim refresh_token sebagai Bearer. Menghapus semua token sesi lama dan menerbitkan pasangan baru.
Authorization: Bearer <refresh_token>{
"success": true,
"data": {
"token": "new_access_token",
"refresh_token": "new_refresh_token"
}
}
Mencabut semua token aktif milik user yang sedang login.
{ "success": true, "message": "Logout successful." }
Mengambil data user yang sedang login.
{
"id": "uuid", "name": "string", "username": "string",
"initials": "string", "email": "string",
"role": 1, "role_label": "Cashier",
"phone": "string|null", "is_active": true
}
Update profil user yang sedang login.
| Field | Tipe | Wajib | Keterangan |
|---|---|---|---|
| name | string | sometimes | Max 120 karakter |
| username | string|null | sometimes | Max 50, alpha_dash, unique |
| string | sometimes | Email valid, unique | |
| phone | string|null | optional | Max 20 karakter |
Ganti password. Setelah berhasil, semua token dicabut — user harus login ulang.
| Field | Tipe | Wajib |
|---|---|---|
| current_password | string | required |
| password | string | required |
| password_confirmation | string | required |
Dashboard
Data ringkasan untuk halaman utama dashboard. Mencakup stat card, transaksi terbaru, produk terlaris hari ini, dan order yang jatuh tempo hari ini.
{
"stat_cards": {
"today_revenue": 0,
"revenue_delta_pct": 12.5, // % vs kemarin
"today_orders": 0,
"orders_delta": 0, // selisih absolut vs kemarin
"cash_on_hand": 0, // saldo terakhir cash book
"today_expenses": 0,
"expense_delta_pct": 0.0
},
"recent_transactions": [
{
"ref": "INV-001", "description": "Kue Coklat ×2, ...",
"time": "09:30", "date": "01 Jan 2025",
"type": "sale", "payment": "CASH",
"amount": 85000, "status": "paid"
}
// expense: amount negatif (-), type: "expense"
],
"top_products": [
{ "name": "string", "image": "path|null",
"qty": 12, "revenue": 240000, "bar_pct": 100 }
],
"quick_stats": {
"busiest_hour": "10:00–11:00",
"avg_order_value": 75000,
"low_stock_count": 3,
"critical_count": 1,
"product_count": 24,
"profit_margin": 42.5
},
"orders_due_today": [ /* order objects */ ]
}
Sales
paid membuat entri kredit di Cash Book. Perubahan status cancelled mengembalikan stok.
Daftar penjualan dengan filter dan ringkasan statistik (hari ini / minggu ini / bulan ini).
| Parameter | Tipe | Keterangan |
|---|---|---|
| status | string | paid | pending | cancelled |
| payment_method | string | cash | qris | transfer |
| date_from | date | Format YYYY-MM-DD |
| date_to | date | Format YYYY-MM-DD |
| search | string | Cari di order_number / customer_name |
| per_page | integer | Default: 15 |
{
"items": [ /* Sale objects */ ],
"summary": {
"today_revenue": 0, "today_orders": 0,
"week_revenue": 0, "week_orders": 0,
"month_revenue": 0, "month_orders": 0
}
}
Catat transaksi penjualan baru. Harga diambil otomatis dari selling_price produk. Stok dipotong otomatis untuk status non-cancelled.
| Field | Tipe | Wajib |
|---|---|---|
| customer_name | string|null | optional |
| payment_method | string | required |
| status | string | required |
| notes | string|null | optional |
| sale_date | date|null | optional |
| items | array | required |
| items[].product_id | uuid | required |
| items[].quantity | integer | required |
payment_method: cash | qris | transfer status: paid | pending | cancelled
{
"success": false,
"message": "Insufficient stock...",
"errors": {
"stock": [
{ "product": "Kue Coklat",
"available": 2,
"requested": 5 }
]
}
}
Detail satu transaksi. Menggunakan route model binding (id = UUID). Memuat relasi items.product.category dan user.
Update metadata atau status penjualan. Transisi status secara otomatis mengelola stok dan Cash Book.
•
active → cancelled: stok dikembalikan•
cancelled → active: stok dipotong (validasi dulu)•
non-paid → paid: entri kredit Cash Book dibuat•
paid → non-paid: entri Cash Book dihapus
| Field | Tipe | Wajib |
|---|---|---|
| customer_name | string|null | optional |
| payment_method | string | sometimes |
| status | string | sometimes |
| notes | string|null | optional |
Hapus transaksi. Stok dikembalikan (jika bukan cancelled). Entri Cash Book dihapus (jika paid).
Orders (Pre-order)
Daftar pre-order diurutkan berdasarkan tanggal dan waktu jatuh tempo.
| Parameter | Tipe | Keterangan |
|---|---|---|
| status | string | Comma-separated: baru,diproses,siap,selesai,batal |
| payment_status | string | belum_bayar | dp | lunas |
| due_date | date | Filter tanggal jatuh tempo tepat |
| date_from / date_to | date | Range tanggal jatuh tempo |
| search | string | Cari di nama customer, telepon, order_number |
| per_page | integer | Default: 15 |
Buat pre-order baru. Item dapat berisi produk custom (tanpa product_id) atau produk dari catalog. Harga diinput manual.
| Field | Tipe | Wajib |
|---|---|---|
| customer_name | string | required |
| customer_phone | string|null | optional |
| due_date | date | required |
| due_time | HH:MM | optional |
| fulfillment | string | optional |
| notes | string|null | optional |
| items[].product_id | uuid|null | optional |
| items[].product_name | string | required |
| items[].qty | integer | required |
| items[].unit_price | integer | required |
| items[].item_notes | string|null | optional |
fulfillment: ambil | antar (default: ambil) status (awal): baru
{
"id": "uuid",
"order_number": "ORD-001",
"customer_name": "string",
"due_date": "YYYY-MM-DD",
"due_time": "HH:MM|null",
"status": "baru",
"payment_status": "belum_bayar",
"total_amount": 150000,
"amount_paid": 0,
"remaining": 150000,
"fulfillment": "ambil",
"items": []
}
Update status, pembayaran, atau data order. Jika amount_paid ≥ total_amount, payment_status otomatis di-set ke lunas.
| Field | Tipe | Keterangan |
|---|---|---|
| status | string | baru | diproses | siap | selesai | batal |
| payment_status | string | belum_bayar | dp | lunas |
| amount_paid | integer | Jika ≥ total → auto lunas |
| due_date / due_time | date/time | Update jadwal jatuh tempo |
| fulfillment | string | ambil | antar |
Hapus pre-order.
Events
Daftar events/pengingat (hari besar, promo, produksi, dll). Query: from, to, type, per_page (default 30).
| Field | Tipe | Wajib |
|---|---|---|
| title | string | required |
| type | string | required |
| start_date | date | required |
| end_date | date|null | optional |
| notes | string|null | optional |
type: hari_besar | promo | produksi | lainnya
CRUD standar. PUT menggunakan body yang sama dengan POST.
Products
| Parameter | Tipe | Keterangan |
|---|---|---|
| sort | string | name(default) | price_asc | price_desc | stock_asc | stock_desc |
| category | string | Slug kategori |
| category_id | uuid | UUID kategori |
| status | string | active | inactive |
| search | string | Cari nama produk |
| price_min / price_max | integer | Range harga |
| stock_status | string | out | low | in |
| per_page | integer | Default: 24 |
Buat produk baru beserta data inventory awal. Gunakan multipart/form-data jika menyertakan gambar. Dijalankan dalam satu transaksi DB.
multipart/form-data jika ada field image| Field | Tipe | Wajib |
|---|---|---|
| category_id | uuid | required |
| name | string | required |
| selling_price | integer | required |
| cost_price | integer | required |
| image | file | optional |
| description | string|null | optional |
| initial_stock | integer | optional |
| min_stock | integer | optional |
| unit | string | optional |
| status | string | optional |
Detail produk beserta relasi category dan inventory.
Update data produk. Gambar lama dihapus otomatis jika ada upload baru. Semua field bersifat sometimes.
category_id // sometimes|string (uuid) name // sometimes|string|max:120 image // nullable|file — mengganti gambar lama description // nullable|string selling_price // sometimes|integer cost_price // sometimes|integer status // sometimes|active|inactive
Hapus produk (soft delete).
Categories
Daftar semua kategori, diurutkan alfabetis. Setiap item menyertakan product_count.
Buat kategori baru. Slug di-generate otomatis dari nama. Gunakan multipart/form-data jika ada gambar.
| Field | Tipe | Wajib |
|---|---|---|
| name | string | required |
| image | file | optional |
Profile
/auth/me. Fungsionalitas serupa tapi diletakkan di path /profile.Data profil user yang sedang login.
| Field | Tipe | Wajib |
|---|---|---|
| name | string | required |
| string | required | |
| phone | string|null | optional |
| Field | Tipe | Wajib |
|---|---|---|
| current_password | string | required |
| password | string | required |
| password_confirmation | string | required |
Inventory
Seluruh data stok produk, disertai ringkasan valuasi dan outflow 30 hari terakhir.
| Parameter | Keterangan |
|---|---|
| status | critical (stok=0) | low (di bawah min) | ok |
{
"items": [
{
"id": "uuid",
"product_id": "uuid",
"product_name": "string",
"product_image": "path|null",
"category": "string",
"current_stock": 50,
"min_stock": 10,
"unit": "pcs",
"stock_status": "ok | low | critical",
"stock_pct": 80,
"cost_value": 500000,
"retail_value": 750000,
"outgoing_30d": 24,
"last_updated_at": "datetime"
}
],
"summary": {
"total": 30, "ok": 25, "low": 3, "critical": 2,
"total_units": 1200,
"total_cost_value": 12000000,
"total_retail_value": 18000000
}
}
Daftar produk dengan stok low dan critical, digabung dalam satu array. Berguna untuk notifikasi.
Adjust stok produk. {productId} adalah UUID produk.
| Field | Tipe | Wajib |
|---|---|---|
| action | string | required |
| quantity | integer | required |
| min_stock | integer | optional |
| unit | string | optional |
| notes | string | optional |
action: add // tambah stok remove // kurangi stok set // set langsung
Recipes
Daftar resep. Query: search, category, include_inactive (boolean, default false), per_page (default 50).
Buat resep baru beserta daftar bahan. HPP dihitung otomatis dari bahan.
| Field | Tipe | Wajib |
|---|---|---|
| name | string | required |
| yield | integer | optional |
| yield_unit | string | optional |
| product_id | uuid | optional |
| steps | string | optional |
| ingredients | array | required |
| ingredients[].name | string | required |
| ingredients[].qty | numeric | required |
| ingredients[].cost_per_unit | integer | required |
| ingredients[].unit | string | optional |
{
"total_cost": 85000, // total biaya bahan
"hpp_per_unit": 8500, // HPP per yield unit
"margin_pct": 40.5, // margin vs harga jual produk
"selling_price": 14000, // dari produk terkait
"ingredients": [
{
"id": "uuid", "name": "Tepung",
"qty": 0.5, "unit": "kg",
"cost_per_unit": 12000,
"line_cost": 6000
}
]
}
Update resep. Seluruh daftar bahan diganti (replace, bukan merge). Field tambahan: is_active (boolean).
Expenses
Daftar pengeluaran dengan statistik bulan ini per kategori.
| Parameter | Keterangan |
|---|---|
| category | Filter kategori detail |
| date_from / date_to | Range tanggal |
| search | Cari di notes, ref_number, supplier, dan description detail |
| per_page | Default: 15 |
{
"items": [ /* paginated Expense objects */ ],
"month_total": 3500000,
"by_category": {
"ingredients": { "total": 2000000, "count": 5 },
"packaging": { "total": 500000, "count": 2 }
// ... kategori lain
}
}
| Field | Tipe | Wajib |
|---|---|---|
| payment_method | string | required |
| expense_date | date | optional |
| supplier | string | optional |
| reference_no | string | optional |
| notes | string | optional |
| Field | Tipe | Wajib |
|---|---|---|
| description | string | required |
| category | string | required |
| amount | integer | required |
| quantity | integer | optional |
| unit_price | integer | optional |
| unit | string | optional |
payment_method: cash | transfer | qris category: ingredients packaging utilities rent payroll other
Update pengeluaran. Jika details[] dikirim, seluruh detail lama diganti. Cash Book entry disinkronisasi otomatis dan balance di-recalculate.
Hapus pengeluaran dan entri Cash Book yang terkait. Balance di-recalculate.
Cash Book
Ringkasan saldo dan statistik Cash Book bulan ini.
{
"current_balance": 5000000,
"total_credit": 8000000, // pemasukan bulan ini
"total_debit": 3000000, // pengeluaran bulan ini
"total_entries": 45,
"opening_balance": 0,
"updated_at": "ISO8601"
}
Daftar entri Cash Book per bulan, diurutkan terbaru ke lama.
| Query Param | Keterangan |
|---|---|
| year | Default: tahun ini |
| month | Default: bulan ini (1–12) |
| type | credit | debit |
| per_page | Default: 15 |
Buat entri manual di Cash Book.
| Field | Tipe | Wajib |
|---|---|---|
| description | string | required |
| type | string | required |
| amount | integer | required |
| entry_date | date | optional |
| notes | string | optional |
type: credit // pemasukan | debit // pengeluaran
Analytics
Data analitik lengkap: KPI, grafik harian, breakdown per kategori, dan top sellers — dengan perbandingan periode sebelumnya.
| Parameter | Tipe | Keterangan |
|---|---|---|
| period | integer|string | 7 | 30(default) | 90 | 365 | week | month | year |
| date_from | date | Menggantikan period jika diisi |
| date_to | date | Default: hari ini |
{
"period": 30, "date_from": "YYYY-MM-DD", "date_to": "YYYY-MM-DD",
"revenue_change": 12.5, // % vs periode sebelumnya
"expense_change": -3.2,
"kpi": {
"revenue": 0, "expenses": 0, "orders": 0,
"net_profit": 0, "gross_margin": 0.0,
"avg_daily_orders": 0.0,
"best_day": { "date": "YYYY-MM-DD", "label": "Monday", "revenue": 0 },
"avg_order_value": 0,
"busiest_hour": "10:00",
"expense_ratio": 0.0
},
"daily_revenue": [
{ "date": "YYYY-MM-DD", "label": "Mon",
"total": 0, "expenses": 0, "orders": 0 }
],
"by_category": [
{ "category": "Roti", "total": 0, "pct": 45.2 }
],
"top_sellers": [
{ "name": "string", "qty": 0, "revenue": 0, "bar_pct": 100 }
]
}
Reports
Riwayat 25 laporan yang pernah di-generate.
Generate laporan. Format json mengembalikan data. Format csv, excel, pdf mengembalikan file download.
| Field | Tipe | Wajib |
|---|---|---|
| type | string | required |
| date_from | date | required |
| date_to | date | required |
| format | string | required |
| group_by | string | optional |
type: sales // daftar transaksi penjualan expenses // daftar pengeluaran cashbook // buku kas inventory // snapshot stok saat ini profit // laba/rugi per periode summary // ringkasan + top produk format: json | csv | excel | pdf group_by: day | week | month
json mengembalikan file download langsung, bukan JSON.Users
| Parameter | Keterangan |
|---|---|
| role | Filter berdasarkan nilai role (integer) |
| active | true | false |
| search | Cari nama atau email |
| per_page | Default: 20 |
| Field | Tipe | Wajib |
|---|---|---|
| name | string | required |
| string | required | |
| password | string | required |
| role | integer | required |
| phone | string | optional |
Update data user. Tidak bisa menarget diri sendiri. Jika role berubah, semua token user dicabut.
Aktifkan atau nonaktifkan akun user. Jika dinonaktifkan, semua token dicabut.
| Field | Tipe | Wajib |
|---|---|---|
| is_active | boolean | required |
Hapus user permanen. Hanya superuser. Token dicabut sebelum dihapus. Tidak bisa menghapus diri sendiri.
Settings
Ambil seluruh konfigurasi sistem (StoreSetting singleton).
Update setting. Body berisi key-value sesuai field fillable StoreSetting. Field yang tidak dikenali diabaikan.
| Field | Tipe | Nilai yang diterima |
|---|---|---|
| action | string | sales | cashbook |
| confirm_phrase | string | Harus persis: DELETE |