Dokumen ini menjelaskan spesifikasi API backend TokoFlow untuk versi SaaS berbasis cloud. API ini digunakan oleh frontend (React + Material UI) dan mendukung multi-tenant architecture, JWT authentication, serta subscription-based access control.
| Keterangan | Nilai |
|---|---|
| Base URL | /api/v1 |
| Autentikasi | Bearer <JWT_ACCESS_TOKEN> |
| Format | application/json |
| Pagination | ?page=1&limit=20 |
| Sorting | ?sort=field atau ?sort=-field |
| Filter | Query params per resource |
| Error Format | { code, message, details? } |
Membuat akun baru (owner) untuk SaaS TokoFlow.
Request
{
"fullName": "Budi Santoso",
"email": "budi@example.com",
"password": "123456",
"storeName": "Toko Budi"
}
Response 201
{
"message": "Account created successfully",
"user": {
"id": "uuid-owner",
"fullName": "Budi Santoso",
"email": "budi@example.com",
"role": "owner"
},
"store": {
"id": "store-uuid",
"name": "Toko Budi"
},
"subscription": {
"plan": "Free",
"expiresAt": "2025-11-21"
}
}
Request
{ "email": "budi@example.com", "password": "123456" }
Response 200
{
"accessToken": "eyJhbGci...",
"refreshToken": "eyJhbGci...",
"user": {
"id": "uuid-1234",
"fullName": "Budi Santoso",
"role": "owner",
"storeId": "store-uuid"
}
}
Request
{ "refreshToken": "eyJhbGci..." }
Response 200
{
"accessToken": "new-access-token",
"refreshToken": "new-refresh-token"
}
Request
{ "refreshToken": "eyJhbGci..." }
Response: 204 No Content
Query: ?page=1&limit=10&role=kasir
Response 200
{
"data": [
{
"id": "uuid-1",
"fullName": "Kasir 1",
"email": "kasir1@tokobudi.id",
"role": "kasir",
"storeId": "store-uuid"
}
],
"meta": { "page": 1, "limit": 10, "total": 5 }
}
Request
{
"fullName": "Kasir Dua",
"email": "kasir2@tokobudi.id",
"password": "123456",
"role": "kasir",
"storeId": "store-uuid"
}
Response 201
{
"id": "uuid-2",
"fullName": "Kasir Dua",
"role": "kasir",
"storeId": "store-uuid",
"isActive": true
}
Request
{ "fullName": "Kasir Dua (Updated)" }
Response 200: Updated user object
Menghapus user dari tenant aktif. Response 204 No Content
Request
{
"name": "Toko Cabang 2",
"address": "Jl. Merdeka 21",
"phone": "081234567890"
}
Response 201
{
"id": "store-uuid-2",
"name": "Toko Cabang 2",
"address": "Jl. Merdeka 21",
"ownerId": "uuid-owner"
}
Response 200
{
"data": [
{ "id": "store-uuid", "name": "Toko Utama" },
{ "id": "store-uuid-2", "name": "Toko Cabang 2" }
]
}
Request
{
"sku": "PRD001",
"name": "Minyak Goreng",
"unit": "liter",
"costPrice": 15000,
"salePrice": 20000,
"storeId": "store-uuid",
"categoryId": null
}
Response 201
{
"id": "product-uuid",
"name": "Minyak Goreng",
"sku": "PRD001",
"unit": "liter",
"salePrice": 20000
}
Response 200
{
"data": [
{ "id": "product-uuid", "name": "Minyak Goreng", "stock": 20 },
{ "id": "product-uuid2", "name": "Sabun", "stock": 15 }
]
}
Request
{
"storeId": "store-uuid",
"productId": "product-uuid",
"type": "IN",
"quantity": 100,
"reason": "Initial Stock"
}
Response 201
{
"id": "inventory-uuid",
"storeId": "store-uuid",
"productId": "product-uuid",
"type": "IN",
"quantity": 100,
"createdAt": "2025-10-21T12:00:00Z"
}
GET /inventory?storeId=store-uuid → menampilkan semua pergerakan stok.
Request
{
"storeId": "store-uuid",
"userId": "user-uuid",
"items": [
{
"productId": "product-uuid",
"sku": "PRD001",
"name": "Minyak Goreng",
"unitPrice": 20000,
"quantity": 2
}
],
"payment": { "method": "CASH", "amount": 40000, "change": 0 },
"notes": "Penjualan harian",
"status": "SAVED"
}
Response 201
{
"id": "sale-uuid",
"receiptNo": "INV/2025/10/001",
"total": 40000,
"createdAt": "2025-10-21T12:30:00Z"
}
Response 200
{
"storeId": "store-uuid",
"date": "2025-10-21",
"totalSales": 400000,
"transactionsCount": 25
}
Response 200
{
"month": "October",
"year": 2025,
"totalSales": 12000000,
"topProducts": [
{ "name": "Minyak Goreng", "qty": 120 },
{ "name": "Sabun", "qty": 80 }
]
}
Response 200
{
"data": [
{
"id": "log-uuid",
"userId": "user-uuid",
"module": "PRODUCT",
"action": "UPDATE",
"before": { "salePrice": 18000 },
"after": { "salePrice": 20000 },
"createdAt": "2025-10-21T10:05:00Z"
}
],
"meta": { "page": 1, "limit": 10, "total": 50 }
}
Menampilkan daftar paket langganan.
Response 200
{
"data": [
{ "id": "plan-free", "name": "Free", "price": 0, "storeLimit": 1 },
{ "id": "plan-basic", "name": "Basic", "price": 49000, "storeLimit": 3 },
{ "id": "plan-pro", "name": "Pro", "price": 99000, "storeLimit": 10 }
]
}
Request
{
"planId": "plan-pro",
"paymentMethod": "midtrans"
}
Response 201
{
"paymentUrl": "https://app.midtrans.com/pay/txn123",
"status": "PENDING"
}
| Code | Message | Keterangan |
|---|---|---|
| 401 | Unauthorized | Token invalid atau expired |
| 403 | Forbidden | Role tidak diizinkan |
| 404 | Not Found | Data tidak ditemukan |
| 422 | Validation Error | Input tidak valid |
| 500 | Internal Server Error | Kesalahan server |
Dokumen ini menjadi acuan utama untuk: