Dokumentasi API Pembayaran
Terima pembayaran lewat Virtual Account dan QRIS dengan satu antarmuka. Seluruh contoh pada halaman ini dapat langsung dicoba memakai kunci sandbox tanpa melibatkan dana sungguhan.
Mulai cepat
Tiga langkah sampai pembayaran pertama Anda terbentuk.
- Daftar dan terbitkan kunci sandbox dari halaman ringkasan.
- Kirim permintaan pembuatan pembayaran seperti contoh di bawah.
- Daftarkan alamat notifikasi agar sistem Anda tahu ketika pelanggan sudah membayar.
curl -X POST http://localhost:3040/api/v1/payments \
-H "Authorization: Bearer lg_sandbox_kunci_anda" \
-H "Idempotency-Key: PESANAN-0001" \
-H "Content-Type: application/json" \
-d '{
"reference_id": "PESANAN-0001",
"amount": 150000,
"method": { "type": "VIRTUAL_ACCOUNT", "channel": "BNI" }
}'lg_sandbox_ memakai lingkungan uji penyedia pembayaran. Nomor Virtual Account yang terbentuk sungguhan, tetapi tidak ada dana yang berpindah.Pendaftaran lewat API
Bila Anda memasang layanan ini di dalam produk Anda sendiri, merchant dapat didaftarkan langsung dari peladen Anda tanpa membuka halaman web. Kunci API sandbox diterbitkan pada jawaban yang sama, sehingga integrasi dapat berjalan seketika.
curl -X POST https://api.langsunggas.shop/api/v1/merchants \
-H "Content-Type: application/json" \
-d '{
"email": "owner@usaha-anda.com",
"password": "kata-sandi-minimal-12",
"legal_name": "PT Usaha Anda Sejahtera",
"display_name": "Usaha Anda",
"scopes": ["payments:write", "payments:read", "payouts:read"]
}'| Kolom | Wajib | Keterangan |
|---|---|---|
email | Ya | Surel pemilik akun, dipakai untuk masuk |
password | Ya | Minimal 12 karakter |
legal_name | Ya | Nama usaha resmi, minimal 3 karakter |
display_name | Ya | Nama yang dilihat pelanggan, minimal 2 karakter |
country_code | Tidak | Dua huruf, bawaannya ID |
scopes | Tidak | Izin kunci pertama. Bawaannya payments:write dan payments:read. Izin di luar daftar yang diizinkan diabaikan, bukan menggagalkan pendaftaran |
Jawaban berstatus 201.
{
"merchant": {
"id": "mch_xxxxxxxxxxxx",
"legal_name": "PT Usaha Anda Sejahtera",
"display_name": "Usaha Anda",
"status": "ACTIVE_SANDBOX"
},
"api_key": {
"id": "key_xxxxxxxxxxxx",
"prefix": "a1b2c3d4e5f6",
"secret": "lg_sandbox_a1b2c3d4e5f6_xxxxxxxxxxxxxxxxxxxx",
"environment": "SANDBOX",
"scopes": ["payments:write", "payments:read"],
"grantable_scopes": [
"payments:write",
"payments:read",
"payouts:read",
"crypto-withdrawals:read"
]
},
"next_steps": [
"Simpan nilai api_key.secret sekarang. Nilai itu tidak dapat dibaca kembali.",
"Panggil GET /api/v1/channels untuk melihat kanal pembayaran yang tersedia.",
"Kirim berkas kelayakan usaha lewat POST /api/v1/kyb sebelum memakai mode live.",
"Izin menulis pencairan dan penarikan kripto dibuka operator bersamaan dengan kenaikan ke mode live."
],
"request_id": "req_xxxxxxxx"
}api_key.secret tidak pernah dapat dibaca kembali, termasuk oleh kami. Simpan pada penyimpanan rahasia Anda saat jawaban diterima. Bila hilang, cabut kunci itu dan terbitkan yang baru dari halaman ringkasan.lg_sandbox_ dengan izin payments:write dan payments:read. Mode langsung dan izin pencairan menuntut pemeriksaan kelayakan usaha oleh tim kami, karena keduanya menyentuh dana sungguhan.Bila operator memasang kunci penjaga, sertakan tajuk X-Signup-Secret. Tanpa tajuk itu jawabannya 401 UNAUTHORIZED.
| Kode | Arti |
|---|---|
409 EMAIL_TAKEN | Surel sudah terdaftar |
400 WEAK_PASSWORD | Kata sandi kurang dari 12 karakter |
400 VALIDATION_ERROR | Kolom tidak lengkap atau tidak sesuai |
429 RATE_LIMITED | Lebih dari 5 pendaftaran per jam dari satu alamat IP |
500 API_KEY_ISSUE_FAILED | Merchant terbentuk tetapi kunci gagal diterbitkan. Jangan mendaftar ulang, hubungi operator |
Kunci pertama membawa izin pembayaran saja bila kolom scopes dikosongkan. Sertakan kolom itu untuk meminta izin membaca pencairan atau penarikan kripto, sehingga integrasi Anda dapat disiapkan lebih dahulu.
| Izin | Dapat diminta saat mendaftar |
|---|---|
payments:write | Ya. Membuat tagihan |
payments:read | Ya. Membaca tagihan, kanal, riwayat notifikasi |
payouts:read | Ya. Membaca saldo, mutasi, dan riwayat pencairan |
crypto-withdrawals:read | Ya. Membaca alamat dan riwayat penarikan USDT |
payouts:write | Tidak. Dibuka operator bersamaan dengan kenaikan ke mode langsung |
crypto-withdrawals:write | Tidak. Dibuka operator bersamaan dengan kenaikan ke mode langsung |
payouts:write tidak menggagalkan pendaftaran; izin itu hanya tidak diberikan. Membatalkan seluruh proses karena satu izin akan memaksa Anda mengulang semuanya, padahal maksudnya sudah jelas. Bacalah api_key.scopes pada jawaban untuk mengetahui izin yang benar-benar menempel, dan api_key.grantable_scopes untuk daftar yang dapat diminta.Autentikasi
Setiap permintaan menyertakan kunci pada tajuk Authorization.
Authorization: Bearer lg_sandbox_a1b2c3d4_xxxxxxxxxxxxxxxx Idempotency-Key: PESANAN-0001 Content-Type: application/json
| Awalan | Lingkungan | Keterangan |
|---|---|---|
lg_sandbox_ | Sandbox | Untuk mencoba integrasi, tanpa dana sungguhan |
lg_live_ | Produksi | Memproses dana sungguhan |
Setiap kunci membawa daftar izin. Permintaan di luar izin kunci dijawab 403 FORBIDDEN.
| Izin | Memberi akses ke |
|---|---|
payments:write | Membuat pembayaran |
payments:read | Membaca pembayaran |
payouts:write | Mengajukan pencairan dana |
payouts:read | Membaca pencairan dana |
crypto-withdrawals:write | Mendaftarkan alamat dan mengajukan penarikan USDT |
crypto-withdrawals:read | Membaca penarikan USDT dan jejaknya |
Mengelola kunci lewat API
Kunci dapat didaftar, diterbitkan, dan dicabut tanpa membuka halaman web. Wewenangnya berasal dari kunci yang Anda pakai memanggil, sehingga seluruh daur hidup kunci dapat dijalankan dari peladen Anda sendiri.
Mengembalikan kunci pada lingkungan yang sama dengan kunci pemanggil. Hanya metadata; rahasia tidak pernah dapat dibaca ulang. Baris dengan current: true adalah kunci yang sedang Anda pakai.
curl https://api.langsunggas.shop/api/v1/api-keys \ -H "Authorization: Bearer lg_sandbox_kunci_anda"
{
"environment": "SANDBOX",
"active_limit": 10,
"active_count": 2,
"data": [
{
"id": "key_xxxxxxxxxxxx",
"prefix": "1ff77c9739cc",
"environment": "SANDBOX",
"scopes": ["payments:write", "payments:read"],
"current": true,
"status": "ACTIVE",
"created_at": "2026-10-10T09:59:44.980Z",
"last_used_at": "2026-10-10T09:59:45.623Z",
"revoked_at": null
}
]
}Menerbitkan kunci baru. Kolom scopes boleh dikosongkan untuk menyalin izin kunci pemanggil. Lingkungan tidak dapat diminta, selalu mengikuti kunci pemanggil.
curl -X POST https://api.langsunggas.shop/api/v1/api-keys \
-H "Authorization: Bearer lg_sandbox_kunci_anda" \
-H "Content-Type: application/json" \
-d '{ "scopes": ["payments:read"] }'403 SCOPE_ESCALATION. Tanpa aturan ini, satu kunci pembayaran yang bocor dapat dipakai menerbitkan kunci pencairan, lalu mengeluarkan dana Anda.Pola yang disarankan adalah menerbitkan kunci sesempit mungkin untuk setiap pemakaian. Kunci yang hanya membaca status pembayaran cukup berizin payments:read, sehingga kebocorannya tidak dapat dipakai membuat tagihan.
Mencabut kunci. Id dapat dikirim lewat kueri ?api_key_id= atau badan JSON. Pencabutan bersifat idempoten; mengulanginya dijawab 200 dengan already_revoked: true.
curl -X DELETE \ "https://api.langsunggas.shop/api/v1/api-keys?api_key_id=key_xxxxxxxxxxxx" \ -H "Authorization: Bearer lg_sandbox_kunci_anda"
{
"id": "key_xxxxxxxxxxxx",
"prefix": "1ff77c9739cc",
"status": "REVOKED",
"already_revoked": false,
"self_revoked": false,
"request_id": "req_xxxxxxxx"
}| Kode | Arti |
|---|---|
403 SCOPE_ESCALATION | Izin yang diminta melampaui izin kunci pemanggil |
409 KEY_LIMIT_REACHED | Kunci aktif sudah 10 pada lingkungan ini |
409 LAST_ACTIVE_KEY | Kunci aktif terakhir tidak dapat dicabut |
404 NOT_FOUND | Kunci bukan milik merchant Anda atau berada di lingkungan lain |
Kolom environment menentukan lingkungan kunci baru. Dikosongkan berarti menyalin lingkungan kunci pemanggil. Inilah cara memperoleh kunci sungguhan tanpa membuka dasbor: kunci pertama Anda selalu lahir sebagai kunci uji, sehingga tanpa kolom ini mode langsung tidak akan pernah terjangkau.
ACTIVE_LIVE. Selama masih ACTIVE_SANDBOX, permintaan dijawab 409 ENVIRONMENT_NOT_ALLOWED. Akun yang ditangguhkan kehilangan kedua lingkungan.Aturan izin tetap berlaku terpisah dari lingkungan: kunci baru tidak pernah boleh melampaui izin pemanggilnya, sehingga kunci sungguhan yang Anda terbitkan sendiri paling banyak memegang izin yang sudah Anda miliki. Untuk menambah izin menulis pencairan, hubungi operator.
Keterangan akun
Memeriksa keadaan akun Anda sendiri beserta izin kunci yang sedang dipakai. Berguna bagi integrasi yang berjalan tanpa membuka dasbor, karena tiga hal pada jawaban ini menentukan perilaku yang benar: lingkungan yang boleh dipakai, cara pencairan diproses, dan tarif yang dikenakan.
curl https://api.langsunggas.shop/api/v1/me \ -H "Authorization: Bearer lg_sandbox_kunci_anda"
{
"merchant": {
"id": "mch_xxxxxxxxxxxx",
"legal_name": "PT Usaha Anda Sejahtera",
"display_name": "Usaha Anda",
"status": "ACTIVE_SANDBOX",
"country_code": "ID",
"created_at": "2026-10-10T10:31:21.302Z",
"suspended_at": null,
"suspended_reason": null,
"kyb_status": "PENDING",
"live_enabled": false,
"allowed_environments": ["SANDBOX"],
"disbursement_mode": "MANUAL"
},
"api_key": {
"id": "key_xxxxxxxxxxxx",
"environment": "SANDBOX",
"scopes": ["payments:write", "payments:read"]
},
"fees": {
"plan": "Tarif Umum v1",
"rules": [
{ "payment_method": "VIRTUAL_ACCOUNT", "calc_type": "FLAT", "flat_amount": 4000, "percentage_bps": 0 },
{ "payment_method": "QRIS", "calc_type": "PERCENTAGE", "flat_amount": 0, "percentage_bps": 70 }
]
}
}| Kolom | Arti |
|---|---|
status | Keadaan merchant. ACTIVE_SANDBOX hanya dapat menguji, ACTIVE_LIVE dapat memproses dana sungguhan |
live_enabled | Jalan pintas untuk memeriksa apakah mode langsung sudah terbuka |
allowed_environments | Lingkungan yang sah bagi status saat ini. Kosong berarti akun sedang tidak dapat memproses apa pun |
kyb_status | Keadaan pemeriksaan kelayakan usaha yang menentukan kenaikan ke mode langsung |
disbursement_mode | MANUAL berarti pencairan menunggu persetujuan operator, AUTOMATIC langsung diteruskan |
suspended_reason | Sebab penangguhan, bila ada |
fees.rules | Tarif yang sedang berlaku. percentage_bps bersatuan seperseratus persen, sehingga 70 berarti 0,7 persen |
MERCHANT_NOT_ACTIVE, bacalah status dan suspended_reason lebih dahulu. Keduanya menjelaskan sebabnya tanpa perlu menghubungi kami.MANUAL, pencairan berhenti pada status menunggu sampai operator menyetujui, sehingga sistem Anda tidak boleh menganggapnya gagal hanya karena belum selesai. Pada AUTOMATIC, pencairan diteruskan ke penyedia seketika.Endpoint ini tidak menuntut izin khusus, karena mengetahui keadaan akun sendiri adalah hak setiap pemegang kunci yang sah dan tidak ada angka dana yang disertakan. Untuk saldo, pakai GET /api/v1/balance.
Kelayakan usaha (KYB)
Kunci yang terbit dari pendaftaran lewat API selalu berlingkungan uji. Agar akun dapat memproses dana sungguhan, data kelayakan usaha harus dikirim dan ditinjau lebih dahulu. Kedua endpoint ini membuat seluruh langkahnya dapat ditempuh tanpa membuka dasbor.
Berkas kelayakan mengikat badan usaha, bukan lingkungan, sehingga kunci uji pun dapat memakainya. Memang justru merchant yang masih di lingkungan uji yang membutuhkannya.
curl https://api.langsunggas.shop/api/v1/kyb \ -H "Authorization: Bearer lg_sandbox_kunci_anda"
{
"status": "PENDING",
"next_step": "SUBMIT_DOCUMENTS",
"can_submit": true,
"merchant_status": "ACTIVE_SANDBOX",
"live_enabled": false,
"submitted_at": null,
"reviewed_at": null,
"rejection_reason": null,
"business": {
"business_type": null,
"registration_number": null,
"tax_number": null,
"website_url": null,
"contact_phone": null,
"business_address": null,
"document_urls": []
}
}Bacalah next_step dan ikuti nilainya, jangan menyimpulkan sendiri dari status. Pemetaan status ke tindakan adalah aturan kami dan dapat berkembang, sedangkan nilai pada kolom ini akan tetap menunjuk tindakan yang benar.
| next_step | Yang perlu Anda lakukan |
|---|---|
SUBMIT_DOCUMENTS | Berkas belum pernah dikirim. Kirim dengan POST /api/v1/kyb |
WAIT_REVIEW | Berkas sedang ditinjau operator. Tidak ada yang perlu dilakukan selain menunggu |
RESUBMIT_DOCUMENTS | Berkas ditolak. Baca rejection_reason, perbaiki, lalu kirim ulang |
WAIT_LIVE_ACTIVATION | Berkas disetujui. Tinggal menunggu operator membuka lingkungan sungguhan |
NONE | Lingkungan sungguhan sudah terbuka. Tidak ada langkah tersisa |
curl -X POST https://api.langsunggas.shop/api/v1/kyb \
-H "Authorization: Bearer lg_sandbox_kunci_anda" \
-H "Content-Type: application/json" \
-d '{
"business_type": "Perdagangan daring",
"registration_number": "AHU-0012345-AH-01-01",
"tax_number": "01.234.567.8-901.000",
"website_url": "https://usahaanda.co.id",
"contact_phone": "081200001111",
"business_address": "Jalan Merdeka Nomor 10, Jakarta Selatan, DKI Jakarta",
"document_urls": [
"https://berkas.usahaanda.co.id/akta.pdf",
"https://berkas.usahaanda.co.id/npwp.pdf"
]
}'{
"status": "IN_REVIEW",
"next_step": "WAIT_REVIEW",
"message": "Berkas dikirim dan menunggu peninjauan operator."
}| Kolom | Wajib | Keterangan |
|---|---|---|
business_type | Ya | Jenis usaha, 2 sampai 80 aksara |
registration_number | Ya | Nomor izin usaha, 3 sampai 60 aksara |
contact_phone | Ya | Nomor telepon yang dapat dihubungi peninjau, 8 sampai 30 aksara |
business_address | Ya | Alamat usaha lengkap, 10 sampai 300 aksara |
document_urls | Ya | 1 sampai 6 tautan https ke dokumen pendukung |
tax_number | Tidak | Nomor pokok wajib pajak, paling banyak 60 aksara |
website_url | Tidak | Alamat situs usaha. Bila diisi harus berupa http atau https yang sah |
https. Pastikan tautan dapat dibuka peninjau selama masa peninjauan, karena tautan mati akan berujung penolakan.APPROVED menyatakan kelayakan usaha Anda diterima, bukan bahwa lingkungan sungguhan sudah terbuka. Pembukaan jalur dana nyata adalah tindakan terpisah, agar tidak ada satu keputusan yang sekaligus menilai kelayakan dan mengalirkan dana. Pantau live_enabled.| Galat | Sebab |
|---|---|
400 VALIDATION_ERROR | Kolom wajib kurang, alamat usaha terlalu pendek, atau tautan dokumen bukan https |
409 KYB_STATE_CONFLICT | Berkas sedang ditinjau atau sudah disetujui, sehingga tidak dapat ditimpa |
403 FORBIDDEN | Scope kunci tidak mencukupi. Membaca butuh payments:read, mengirim butuh payments:write |
429 RATE_LIMITED | Pengiriman dibatasi per merchant karena setiap kiriman memicu peninjauan manusia |
Kanal pembayaran
Daftar kanal yang benar-benar dapat Anda pakai, sudah dikelompokkan dan mengikuti lingkungan kunci yang dipakai. Gunakan ini untuk menyusun pilihan pembayaran, agar Anda tidak menawarkan kanal yang akan ditolak saat tagihan dibuat.
curl https://api.langsunggas.example/api/v1/channels \ -H "Authorization: Bearer lg_sk_test_xxxxxxxx"
{
"environment": "SANDBOX",
"total": 9,
"data": [
{
"group": "VIRTUAL_ACCOUNT",
"group_name": "Virtual Account",
"channels": [
{
"code": "BNI",
"name": "Bank BNI",
"method_type": "VIRTUAL_ACCOUNT",
"description": "Virtual account nominal terkunci",
"available": true
}
]
},
{
"group": "QR",
"group_name": "QRIS",
"channels": [
{
"code": "QRIS",
"name": "QRIS",
"method_type": "QRIS",
"description": "Pindai kode dari aplikasi apa pun yang mendukung QRIS",
"available": true
}
]
}
]
}| Kelompok | Isi |
|---|---|
VIRTUAL_ACCOUNT | Transfer ke nomor virtual account bank |
QR | QRIS |
OVER_THE_COUNTER | Bayar tunai di minimarket |
EWALLET | E-Money |
CRYPTO | USDT di jaringan TRON dan BSC |
PAYLATER | Bayar nanti |
Kolom code adalah nilai yang Anda kirim padamethod.channel, sedangkan method_typeadalah nilai untuk method.type. Khusus kelompokCRYPTO, keduanya bernilai sama danmethod.channel tidak perlu dikirim.
USDT_TRC20 dan USDT_BEP20 harus dinyalakan lebih dahulu pada menu Kanal Pembayaran. Menerima pembayaran kripto adalah keputusan usaha, sehingga tidak pernah menyala tanpa tindakan Anda.?include_disabled=true bila Anda perlu melihat kanal yang sedang mati beserta alasannya.Pada mode tersebut, setiap kanal membawa available danblocked_reason.
| Alasan | Arti |
|---|---|
DIMATIKAN_OPERATOR | Ditutup operator, biasanya karena bank sedang bermasalah. Tidak dapat Anda nyalakan sendiri. |
DIMATIKAN_MERCHANT | Anda matikan sendiri. Nyalakan lagi dari halaman Kanal Pembayaran. |
TIDAK_DIDUKUNG | Kanal belum tersedia pada lingkungan ini. |
Menyalakan dan mematikan kanal
Mengubah kanal yang Anda tawarkan tanpa membuka dasbor. Lingkungan tidak pernah diminta, selalu diambil dari kunci, sehingga kanal produksi tidak dapat diubah memakai kunci uji.
curl -X PATCH https://api.langsunggas.shop/api/v1/channels \
-H "Authorization: Bearer lg_sandbox_kunci_anda" \
-H "Content-Type: application/json" \
-d '{ "channel": "BNI", "enabled": false }'{
"channel": "BNI",
"enabled": false,
"environment": "SANDBOX"
}409 BLOCKED_BY_PLATFORM. Menawarkan kanal yang tidak dapat ditepati saat pelanggan membayar lebih merugikan daripada tidak menawarkannya. Mematikan kanal selalu boleh.| Galat | Sebab |
|---|---|
404 UNKNOWN_CHANNEL | Kode kanal tidak ada pada katalog |
409 BLOCKED_BY_PLATFORM | Kanal sedang ditutup operator |
400 UNSUPPORTED_CHANNEL | Kanal ada pada katalog tetapi belum didukung sistem |
403 FORBIDDEN | Scope payments:write tidak dimiliki kunci |
Membuat pembayaran
Virtual Account:
{
"reference_id": "PESANAN-2026-0001",
"amount": 275000,
"method": { "type": "VIRTUAL_ACCOUNT", "channel": "BNI" },
"customer": { "name": "Budi Santoso" }
}QRIS:
{
"reference_id": "PESANAN-2026-0002",
"amount": 45000,
"method": { "type": "QRIS" }
}Jawaban berhasil dengan kode 201:
{
"id": "pay_xxxxxxxxxxxx",
"reference_id": "PESANAN-2026-0001",
"status": "PENDING",
"amount": 275000,
"currency": "IDR",
"method": {
"type": "VIRTUAL_ACCOUNT",
"channel": "BNI",
"accountNumber": "8808999979278987",
"accountName": "XDT-InoPay"
},
"expires_at": "2026-08-21T03:59:21.317Z",
"created_at": "2026-08-21T02:59:21.631Z"
}| Kolom | Wajib | Keterangan |
|---|---|---|
reference_id | Ya | Nomor pesanan Anda. Harus unik untuk setiap tagihan. |
amount | Ya | Nominal dalam rupiah penuh, tanpa desimal. Paling sedikit 1.000. |
method.type | Ya | VIRTUAL_ACCOUNT atau QRIS. |
method.channel | Untuk VA | Kode bank dari GET /api/v1/channels, misalnya BNI, BRI, MANDIRI. |
expires_at | Tidak | Waktu kedaluwarsa. Bawaannya enam puluh menit. |
customer | Tidak | Nama dan surel pelanggan. |
metadata | Tidak | Data tambahan milik Anda, dikembalikan apa adanya. |
Idempotensi
Tajuk Idempotency-Key wajib disertakan pada setiap pembuatan pembayaran. Tajuk ini mencegah tagihan ganda ketika jaringan bermasalah dan permintaan yang sama terkirim dua kali.
| Keadaan | Yang terjadi |
|---|---|
| Kunci sama, isi sama | Jawaban pertama dikembalikan. Tidak ada pembayaran baru. |
| Kunci sama, isi berbeda | Ditolak dengan kode 409. |
| Kunci berbeda | Pembayaran baru dibuat. |
Membaca pembayaran
Daftar memakai penomoran berbasis kursor. Sertakan nilainext_cursor dari jawaban sebelumnya untuk mengambil halaman berikutnya.
| Parameter | Bawaan | Keterangan |
|---|---|---|
status | semua | Saring menurut satu status, misalnya PAID atau EXPIRED. |
limit | 20 | Jumlah baris per halaman, paling banyak 100. |
cursor | kosong | Isi dengan next_cursor dari jawaban sebelumnya. |
{
"data": [
{
"id": "pay_xxxxxxxxxxxx",
"status": "PAID",
"amount": 275000,
"paid_at": "2026-08-21T03:01:04Z"
}
],
"has_more": true,
"next_cursor": "cmt2xxxxxxxxxx"
}Biaya layanan
Setiap pembayaran yang lunas dikenai biaya layanan. Nominal yang masuk ke dompet Anda adalah nominal yang dibayar pelanggan dikurangi biaya tersebut, bukan nominal penuh.
Besaran biaya ditetapkan operator dan dapat berbeda antar merchant sesuai kesepakatan. Tarif yang berlaku bagi akun Anda dapat ditanyakan kepada operator.
Karena itu, jangan menghitung penerimaan dari nominal tagihan. Pakai saldo pada halaman Dompet atau catatan mutasi, yang sudah memperhitungkan potongan.
Saldo dan mutasi dompet
Saldo dan mutasi dapat dibaca langsung dari peladen Anda untuk keperluan rekonsiliasi, tanpa membuka dasbor.
curl https://api.langsunggas.shop/api/v1/balance \ -H "Authorization: Bearer lg_live_kunci_anda"
{
"environment": "LIVE",
"idr": {
"currency": "IDR",
"available": 542000,
"pending": 0,
"total": 542000,
"minimum_payout": 10000
},
"usdt": {
"currency": "USDT",
"available": 0,
"available_display": "0",
"decimals": 6
}
}| Kolom | Arti |
|---|---|
idr.available | Dana rupiah yang dapat dicairkan saat ini |
idr.pending | Dana yang sedang dalam proses pencairan |
idr.total | Jumlah available dan pending |
idr.minimum_payout | Nominal pencairan terkecil yang akan diterima. Ditentukan operator dan dapat berubah |
usdt.available | Saldo USDT dalam mikro-USDT, yaitu USDT dikali satu juta |
usdt.available_display | Saldo USDT yang sudah dijadikan bentuk mudah dibaca |
minimum_payout ditentukan operator dan dapat berubah. Menyalinnya menjadi tetapan di sisi Anda membuat pengajuan pencairan tertolak tanpa sebab yang jelas ketika nilainya berubah.Mutasi dompet rupiah, terbaru lebih dahulu. Parameter limit paling banyak 100 dengan bawaan 30, dan offset dipakai untuk melanjutkan ke halaman berikutnya selama has_more masih benar.
curl \ "https://api.langsunggas.shop/api/v1/wallet-entries?limit=20&offset=0" \ -H "Authorization: Bearer lg_live_kunci_anda"
{
"environment": "LIVE",
"currency": "IDR",
"limit": 20,
"offset": 0,
"has_more": false,
"data": [
{
"occurred_at": "2026-10-10T10:24:06.514Z",
"description": "Pembayaran diterima",
"direction": "CREDIT",
"amount": 346000,
"reference_id": "PESANAN-2026-0001"
},
{
"occurred_at": "2026-10-09T08:11:02.003Z",
"description": "Pencairan selesai",
"direction": "DEBIT",
"amount": 500000,
"reference_id": null
}
]
}Nilai direction dilihat dari sudut pandang dompet Anda: CREDIT berarti dana masuk, dan DEBIT berarti dana keluar.
idr.available, dan selisih di antara keduanya tidak mungkin terjadi.Kedua endpoint menuntut izin payouts:read, bukan payments:read. Saldo menyangkut dana yang tersimpan, sehingga kunci yang hanya membuat tagihan tidak perlu mengetahuinya.
Pencairan dana
Saldo yang terkumpul dari pembayaran lunas dapat ditarik ke rekening bank yang sudah terverifikasi. Nominal ditahan sejak permintaan dibuat, sehingga saldo tidak dapat dipakai dua kali.
Kode bank tujuan tidak boleh ditebak. Ambil daftarnya dari sini, lalu pakai nilai code apa adanya saat menambah rekening tujuan. Scope yang dibutuhkanpayouts:read.
| Parameter | Wajib | Keterangan |
|---|---|---|
search | Tidak | Menyaring berdasarkan kode atau nama bank, tanpa membedakan huruf besar kecil. |
curl https://api.langsunggas.example/api/v1/payout-banks \ -H "Authorization: Bearer lg_live_a1b2c3d4_xxxxxxxxxxxxxxxx"
{
"environment": "LIVE",
"data": [
{
"code": "BCA",
"name": "Bank Central Asia (BCA)",
"can_validate_name": true
},
{
"code": "BNI",
"name": "Bank Negara Indonesia (BNI)",
"can_validate_name": true
}
],
"count": 149,
"request_id": "req_2f2f9a1c-2a6f-4f4a-9d18-0d6f6a52e9c1"
}Kolom can_validate_name menyatakan bahwa bank tersebut mendukung pencocokan nama pemilik rekening di sisi penyedia. Pemeriksaan itu belum aktif pada akun kami, sehingga nama pemilik tetap dicocokkan operator sebelum rekening dapat menerima dana. Perlakukan kolom ini sebagai keterangan, bukan jaminan bahwa nama sudah diperiksa.
| Kolom | Wajib | Keterangan |
|---|---|---|
reference_id | Ya | Penanda milik Anda, paling panjang 128 huruf. Dipakai menolak permintaan kembar. Mengirim ulang dengan penanda dan rincian yang sama mengembalikan catatan yang sudah ada. |
amount | Ya | Bilangan bulat rupiah. Batas terkecil ditetapkan operator; bawaannya 50.000. |
bank_code | Ya | Kode bank tujuan. Ambil dari GET /api/v1/payout-banks. |
account_number | Ya | Nomor rekening tujuan, hanya angka. |
account_name | Ya | Nama pemilik rekening sesuai buku tabungan. |
payout_account_id | Tidak | Penanda rekening tersimpan. Bila diisi, tiga kolom di atas tidak perlu. |
metadata | Tidak | Objek bebas, dikembalikan apa adanya pada catatan pencairan. |
Rekening tujuan disertakan langsung pada permintaan. Tidak ada pendaftaran yang harus dilakukan lebih dahulu.
Kode bank tidak boleh ditebak. Ambil dari GET /api/v1/payout-banks, lalu pakai nilai code apa adanya. Kode yang tidak dikenal penyedia dijawab BANK_NOT_FOUND.
payout_account_id tanpa rincian bank. Rekening tersimpan yang belum lolos pemeriksaan operator ditolak dengan ACCOUNT_NOT_VERIFIED.curl -X POST https://api.langsunggas.example/api/v1/payouts \
-H "Authorization: Bearer $LG_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"reference_id": "PO-2026-0001",
"amount": 250000,
"bank_code": "BNI",
"account_number": "1234567890",
"account_name": "PT Contoh Sejahtera",
"metadata": { "catatan": "penarikan mingguan" }
}'{
"id": "cmt2tsz6o000k3sywuw48ja4k",
"reference_id": "PO-2026-0001",
"amount": 250000,
"status": "PENDING_APPROVAL",
"mode": "MANUAL",
"requires_approval": true,
"created_at": "2026-08-21T10:48:11.040Z",
"request_id": "req_1cdd48a7-b96f-431c-b8b5-5e12f100cea9"
}Kunci API harus memiliki scope payouts:write untuk mengajukan dan payouts:read untuk membaca.
requires_approval. Bila bernilai benar, pencairan menunggu persetujuan operator dan belum diteruskan ke bank. Jangan menandai penarikan sebagai selesai sebelum status menjadiCOMPLETED.Mode pencairan ditetapkan oleh operator pada setiap merchant.
| Mode | Perilaku |
|---|---|
AUTOMATIC | Diteruskan ke bank seketika, selama nominal masih di bawah batas otomatis merchant. |
MANUAL | Selalu menunggu persetujuan operator. |
Nominal di atas batas otomatis tetap menunggu persetujuan, apa pun modenya.
| Status | Arti |
|---|---|
PENDING_APPROVAL | Menunggu persetujuan operator. Saldo sudah ditahan. |
APPROVED | Disetujui, sedang menuju bank. |
PROCESSING | Sudah diterima bank, menunggu penyelesaian. |
COMPLETED | Dana sampai di rekening tujuan. Status akhir. |
FAILED | Gagal. Dana dikembalikan ke saldo. Lihat failure_code. |
REJECTED | Ditolak operator. Dana dikembalikan ke saldo. |
{
"id": "cmt2tsz6o000k3sywuw48ja4k",
"reference_id": "PO-2026-0001",
"amount": 250000,
"status": "COMPLETED",
"mode": "MANUAL",
"failure_code": null,
"failure_message": null,
"created_at": "2026-08-21T10:48:11.040Z",
"approved_at": "2026-08-21T11:02:44.180Z",
"sent_at": "2026-08-21T11:02:46.902Z",
"completed_at": "2026-08-21T11:04:10.551Z",
"request_id": "req_d9019bf2-550f-4323-9e5d-8d3482ea00c6"
}Daftar memakai penomoran berbasis kursor, sama seperti daftar pembayaran. Hanya pencairan pada lingkungan kunci yang dipakai yang ditampilkan.
{
"data": [
{
"id": "cmt2tsz6o000k3sywuw48ja4k",
"reference_id": "PO-2026-0001",
"amount": 250000,
"status": "PENDING_APPROVAL",
"mode": "MANUAL",
"failure_code": null,
"failure_message": null,
"created_at": "2026-08-21T10:48:11.040Z",
"completed_at": null
}
],
"has_more": true,
"next_cursor": "cmt2tb5oe00333s84ei17uis1",
"request_id": "req_ee24eaa8-512c-4499-94d3-4251001593e8"
}| Kode | HTTP | Arti |
|---|---|---|
BELOW_MINIMUM | 400 | Nominal di bawah batas terkecil yang berlaku. |
ACCOUNT_INCOMPLETE | 400 | Rincian rekening tidak lengkap dan payout_account_id juga kosong. |
ACCOUNT_INVALID | 400 | Nomor rekening memuat selain angka. |
BANK_NOT_FOUND | 400 | Kode bank tidak dikenal penyedia pencairan. |
ACCOUNT_NOT_FOUND | 404 | Rekening tujuan tidak ditemukan. |
ACCOUNT_NOT_VERIFIED | 422 | Rekening tujuan belum terverifikasi. |
INSUFFICIENT_BALANCE | 422 | Saldo tersedia tidak mencukupi. |
REFERENCE_CONFLICT | 409 | reference_id sudah dipakai untuk pencairan dengan nominal atau rekening berbeda. |
PAYOUTS_HALTED | 503 | Pencairan sedang dihentikan sementara oleh operator. |
{
"error": {
"code": "BELOW_MINIMUM",
"message": "Nominal pencairan paling sedikit 50.000.",
"request_id": "req_93462893-ed67-4223-ab02-b0d1c0f91330",
"details": []
}
}REFERENCE_CONFLICT, bukan diterima sebagai pencairan baru. Aturan ini menjaga agar penanda yang keliru dipakai ulang tidak diam-diam dianggap sebagai permintaan yang sudah berhasil, sementara pencairan yang Anda maksud tidak pernah terjadi.Ketika pencairan mencapai keadaan akhir, kami mengirim notifikasi ke alamat yang sama dengan notifikasi pembayaran. Anda tidak perlu menanyakan status berulang kali.
| Jenis | Kapan dikirim |
|---|---|
payout.completed | Dana sampai di rekening tujuan. |
payout.failed | Gagal di bank, atau ditolak operator. Dana kembali ke saldo. |
{
"id": "evt_6adb8f7a-f2e4-4d07-8129-5f1cf650744e",
"type": "payout.completed",
"created_at": "2026-08-21T12:27:32.976Z",
"livemode": false,
"data": {
"payout_id": "cmt2xcq01000k3sm0uyk2nzoc",
"reference_id": "PO-2026-0001",
"amount": 200000,
"status": "COMPLETED"
}
}{
"id": "evt_66ac771b-5c82-4995-a199-8514ff2198f8",
"type": "payout.failed",
"created_at": "2026-08-21T12:27:35.309Z",
"livemode": false,
"data": {
"payout_id": "cmt2xcse600193sm0l3y4kfz1",
"reference_id": "PO-2026-0002",
"amount": 150000,
"status": "FAILED",
"failure_code": "INVALID_DESTINATION",
"failure_message": "Rekening tujuan ditolak bank."
}
}payout.failed. Periksastatus pada isi notifikasi: FAILEDberarti bank menolak, sedangkan REJECTED berarti operator tidak menyetujui. Penolakan operator selalu membawafailure_code bernilaiREJECTED_BY_OPERATOR.Pembayaran USDT
Selain rupiah, tagihan dapat diterbitkan dalam USDT untuk pelanggan luar negeri. Setiap tagihan memperoleh alamat setor tersendiri, sehingga pembayaran langsung teridentifikasi tanpa memo atau kode unik.
USDT TRC20 atauUSDT BEP20 pada menu Kanal Pembayaran di dasbor sebelum memakainya. Selama kanal masih mati, permintaan dijawabCHANNEL_DISABLED. Periksa kesiapannya kapan saja lewat GET /api/v1/channels, kelompokCRYPTO.Metode yang tersedia: USDT_TRC20 pada jaringan TRON dan USDT_BEP20 pada jaringan BSC. Nominal ditulis pada amount dalam mikro-USDT, yaitu USDT dikali satu juta. Mata uang tagihan mengikuti metode yang dipilih, sehingga currency tidak perlu dikirim. Satuan bulat ini dipakai agar tidak ada pembulatan pecahan yang menyimpang.
{
"reference_id": "order-usdt-001",
"amount": 25000000,
"method": { "type": "USDT_TRC20" },
"customer": { "email": "buyer@example.com" }
}Nilai 25000000 di atas berarti 25 USDT. Respons memuat alamat setor beserta keterangan jaringan:
{
"id": "pay_...",
"reference_id": "order-usdt-001",
"status": "PENDING",
"amount": 25000000,
"currency": "USDT",
"method": {
"type": "USDT_TRC20",
"channel": null,
"chain": "TRON",
"deposit_address": "T...",
"token_contract": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
"amount_atomic": "25000000",
"decimals": 6,
"confirmations_required": 20
},
"expires_at": "2026-01-01T10:00:00.000Z"
}Kode kanal untuk kedua metode sama dengan nama metodenya, yaituUSDT_TRC20 dan USDT_BEP20, dan keduanya berada pada kelompok CRYPTO saat daftar kanal dibaca.
| Jaringan | Desimal token | Konfirmasi | Bentuk alamat |
|---|---|---|---|
| TRON (TRC20) | 6 | 20 blok | diawali huruf T |
| BSC (BEP20) | 18 | 15 blok | diawali 0x |
Tagihan berpindah ke PAID setelah jumlah konfirmasi terpenuhi, lalu notifikasipayment.paid dikirim seperti pembayaran rupiah. Sebelum konfirmasi terpenuhi, dana yang sudah terlihat masuk belum diakui sebagai lunas.
Saldo USDT tercatat terpisah dari saldo rupiah dan ditarik lewat menu USDT pada dasbor. Alamat tujuan penarikan wajib didaftarkan lebih dahulu dan baru dapat dipakai setelah masa tunggu 24 jam berlalu, sehingga alamat asing yang disisipkan pihak lain masih sempat diketahui pemilik akun.
Penarikan USDT
Saldo USDT ditarik ke alamat milik merchant sendiri. Alurnya dua langkah: daftarkan alamat lebih dahulu, lalu ajukan penarikan ke alamat yang sudah aktif.
Mendaftarkan alamat tujuan:
curl -X POST https://api.langsunggas.shop/api/v1/crypto-withdrawals/addresses \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"chain": "TRON",
"address": "TXxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}'{
"id": "cwa_...",
"chain": "TRON",
"address": "TXxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"active_at": "2026-01-02T09:00:00.000Z",
"cooldown_hours": 24
}Membaca daftar alamat tujuan:
Medan usable bernilai benar hanya bila masa tunggu alamat sudah lewat. Alamat yang sudah dicabut tidak ikut terbawa. Izin yang dibutuhkan crypto-withdrawals:read.
{
"data": [
{
"id": "cwa_...",
"chain": "TRON",
"address": "TXxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"status": "ACTIVE",
"usable": true,
"active_at": "2026-01-02T09:00:00.000Z",
"created_at": "2026-01-01T09:00:00.000Z"
}
],
"request_id": "req_xxxxxxxx"
}Mengajukan penarikan:
curl -X POST https://api.langsunggas.shop/api/v1/crypto-withdrawals \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"reference_id": "wd-2026-0001",
"chain": "TRON",
"address": "TXxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"amount": "25.5"
}'{
"id": "cw_...",
"reference_id": "wd-2026-0001",
"chain": "TRON",
"amount": "25.500000",
"amount_micro": "25500000",
"status": "APPROVED",
"requires_approval": false,
"environment": "SANDBOX",
"idempotent_replay": false,
"created_at": "2026-01-02T10:00:00.000Z"
}reference_id yang sama dan nominal sama mengembalikan penarikan yang sudah ada, ditandaiidempotent_replay: true dengan status 200. Selalu kirim ulang memakai penanda yang sama ketika jaringan terputus; penanda baru berarti penarikan kedua.Status PENDING_APPROVAL berarti nominalnya melampaui ambang dan menunggu persetujuan operator. StatusAPPROVED berarti penarikan masuk antrean pengiriman ke jaringan.
Membaca satu penarikan beserta jejak lengkapnya:
Pengenal yang diterima berupa id maupunreference_id, sehingga penarikan tetap dapat ditelusuri walau jawaban permintaan pertama tidak pernah diterima.
{
"id": "cw_...",
"reference_id": "wd-2026-0001",
"status": "CONFIRMED",
"amount": "25.500000",
"tx_hash": "0x...",
"failure_code": null,
"events": [
{
"from_status": null,
"to_status": "APPROVED",
"message": "Penarikan diajukan dan masuk antrean pengiriman.",
"actor": "api",
"created_at": "2026-01-02T10:00:00.000Z"
},
{
"from_status": "APPROVED",
"to_status": "BROADCASTING",
"message": "Penarikan sedang disusun dan disiarkan ke jaringan TRON.",
"actor": "system",
"created_at": "2026-01-02T10:02:00.000Z"
},
{
"from_status": "BROADCASTING",
"to_status": "CONFIRMED",
"message": "Transaksi berhasil disiarkan ke jaringan.",
"actor": "system",
"tx_hash": "0x...",
"created_at": "2026-01-02T10:02:30.000Z"
}
]
}Daftar penarikan dibaca lewatGET /api/v1/crypto-withdrawals dengan penyaringstatus, limit, dancursor.
| Status | Arti | Tindakan Anda |
|---|---|---|
| PENDING_APPROVAL | Menunggu persetujuan operator | Tunggu, dana sudah ditahan |
| APPROVED | Antre dikirim ke jaringan | Tunggu |
| BROADCASTING | Sedang disiarkan | Tunggu, jangan ajukan ulang |
| CONFIRMED | Terkirim, tx_hash tersedia | Selesai |
| REJECTED | Ditolak operator | Baca failure_code dan events |
| failure_code | Penyebab |
|---|---|
| INSUFFICIENT_BALANCE | Saldo USDT tidak mencukupi |
| BELOW_MINIMUM | Nominal di bawah batas minimum |
| ADDRESS_IN_COOLDOWN | Alamat masih dalam masa tunggu |
| ADDRESS_NOT_FOUND | Alamat belum didaftarkan pada jaringan itu |
| REFERENCE_CONFLICT | reference_id dipakai ulang dengan nominal berbeda |
| MERCHANT_DAILY_LIMIT | Melebihi batas penarikan harian merchant |
| GAS_EXHAUSTED | Gas jaringan habis; dana tetap ditahan dan dicoba ulang |
| WITHDRAWALS_HALTED | Penarikan dihentikan sementara operator |
APPROVED selama operator belum menyalakan jalur pengiriman kripto. Dana tetap ditahan dan tidak hilang, tetapi transaksi belum disiarkan.Notifikasi
Ketika status pembayaran berubah, kami mengirim pemberitahuan ke alamat yang Anda daftarkan pada halaman Notifikasi.
{
"id": "evt_xxxxxxxxxxxx",
"type": "payment.paid",
"created_at": "2026-08-21T03:01:05Z",
"livemode": true,
"data": {
"payment": {
"id": "pay_xxxxxxxxxxxx",
"reference_id": "PESANAN-2026-0001",
"status": "PAID",
"amount": 275000,
"paid_at": "2026-08-21T03:01:04Z"
}
}
}Kolom type menyatakan peristiwa yang terjadi. Abaikan jenis yang belum Anda kenali, karena daftar ini dapat bertambah.
| Jenis | Kapan dikirim |
|---|---|
payment.pending | Tagihan siap dibayar pelanggan |
payment.paid | Pembayaran diterima |
payment.expired | Tagihan melewati batas waktu tanpa dibayar |
payout.completed | Pencairan sampai di rekening tujuan |
payout.failed | Pencairan gagal atau ditolak, dana kembali ke saldo |
account.kyb.approved | Berkas kelayakan usaha disetujui peninjau |
account.kyb.rejected | Berkas kelayakan usaha ditolak, lihat rejection_reason |
account.status.changed | Status akun berubah, termasuk pembukaan mode sungguhan dan penangguhan |
Tiga jenis account.* menyangkut akun, bukan satu transaksi. Berkas kelayakan mengikat badan usaha dan penangguhan mematikan kedua lingkungan sekaligus, sehingga peristiwa ini dikirim ke setiap alamat notifikasi aktif yang Anda miliki, termasuk alamat uji. Karena itu livemode pada peristiwa akun menyatakan alamat mana yang menerimanya, bukan lingkungan tempat perubahan terjadi.
live_enabled bernilai salah, karena persetujuan kelayakan dan pembukaan jalur dana nyata adalah dua keputusan terpisah. Tunggu account.status.changed dengan live_enabled bernilai benar sebelum beralih ke kunci sungguhan.| Jenis | Kolom pada data |
|---|---|
account.kyb.approved | kyb_status, rejection_reason (null), live_enabled |
account.kyb.rejected | kyb_status, rejection_reason, live_enabled |
account.status.changed | previous_status, status, live_enabled, suspended_reason |
Isi data berbeda menurut jenisnya. Notifikasi pembayaran membawa payment_id, sedangkan notifikasi pencairan membawa payout_id,reference_id, amount, danstatus.
livemode bernilai benar hanya pada pembayaran dengan dana sungguhan. Periksa kolom ini sebelum memenuhi pesanan, agar pembayaran uji tidak pernah dianggap lunas.| Tajuk | Isi |
|---|---|
X-Webhook-Id | Penanda unik pengiriman |
X-Webhook-Timestamp | Waktu penandatanganan dalam milidetik |
X-Webhook-Signature | Tanda tangan HMAC SHA-256 |
X-Webhook-Attempt | Nomor percobaan pengiriman |
Pengiriman dianggap berhasil hanya bila sistem Anda menjawab dengan kode 2xx dalam sepuluh detik. Bila gagal, pengiriman diulang dengan jeda menaik: satu menit, lima menit, tiga puluh menit, dua jam, delapan jam, lalu dua puluh empat jam.
Mengatur notifikasi lewat API
Alamat notifikasi dapat disetel, diperiksa, dan rahasianya diputar tanpa membuka halaman web. Alamat dan rahasia terpisah per lingkungan, dan lingkungannya selalu diambil dari kunci yang Anda pakai memanggil.
lg_sandbox_ hanya menyentuh alamat uji, dan kunci lg_live_ hanya menyentuh alamat produksi.Menyetel alamat. Dipakai juga untuk memperbaruinya di kemudian hari.
curl -X PUT https://api.langsunggas.shop/api/v1/webhook-endpoint \
-H "Authorization: Bearer lg_sandbox_kunci_anda" \
-H "Content-Type: application/json" \
-d '{ "url": "https://usaha-anda.com/notifikasi" }'{
"endpoint": {
"id": "whe_xxxxxxxxxxxx",
"url": "https://usaha-anda.com/notifikasi",
"is_active": true,
"environment": "SANDBOX"
},
"secret": "whsec_xxxxxxxxxxxxxxxxxxxxxxxx",
"request_id": "req_xxxxxxxx"
}secret hanya ada pada jawaban saat alamat pertama kali dibuat. Simpan nilainya saat itu juga; nilai itu tidak dapat dibaca kembali lewat pembacaan biasa. Memperbarui alamat tidak mengganti rahasia, sehingga pemeriksaan tanda tangan yang sudah Anda pasang tetap berlaku.Alamat yang mengarah ke jaringan internal, memakai protokol selain http dan https, atau memuat nama pengguna dan sandi akan ditolak. Pembatasan itu menjaga agar peladen kami tidak dapat disuruh mengetuk jaringan pribadi memakai alamat yang Anda tentukan.
Memeriksa keadaan alamat beserta ringkasan pengiriman, berguna untuk memantau apakah sistem Anda sanggup menerima notifikasi.
{
"environment": "SANDBOX",
"endpoint": {
"id": "whe_xxxxxxxxxxxx",
"url": "https://usaha-anda.com/notifikasi",
"is_active": true,
"created_at": "2026-10-10T10:12:32.003Z"
},
"secret_available": true,
"deliveries": {
"total": 128,
"succeeded": 124,
"failed": 3,
"pending": 1,
"dead_letter": 0
}
}Nilai dead_letter yang bertambah berarti ada notifikasi yang berhenti dicoba setelah semua percobaan ulang habis. Itu tanda alamat Anda sedang bermasalah dan perlu diperiksa.
Kolom action menerima rotate_secret, enable, atau disable.
curl -X POST https://api.langsunggas.shop/api/v1/webhook-endpoint \
-H "Authorization: Bearer lg_sandbox_kunci_anda" \
-H "Content-Type: application/json" \
-d '{ "action": "rotate_secret" }'| Kode | Arti |
|---|---|
400 PRIVATE_ADDRESS | Alamat mengarah ke jaringan internal |
400 PROTOCOL_NOT_ALLOWED | Protokol bukan http atau https |
400 PORT_NOT_ALLOWED | Nomor porta tidak diizinkan |
400 RESOLUTION_FAILED | Nama domain tidak dapat diterjemahkan |
404 NOT_FOUND | Alamat belum diatur pada lingkungan ini |
403 FORBIDDEN | Membaca menuntut payments:read, mengubah menuntut payments:write |
Riwayat notifikasi
Melihat notifikasi mana yang gagal sampai, beserta sebabnya. Tanpa ini, pembayaran tampak hilang di sisi Anda padahal dana sudah masuk, dan satu-satunya bukti sebabnya hanya terbaca pada dasbor.
curl "https://api.langsunggas.shop/api/v1/webhook-deliveries?status=DEAD_LETTER&limit=10" \ -H "Authorization: Bearer lg_sandbox_kunci_anda"
{
"environment": "SANDBOX",
"data": [
{
"id": "whd_xxxxxxxxxxxx",
"event_id": "evt_xxxxxxxxxxxx",
"event_type": "payment.paid",
"attempt": 5,
"status": "DEAD_LETTER",
"response_code": 500,
"error_message": "Peladen Anda menjawab 500.",
"next_retry_at": null,
"created_at": "2026-10-15T06:33:47.442Z"
}
],
"has_more": false,
"dead_letter_count": 1
}| Parameter | Keterangan |
|---|---|
limit | 1 sampai 100, bawaan 30 |
status | PENDING, SUCCEEDED, FAILED, atau DEAD_LETTER |
starting_after | Pengenal pengiriman; mengambil yang lebih tua darinya |
dead_letter_count adalah jumlah notifikasi yang sudah berhenti dicoba. Angka itulah yang menentukan perlu tidaknya pengiriman ulang, sehingga Anda tidak perlu menyaring seluruh riwayat untuk mengetahuinya.
curl -X POST https://api.langsunggas.shop/api/v1/webhook-deliveries \
-H "Authorization: Bearer lg_sandbox_kunci_anda" \
-H "Content-Type: application/json" \
-d '{ "action": "redeliver", "all": true }'{
"action": "redeliver",
"scheduled": 3,
"environment": "SANDBOX"
}| Galat | Sebab |
|---|---|
404 NOT_FOUND | Pengiriman tidak ada, atau bukan milik lingkungan kunci ini |
409 NOT_DEAD_LETTER | Pengiriman masih dijadwalkan ulang otomatis, belum perlu dipaksa |
Pengiriman ulang hanya menjadwalkan; kiriman sesungguhnya tetap dilakukan pekerja latar. scheduled bernilai nol berarti notifikasi itu sudah terjadwal sebelumnya, bukan gagal.
Simulasi pembayaran
Melunasi tagihan uji tanpa dana sungguhan, sehingga alur pembayaran Anda dapat diuji sampai tuntas tanpa membuka dasbor. Tanpa ini, tagihan dapat dibuat tetapi tidak ada cara membuatnya lunas.
curl -X POST https://api.langsunggas.shop/api/v1/simulate \
-H "Authorization: Bearer lg_sandbox_kunci_anda" \
-H "Content-Type: application/json" \
-d '{ "reference_id": "pesanan-001", "apply_directly": true }'{
"payment_id": "pay_xxxxxxxxxxxx",
"reference_id": "pesanan-001",
"amount": 100000,
"method": "LOCAL",
"message": "Pembayaran disimulasikan dan tagihan telah dilunasi."
}403 LIVE_KEY_FORBIDDEN.| Kolom | Wajib | Keterangan |
|---|---|---|
reference_id | Ya | Nomor pesanan tagihan yang hendak dilunasi |
amount | Tidak | Nominal yang dibayarkan. Bila kosong, memakai nominal tagihan |
apply_directly | Tidak | Benar berarti langsung dilunasi tanpa menunggu notifikasi penyedia |
Kolom method pada jawaban bernilai LOCAL bila tagihan sudah lunas saat jawaban terbit, atau PROVIDER bila status baru berubah setelah notifikasi penyedia tiba. Pakai apply_directly ketika alamat notifikasi Anda belum dapat dijangkau dari luar, misalnya saat masih berjalan di mesin lokal.
Verifikasi tanda tangan
Contoh dengan Node.js:
import { createHmac, timingSafeEqual } from "node:crypto";
// Ambil isi mentah, jangan diuraikan lebih dulu.
const rawBody = await request.text();
const timestamp = request.headers.get("x-webhook-timestamp");
const signature = request.headers.get("x-webhook-signature");
// Tolak notifikasi lama untuk mencegah pengiriman ulang.
if (Math.abs(Date.now() - Number(timestamp)) / 1000 > 300) {
return new Response(null, { status: 400 });
}
const diharapkan = createHmac("sha256", RAHASIA_ANDA)
.update(timestamp + "." + rawBody)
.digest("hex");
const a = Buffer.from(diharapkan);
const b = Buffer.from(signature);
if (a.length !== b.length || timingSafeEqual(a, b) === false) {
return new Response(null, { status: 400 });
}
const event = JSON.parse(rawBody);
return new Response(null, { status: 200 });Contoh dengan PHP:
<?php
$rawBody = file_get_contents('php://input');
$timestamp = $_SERVER['HTTP_X_WEBHOOK_TIMESTAMP'];
$signature = $_SERVER['HTTP_X_WEBHOOK_SIGNATURE'];
if (abs(round(microtime(true) * 1000) - (int)$timestamp) / 1000 > 300) {
http_response_code(400);
exit;
}
$diharapkan = hash_hmac('sha256', $timestamp . '.' . $rawBody, RAHASIA_ANDA);
if (!hash_equals($diharapkan, $signature)) {
http_response_code(400);
exit;
}
$event = json_decode($rawBody, true);
http_response_code(200);Status pembayaran
CREATED -> PENDING -> PAID
|
+--> EXPIRED / FAILED / CANCELLED| Status | Arti |
|---|---|
CREATED | Tagihan dibuat, menunggu penyedia |
PENDING | Siap dibayar pelanggan |
PAID | Sudah dibayar |
EXPIRED | Melewati batas waktu |
FAILED | Gagal dibuat |
CANCELLED | Dibatalkan |
Kode kesalahan
Seluruh kesalahan memakai bentuk yang sama.
{
"error": {
"code": "INVALID_AMOUNT",
"message": "Nominal di luar batas yang diizinkan",
"request_id": "req_xxxxxxxx",
"details": []
}
}| HTTP | Kode | Arti |
|---|---|---|
| 401 | UNAUTHORIZED | Kunci tidak ada atau tidak sah |
| 403 | FORBIDDEN | Cakupan kunci tidak mencukupi |
| 403 | MERCHANT_NOT_ACTIVE | Akun belum aktif atau dihentikan |
| 400 | VALIDATION_ERROR | Isi permintaan tidak sesuai |
| 400 | INVALID_AMOUNT | Nominal di luar batas |
| 409 | IDEMPOTENCY_CONFLICT | Kunci idempotensi dipakai dengan isi berbeda |
| 404 | RESOURCE_NOT_FOUND | Data tidak ditemukan |
| 429 | RATE_LIMITED | Permintaan terlalu sering |
| 502 | PROVIDER_UNAVAILABLE | Penyedia sedang bermasalah |
| 400 | UNKNOWN_CHANNEL | Kode kanal tidak dikenal |
| 422 | CHANNEL_DISABLED | Kanal dimatikan operator atau oleh Anda sendiri |
| 502 | PROVIDER_STATE_UNKNOWN | Status belum dapat dipastikan |
| 400 | API_KEY_ERROR | Permintaan kunci API ditolak, misalnya nama kunci tidak sah |
| 409 | NO_OWNER | Merchant tidak punya pemilik aktif, kunci tidak dapat diterbitkan |
| 429 | TOO_MANY | Pengiriman ulang notifikasi terlalu banyak dalam satu permintaan |
| 400 | ADDRESS_INVALID | Alamat kripto tidak sesuai bentuk rantai yang dipilih |
| 409 | ADDRESS_REVOKED | Alamat tujuan sudah dicabut dan tidak dapat dipakai lagi |
| 409 | PLATFORM_DAILY_LIMIT | Batas penarikan kripto harian seluruh platform tercapai |
| 409 | WITHDRAWAL_REJECTED | Penarikan kripto ditolak aturan lain, baca pesannya |
| 500 | INTERNAL_ERROR | Kesalahan tak terduga di sisi kami, aman untuk dicoba ulang |
Batas permintaan
| Jenis | Batas |
|---|---|
| Membuat pembayaran | 60 per menit untuk setiap kunci |
| Membaca data | 300 per menit untuk setiap kunci |
| Mengajukan pencairan | 20 per menit untuk setiap kunci |
| Pendaftaran merchant lewat API | 5 per jam untuk setiap alamat IP |
| Mengelola kunci, notifikasi, dan KYB | 300 per menit untuk setiap kunci |
| Pengiriman ulang notifikasi | 20 per menit untuk setiap kunci |
Melampaui batas menghasilkan kode 429. Tunggu sesuai tajukRetry-After sebelum mencoba lagi.
Praktik yang disarankan
- Simpan nilai
idyang kami kembalikan, bukan hanya nomor pesanan Anda sendiri. - Sediakan pemeriksaan berkala sebagai cadangan bila notifikasi tidak kunjung tiba, misalnya karena peladen Anda sempat mati.
- Catat setiap notifikasi yang masuk beserta hasil pemeriksaan tanda tangannya, agar penelusuran masalah lebih mudah.
- Uji seluruh alur pada lingkungan sandbox, termasuk keadaan gagal, sebelum beralih ke produksi.