KasirPro API v1

Base URL: https://api.kasirpro.com · Dokumen mesin: GET /v1 (JSON) & /llms.txt (markdown). Halaman ini memuat kedua bahasa di HTML-nya. Machine docs: GET /v1 (JSON) & /llms.txt (markdown). This page contains both languages in its HTML.

Ikhtisar

API resmi KasirPro untuk aplikasi apa pun yang bisa memanggil HTTP — backend web/mobile, sistem pemesanan, dashboard, middleware, skrip otomasi, hingga AI agent. Prinsip terpenting:

  • Khusus lisensi MAX & Unlimited. Akun PRO ditolak dengan 403 license_tier.
  • Satu kunci = satu toko. Token kp_live_… mengidentifikasi toko sekaligus akun — tidak ada parameter toko di endpoint mana pun. Akun multi toko memakai kunci berbeda per toko (maks 3 kunci/toko).
  • Izin (scope) per kunci: produk, stok, pelanggan, laporan, transaksi, order.
  • Mode kunci: Hanya Baca (semua GET) atau Baca+Tulis (juga POST).
  • Tidak disediakan: HPP/biaya modal tidak pernah dikembalikan; stok, transaksi, kas, dan uang tidak bisa ditulis; tidak ada akses lintas toko.

Overview

The official KasirPro API for any application that can make HTTP calls — web/mobile backends, ordering systems, dashboards, middleware, automation scripts, and AI agents alike. Core principles:

  • MAX & Unlimited licenses only. PRO accounts are rejected with 403 license_tier.
  • One key = one store. The kp_live_… token identifies both the store and the account — no store parameter exists on any endpoint. Multi-store accounts use a separate key per store (max 3 keys/store).
  • Scopes per key: produk, stok, pelanggan, laporan, transaksi, order.
  • Key mode: Read-only (all GET) or Read+Write (POST too).
  • Deliberately not provided: cost price (HPP) is never returned; stock, transactions, cash and money cannot be written; no cross-store access.

Autentikasi

Buat kunci di backoffice.kasirpro.com → menu API Akses (pilih toko, izin, dan mode). Kunci tampil sekali — simpan sebagai environment variable.

Authentication

Create a key at backoffice.kasirpro.comAPI Akses (choose store, scopes and mode). The key is shown once — store it as an environment variable.

curl -H "Authorization: Bearer kp_live_..." https://api.kasirpro.com/v1/me

Wajib HTTPS. Batas 120 request/menit per kunci — saat 429, hormati header Retry-After.

HTTPS required. Limit 120 requests/minute per key — on 429, honor the Retry-After header.

Format & Error

Semua jawaban JSON UTF-8. Tanggal YYYY-MM-DD; nominal uang = integer Rupiah. Bentuk error selalu sama:

Format & Errors

All responses are UTF-8 JSON. Dates are YYYY-MM-DD; money values are integer Rupiah. Errors always share one shape:

{
  "error": true,
  "code": "scope_required",
  "message": "API key ini tidak punya izin 'laporan'. Buat/ubah key di backoffice."
}
HTTPcodeArtiMeaning
401unauthorizedKunci tidak dikenal / dinonaktifkan.Unknown or disabled key.
403scope_requiredKunci tidak punya izin endpoint ini.Key lacks the endpoint's scope.
403write_not_allowedKunci hanya-baca dipakai di endpoint POST.Read-only key used on a POST endpoint.
403license_tierLisensi bukan MAX/Unlimited.License is not MAX/Unlimited.
403license_expiredLisensi backoffice kedaluwarsa.Backoffice license expired.
403account_disabled / toko_deletedAkun dinonaktifkan / toko kunci dihapus.Account disabled / the key's store was deleted.
404not_foundData/endpoint tidak ditemukan.Data or endpoint not found.
405method_not_allowedMethod salah (GET/POST sesuai endpoint).Wrong method (GET/POST per endpoint).
422invalid_paramParameter/body tidak valid — message menjelaskan.Invalid parameter/body — message explains.
429rate_limited>120 request/menit. Ada header Retry-After.>120 requests/minute. Includes Retry-After.
5xxserver_error / store_error / xendit_failedGangguan server / Toko Online / pembuatan QRIS.Server / online-store / QRIS creation failure.

Pagination endpoint daftar: page (mulai 1, maks 400) & per (default 50, maks 100).

Pagination on list endpoints: page (from 1, max 400) & per (default 50, max 100).

GET /v1/ping

Cek koneksi & validitas kunci.Check connectivity & key validity.

Contoh responseExample response — 200
{ "ok": true, "waktu_server": "2026-08-26T14:05:11+07:00" }

GET /v1/me

Identitas kunci: akun, lisensi, toko, mode, dan izin. Mulailah dari sini.The key's identity: account, license, store, mode and scopes. Start here.

Contoh responseExample response — 200
{
  "nama": "Budi Santoso",
  "lisensi": "MAX",
  "aktif_sampai": "2027-01-15",
  "toko": { "id": 12, "nama": "Kedai Kopi Melati" },
  "mode": "baca+tulis",
  "scopes": ["produk", "laporan", "order"]
}

GET /v1/toko

Profil toko milik kunci ini.The key's store profile.

Contoh responseExample response — 200
{
  "data": {
    "id": 12, "nama": "Kedai Kopi Melati",
    "alamat": "Jl. Melati No. 5", "kota": "Bandung",
    "telp": "0227654321", "timezone": "Asia/Jakarta"
  }
}

GET /v1/produk produk

Daftar produk toko — tanpa HPP/biaya modal.The store's products — cost price never included.

Parameter
ParamKeteranganDescription
qCari pada nama / SKU (opsional).Search name / SKU (optional).
page, perPagination (lihat Format).Pagination (see Format).
ContohExample
curl -H "Authorization: Bearer kp_live_..." \
  "https://api.kasirpro.com/v1/produk?q=kopi&per=2"
Contoh responseExample response — 200
{
  "page": 1, "per": 2,
  "data": [
    { "id": 345, "toko": 12, "nama": "Kopi Susu Gula Aren", "sku": "KSG-01",
      "satuan": "cup", "kategori": "Minuman", "harga": 22000, "aktif": true },
    { "id": 351, "toko": 12, "nama": "Kopi Tubruk", "sku": "",
      "satuan": "cup", "kategori": "Minuman", "harga": 15000, "aktif": true }
  ]
}

GET /v1/stok stok

Stok per produk (dijumlah lintas varian, mengikuti mode desimal toko). resep:true = produk berbahan: stok fisik lazim 0 — ketersediaan sebenarnya dari bahan, tidak dihitung endpoint ini. Stock per product (summed across variants, following the store's decimal mode). resep:true = recipe product: physical stock is usually 0 — real availability derives from ingredients, not computed here.

Parameter
ParamKeteranganDescription
qCari nama produk (opsional).Search product name (optional).
page, perPagination.Pagination.
Contoh responseExample response — 200
{
  "page": 1, "per": 50, "toko": 12,
  "data": [
    { "produk_id": 345, "nama": "Kopi Susu Gula Aren", "satuan": "cup", "stok": 0,  "resep": true },
    { "produk_id": 402, "nama": "Air Mineral 600ml",   "satuan": "btl", "stok": 47, "resep": false }
  ]
}

POST /v1/produk produk Baca+Tulis

Tambah produk baru. Tersinkron ke perangkat kasir ≤ 1 menit.Create a product. Syncs to cashier devices within ~1 minute.

Body (JSON)
FieldKeteranganDescription
nama*Nama produk (maks 50 karakter).Product name (max 50 chars).
harga*Harga jual, integer Rupiah ≥ 0.Sell price, integer Rupiah ≥ 0.
sku, satuan, deskripsiOpsional.Optional.
kategori_idOpsional — harus kategori milik toko ini.Optional — must belong to this store.
stokStok awal (opsional, default 0).Initial stock (optional, default 0).
ContohExample
curl -X POST https://api.kasirpro.com/v1/produk \
  -H "Authorization: Bearer kp_live_..." -H "Content-Type: application/json" \
  -d '{"nama":"Es Teh Manis","harga":8000,"satuan":"cup","stok":0}'
Contoh responseExample response — 201
{
  "ok": true, "produk_id": 512,
  "catatan": "Perangkat kasir menerima produk ini lewat sinkronisasi (<=1 menit)."
}

POST /v1/produk/ubah produk Baca+Tulis

Ubah sebagian field produk — hanya field yang dikirim yang berubah. Bisa diubah: nama, harga, sku, satuan, deskripsi, kategori_id. HPP dan stok tidak bisa diubah lewat API.Partial update — only sent fields change. Editable: nama, harga, sku, satuan, deskripsi, kategori_id. Cost price and stock cannot be changed via the API.

ContohExample
curl -X POST https://api.kasirpro.com/v1/produk/ubah \
  -H "Authorization: Bearer kp_live_..." -H "Content-Type: application/json" \
  -d '{"id":512,"harga":9000}'
Contoh responseExample response — 200
{ "ok": true, "produk_id": 512 }

GET /v1/pelanggan pelanggan

Daftar pelanggan toko. piutang = tagihan berjalan pelanggan (Rupiah).The store's customers. piutang = the customer's outstanding receivable (Rupiah).

Parameter
ParamKeteranganDescription
qCari nama / no. HP (opsional).Search name / phone (optional).
page, perPagination.Pagination.
Contoh responseExample response — 200
{
  "page": 1, "per": 50,
  "data": [
    { "id": 88, "toko": 12, "nama": "Siti Rahma", "nohp": "081234567890",
      "alamat": "Jl. Anggrek 3", "piutang": 150000 }
  ]
}

POST /v1/pelanggan pelanggan Baca+Tulis

Tambah pelanggan baru ke toko ini.Create a customer in this store.

Body (JSON)
FieldKeteranganDescription
nama*Nama pelanggan (maks 50 karakter).Customer name (max 50 chars).
nohp, alamatOpsional.Optional.
ContohExample
curl -X POST https://api.kasirpro.com/v1/pelanggan \
  -H "Authorization: Bearer kp_live_..." -H "Content-Type: application/json" \
  -d '{"nama":"Siti Rahma","nohp":"081234567890"}'
Contoh responseExample response — 201
{ "ok": true, "pelanggan_id": 913 }

POST /v1/pelanggan/ubah pelanggan Baca+Tulis

Ubah sebagian data pelanggan: nama, nohp, alamat.Partial customer update: nama, nohp, alamat.

ContohExample
curl -X POST https://api.kasirpro.com/v1/pelanggan/ubah \
  -H "Authorization: Bearer kp_live_..." -H "Content-Type: application/json" \
  -d '{"id":913,"nohp":"081298765432"}'
Contoh responseExample response — 200
{ "ok": true, "pelanggan_id": 913 }

GET /v1/laporan/ringkasan laporan

Omzet & jumlah transaksi per hari. Omzet = total − refund (NET), rumus yang sama dengan laporan backoffice.Daily revenue & transaction count. Revenue = total − refund (net), matching the backoffice reports.

Parameter
ParamKeteranganDescription
from, toYYYY-MM-DD; default bulan berjalan; rentang maks 366 hari.YYYY-MM-DD; defaults to current month; range ≤366 days.
ContohExample
curl -H "Authorization: Bearer kp_live_..." \
  "https://api.kasirpro.com/v1/laporan/ringkasan?from=2026-08-01&to=2026-08-07"
Contoh responseExample response — 200
{
  "from": "2026-08-01", "to": "2026-08-07",
  "total": { "trx": 214, "omzet": 8425000 },
  "per_hari": [
    { "tanggal": "2026-08-01", "trx": 31, "omzet": 1180000 },
    { "tanggal": "2026-08-02", "trx": 28, "omzet": 1035000 }
  ]
}

GET /v1/laporan/produk laporan

Penjualan per produk, urut nilai terbesar — rumus identik Laporan Penjualan backoffice (qty ikut desimal & dikurangi retur; nota dibatalkan tidak dihitung).Per-product sales, ordered by value — the exact backoffice Sales Report formula (decimal qty, returns deducted; voided receipts excluded).

Parameter
ParamKeteranganDescription
from, toRentang tanggal (maks 366 hari).Date range (≤366 days).
page, perPagination.Pagination.
Contoh responseExample response — 200
{
  "from": "2026-08-01", "to": "2026-08-07", "page": 1, "per": 50,
  "data": [
    { "produk_id": 345, "nama": "Kopi Susu Gula Aren", "qty": 182,  "nilai": 4004000 },
    { "produk_id": 402, "nama": "Air Mineral 600ml",   "qty": 95.5, "nilai": 477500 }
  ]
}

GET /v1/transaksi transaksi

Daftar nota, terbaru dulu. metode kosong ditampilkan sebagai "Tunai".Receipt list, newest first. Empty metode is shown as "Tunai" (cash).

Parameter
ParamKeteranganDescription
from, toRentang tanggal (maks 366 hari).Date range (≤366 days).
page, perPagination.Pagination.
Contoh responseExample response — 200
{
  "from": "2026-08-01", "to": "2026-08-07", "page": 1, "per": 50,
  "data": [
    { "id": 26612345, "toko": 12, "tanggal": "2026-08-07", "waktu": "14:22:31",
      "nota": "KM26877102", "total": 57000, "refund": 0, "metode": "QrisToko", "piutang": 0 }
  ]
}

GET /v1/transaksi/detail transaksi

Satu nota lengkap dengan rincian biaya dan item. total_baris = harga total baris (sudah × qty, setelah diskon item).One receipt with charge breakdown and items. total_baris = the line total (already × qty, after item discount).

Parameter
ParamKeteranganDescription
id*id nota dari /v1/transaksi.Receipt id from /v1/transaksi.
Contoh responseExample response — 200
{
  "nota": {
    "id": 26612345, "toko": 12, "tanggal": "2026-08-07", "waktu": "14:22:31",
    "no": "KM26877102", "subtotal": 52000, "diskon": 0, "pajak": 5000,
    "layanan": 0, "ongkir": 0, "total": 57000, "refund": 0, "metode": "QrisToko"
  },
  "items": [
    { "nama": "Kopi Susu Gula Aren", "qty": 2, "qty_retur": 0, "total_baris": 44000, "nilai_retur": 0 },
    { "nama": "Es Teh Manis",        "qty": 1, "qty_retur": 0, "total_baris": 8000,  "nilai_retur": 0 }
  ]
}

POST /v1/order order Baca+Tulis

Buat pesanan Toko Online + kode QRIS dalam satu panggilan. Harga dihitung server mengikuti aturan toko (promo / harga grosir / harga pelanggan). Pesanan langsung tampil di aplikasi kasir sebagai pesanan online; setelah QRIS dibayar, nota dibuat otomatis.

Create an online-store order plus a QRIS payment code in one call. Prices are computed server-side following the store's rules (promos / wholesale / customer pricing). The order appears in the cashier app immediately; once the QRIS is paid, the receipt is created automatically.

Body (JSON)
FieldKeteranganDescription
nama*Nama pemesan.Customer name.
nohpNo. HP pemesan (9–15 digit; opsional). Bila diisi, pelanggan otomatis terdaftar/tertaut.Customer phone (9–15 digits; optional). If present, the customer is auto-created/linked.
meja_idOpsional — id meja untuk pesanan dine-in.Optional — table id for dine-in orders.
items*Maks 100 baris: {produk_id*, varian_id, qty* (1–999), catatan}.Max 100 lines: {produk_id*, varian_id, qty* (1–999), catatan}.
ContohExample
curl -X POST https://api.kasirpro.com/v1/order \
  -H "Authorization: Bearer kp_live_..." -H "Content-Type: application/json" \
  -d '{
    "nama": "Budi", "nohp": "081234567890",
    "items": [
      { "produk_id": 345, "qty": 2 },
      { "produk_id": 351, "qty": 1, "catatan": "tanpa gula" }
    ]
  }'
Contoh responseExample response — 201
{
  "ok": true,
  "order_id": 9812,
  "savednota_id": 5541,
  "qris": {
    "qris_id": "qr_8f2f6c1e-2c3a-4f6d-9d21-7f1b2a9c0e55",
    "qr_string": "00020101021226670016ID.CO.XENDIT.WWW01189360091100...6304A1B2",
    "amount": 59000,
    "orderid": 77120,
    "expires_at": "2026-08-26T09:35:00.000Z"
  },
  "catatan": "Render qris.qr_string sebagai QR code utk dibayar. Cek pembayaran lewat GET /v1/order/status?id=9812. Pesanan tampil di aplikasi kasir sebagai pesanan online."
}

qr_string dirender menjadi gambar QR (QRIS dinamis, kedaluwarsa ±30 menit). amount sudah termasuk pajak/biaya sesuai pengaturan toko.

Render qr_string as a QR image (dynamic QRIS, expires in ~30 minutes). amount already includes tax/charges per the store's settings.

GET /v1/order/status order

Status pembayaran pesanan. Poll tiap 5–10 detik sampai paid:true atau ±30 menit (QRIS kedaluwarsa).Order payment status. Poll every 5–10 seconds until paid:true or ~30 minutes (QRIS expiry).

Parameter
ParamKeteranganDescription
id*order_id dari POST /v1/order.order_id from POST /v1/order.
Contoh responseExample response — 200
// belum dibayar / unpaid:
{ "order_id": 9812, "paid": false, "status": "pending", "total": 59000 }

// sudah dibayar / paid:
{ "order_id": 9812, "paid": true, "status": "settlement", "total": 59000 }

Praktik Terbaik

  • Mulai dengan GET /v1/me untuk mengetahui toko, mode, dan scope kunci.
  • Cache data master (/v1/toko, /v1/produk) — jarang berubah.
  • Saat 429, tunggu sesuai Retry-After; jangan retry agresif.
  • Simpan kunci sebagai environment variable; jangan pernah tanam di kode yang dibagikan.
  • Versi markdown dokumen ini: /llms.txt (mis. untuk dimasukkan ke konteks AI agent).

Best Practices

  • Start with GET /v1/me to learn the key's store, mode and scopes.
  • Cache master data (/v1/toko, /v1/produk) — it changes rarely.
  • On 429, wait per Retry-After; never retry aggressively.
  • Keep keys in environment variables; never embed them in shared code.
  • Markdown version of this document: /llms.txt (e.g. to feed into an AI agent's context).

KasirPro · backoffice.kasirpro.com