Beta

Langganan

Beta — tagihan berulang, ditagih lewat QRIS tiap siklus.

Beta, tertutup. Endpoint ini menjawab 404 untuk semua akun kecuali beberapa yang kami aktifkan manual — jadi untuk sekarang akan 404 juga di Anda, dan itu bukan masalah di key Anda. Formatnya kami publikasikan sekarang supaya Anda bisa mulai menyiapkan integrasi, dan masih mungkin berubah sebelum rilis umum. Referensi lengkapnya ada di /v1/openapi.json. Hubungi kami kalau mau ikut.

Tiap siklus menerbitkan satu invoice, dan pelanggan menyetujui pembayaran QRIS untuk invoice itu. Tidak ada kartu tersimpan dan tidak ada yang ditagih otomatis — perpanjangan terjadi karena ada orang yang scan.

Bentuknya

Customer adalah orang yang Anda tagih. Plan adalah harga dan siklusnya. Subscription menggabungkan keduanya. Tiap siklus terbit satu invoice, dan tiap invoice punya payment request yang bisa Anda arahkan ke pelanggan.

1. Siapkan plan dan customer

curl __BASE__/v1/subscription_plans \
  -H "Authorization: Bearer kp_test_..." \
  -H "Content-Type: application/json" \
  -d '{"code":"basic","name":"Bulanan","amount":150000,"interval_unit":"month"}'

curl __BASE__/v1/subscription_customers \
  -H "Authorization: Bearer kp_test_..." \
  -H "Content-Type: application/json" \
  -d '{"name":"Budi","phone":"+628123456789","external_id":"crm-42"}'

Kirim external_id kalau Anda punya id sendiri. Mengirim id yang sama lagi akan memperbarui customer itu, bukan bikin yang kedua — ini yang bikin import aman diulang.

amount tetap wajib walaupun isinya 0. Plan gratis itu plan beneran, jadi field yang kosong tidak bisa diartikan sebagai gratis.

2. Mulai langganan

curl __BASE__/v1/subscriptions \
  -H "Authorization: Bearer kp_test_..." \
  -H "Content-Type: application/json" \
  -d '{"customer_id":"cust_...","plan_id":"plan_..."}'

Siklus pertama langsung ditagih, jadi invoice pertama sudah ada saat response ini kembali. Kalau plan-nya punya trial, belum ada invoice sampai trial-nya habis — trial yang tidak lanjut tidak pernah muncul di invoice sama sekali.

3. Menagih

Baca invoice-nya, ambil payment_request_id, lalu ambil itu dari GET /v1/transactions/{id} untuk dapat QRIS-nya. Invoice hidup lebih lama dari percobaan bayarnya: kode QRIS mati dalam sejam, invoice jatuh temponya beberapa hari, dan percobaan baru menggantikan yang sudah mati.

4. Beri akses lewat paid_through, bukan status

status itu posisi langganan dalam siklus hidupnya. paid_through itu boleh-tidaknya pelanggan memakai layanan Anda sekarang. Dua pertanyaan yang berbeda.

Pelanggan past_due yang masih di dalam periode yang sudah dia bayar tetap punya akses — memang untuk itu masa tenggangnya ada. Kalau Anda cek status saja, pelanggan yang membayar akan terputus begitu satu invoice telat.

const ok = sub.paid_through && new Date() < new Date(sub.paid_through);

5. Kalau telat bayar

Invoice yang belum dibayar lewat masa tenggang memindahkan langganan ke past_due dan memicu invoice.overdue. Akses tetap jalan sampai paid_through habis sendiri. Bayar telat tetap melunasi invoice-nya dan memperpanjang akses dari situ — tidak ada yang hangus.

6. Ubah dan berhenti

POST /v1/subscriptions/{id}/change berlaku di perpanjangan berikutnya, dan hanya di situ. Tidak ada opsi langsung: proration belum ada di rilis ini, dan menerapkan upgrade sebelum dibayar sama saja memberi layanan yang belum disetujui siapa pun. Nilai yang dijadwalkan muncul sebagai pending_plan_id dan pending_quantity sampai perpanjangan menerapkannya.

Berhenti dengan at_period_end: true tetap menghormati layanan yang sudah dibayar. Defaultnya menghentikan akses sekarang. Keduanya tidak mengembalikan dana.

Berhenti itu final. Pembayaran yang datang setelahnya tetap melunasi invoice-nya — utangnya memang nyata — tapi tidak memberi akses dan tidak menghidupkan penagihan lagi. Cancel kedua kali dijawab 409 already_canceled, bukan karena request Anda salah.

Webhook

invoice.issued, invoice.paid, invoice.overdue, invoice.voided, dan event siklus hidup subscription.*. Isi body-nya sama persis dengan objek yang dikembalikan API ini, jadi yang Anda simpan dari webhook dan yang Anda ambil lewat GET itu barang yang sama.

Pengiriman bersifat at-least-once. Dedup pakai Kasera-Event-Id dan anggap urutannya bisa tertukar — event itu penanda untuk membaca objeknya, bukan pengganti membacanya.

Test mode

Key kp_test_ membuat langganan sandbox. Payment request-nya sandbox dan tidak ada pengingat yang dikirim ke siapa pun, jadi nomor asli tidak akan pernah menerima pesan dari langganan yang cuma Anda coba-coba.

Yang belum ada

Untuk sekarang baru siklus bulanan ke bawah. Proration, kode kupon, dan pembayaran sebagian belum ada di rilis ini, dan auto-debit memang tidak ada — tiap siklus disetujui pelanggan.