Dokumentasi API H2H Dotkas
Sambungin server lo (OtomaX, IRS, atau server sendiri) ke Dotkas buat transaksi pulsa, paket data, token PLN, e-wallet, voucher game, dan produk digital lainnya. Formatnya standar OtomaX, jadi kebanyakan server pulsa tinggal isi alamat dan kode.
Ringkasan
- Kirim transaksi ke
/h2h/trx. Balasan langsung: status=1 (diproses) atau status=0 (gagal, saldo gak kepotong). - Status akhir (status=2 sukses + SN, atau status=0 gagal + saldo balik) dikirim ke URL callback lo.
- Callback gak nyampe? Kirim ulang request dengan refID yang sama. Dotkas gak bikin trx baru, cuma balas status trx itu.
Parameter bisa lewat query string (GET), form (POST application/x-www-form-urlencoded), atau JSON (POST application/json). Nama parameter gak peka huruf besar/kecil.
Dapetin akses
- Daftar akun di app.dotkas.com, terus buka menu Akses API dan ajukan ke admin.
- Setelah disetujui, lo dapet Member ID (contoh
KP00012), lalu bikin API Key dan PIN API sendiri di menu yang sama. Dua-duanya rahasia, jangan dikirim ke siapa pun. - Isi IP whitelist (IP publik server lo). Request dari IP lain ditolak.
- Isi URL callback (wajib alamat publik, http/https).
- Coba dulu di Sandbox (menu Akses API): gak motong saldo, gak beneran dikirim, tapi callback-nya beneran nyampe ke server lo. Tujuan berakhiran
0= simulasi gagal.
Sign
Semua request wajib bawa sign:
sign = Base64URL( SHA1( "OtomaX|{memberID}|{product}|{dest}|{refID}|{PIN}|{APIKey}" ) )
- SHA1 diambil dalam bentuk byte mentah (bukan hex), lalu di-Base64.
- Base64URL:
+jadi-,/jadi_, tanda=di belakang dibuang. - Nilai di dalam string harus persis sama dengan yang dikirim di parameter (huruf besar/kecil, angka 0 di depan).
- Cek saldo pakai rumus pendek:
OtomaX|{memberID}|{PIN}|{APIKey}.
……Dihitung di browser lo, gak dikirim ke mana-mana.
Format balasan
Default-nya teks gaya OtomaX. Kalau request dikirim sebagai JSON, balasannya JSON.
| status | Arti | Saldo |
|---|---|---|
| 0 | Gagal / ditolak | Gak kepotong, atau udah dibalikin |
| 1 | Diproses, tunggu callback | Udah kepotong |
| 2 | Sukses, ada SN | Kepotong |
status=1&message=Trx S10 081234567890 akan diproses&refid=INV-0001&ref=KP261029A1B2C3&harga=10350&saldo=489650
{
"status": 1,
"status_text": "proses",
"message": "Trx S10 081234567890 akan diproses",
"refid": "INV-0001",
"ref": "KP261029A1B2C3",
"harga": 10350,
"saldo": 489650
}refid = nomor trx lo, ref = nomor trx di Dotkas (simpen buat komplain), harga = yang dipotong dari saldo.
GETCek saldo
| Parameter | Keterangan |
|---|---|
memberID wajib | Member ID lo, contoh KP00012 |
sign wajib | Base64URL(SHA1("OtomaX|{memberID}|{PIN}|{APIKey}")) |
status=1&message=Saldo: Rp 489.650&saldo=489650
GETTransaksi
| Parameter | Keterangan |
|---|---|
product wajib | Kode produk Dotkas (lihat daftar harga) |
dest wajib | Nomor HP / ID pelanggan / nomor meter. Nomor HP boleh 08… atau 628… |
refID wajib | Nomor trx lo, unik per akun, 3–30 karakter (huruf, angka, strip) |
memberID wajib | Member ID lo |
sign wajib | Lihat Sign |
qty opsional | Produk biasa: 2 = sengaja kirim lagi produk yang sama ke nomor yang sama (lewatin rem dobel). Produk open denom: nominal, lihat bawah. |
Contoh balasan
# diterima, tunggu callback status=1&message=Trx S10 081234567890 akan diproses&refid=INV-0001&ref=KP261029A1B2C3&harga=10350&saldo=489650 # ditolak (saldo gak kepotong) status=0&message=Saldo tidak cukup. Transaksi GAGAL&refid=INV-0001
GETOpen denom (bebas nominal)
Buat produk "bebas nominal" (top up DANA, OVO, GoPay, ShopeePay, dll), kirim nominalnya di qty. Sama kayak format Okeconnect.
qty= nominal, Rp10.000 sampai Rp10.000.000. Boleh juga lewat parameternominal.- Yang dipotong dari saldo = nominal + biaya admin produk (muncul di
harga). - Sign tetap pakai rumus transaksi biasa (
qtygak ikut di-hash).
GETCek status
Kirim ulang request transaksi yang sama persis (refID sama). Dotkas gak bikin trx baru, cuma balas status trx itu. Aman diulang berapa kali pun.
# masih diproses status=1&message=Trx S10 081234567890 akan diproses (refID udah masuk sebelumnya)&refid=INV-0001&ref=KP261029A1B2C3 # sukses status=2&message=Trx S10 081234567890 SUKSES. SN: 0431890000145197&refid=INV-0001&ref=KP261029A1B2C3&sn=0431890000145197 # gagal (saldo udah balik) status=0&message=Trx S10 081234567890 GAGAL. Nomor tujuan salah&refid=INV-0001&ref=KP261029A1B2C3
GETDaftar harga
JSON publik, update tiap menit. Isinya kategori, kode produk, nama, harga, dan status (normal / gangguan). Bisa juga dilihat di app.dotkas.com/harga.
{
"ok": true,
"update": "2026-10-29 00:10:00",
"kategori": [
{ "nama": "Pulsa", "items": [
{ "kode": "S10", "nama": "Telkomsel 10.000", "harga": 10350, "status": "normal" }
]}
]
}
Ini harga level Reguler. Harga khusus akun lo (level, diskon) ada di menu Akses API, dan yang beneran dipotong selalu muncul di harga pas transaksi.
CBCallback
Begitu trx final, Dotkas manggil URL callback lo pakai GET, parameter ditempel di belakang URL:
| Parameter | Keterangan |
|---|---|
refid | refID dari lo |
ref | Nomor trx Dotkas |
status | 2 sukses, 0 gagal (saldo udah dibalikin) |
sn | Serial number / token (kosong kalau gagal) |
harga | Harga yang dipotong |
message | Pesan lengkap, format OtomaX: Trx {kode} {tujuan} SUKSES. SN: … / … GAGAL. {alasan} |
- Balas dengan HTTP 2xx (isi bebas). Selain itu dianggap gagal.
- Gagal nyampe → dikirim ulang sampai 3x, jeda mulai 60 detik dan makin panjang tiap percobaan. Riwayat callback ada di menu Akses API, bisa dikirim ulang manual.
- Timeout 10 detik, gak ngikutin redirect. User-Agent:
Dotkas-H2H-Callback/1.x. - Callback bisa datang lebih dari sekali buat trx yang sama. Pakai
refidsebagai kunci dan abaikan yang udah final.
status lewat cek status sebelum ngerefund pelanggan lo.Aturan & batasan
- refID unik per akun. refID yang udah pernah dipakai = cek status, bukan trx baru.
- Rem dobel: produk sama ke nomor sama dalam 30 menit ditolak. Pakai
qty=2kalau emang sengaja. - Batas request: 120 per menit per akun. Lewat dari itu dapet
status=0+ HTTP 429. - IP whitelist wajib diisi. Ganti IP server = update di menu Akses API dulu.
- Produk tagihan (PLN pascabayar, BPJS, PDAM, dll) belum bisa lewat H2H, bayarnya lewat app.
- Status 1 yang lama banget gak ada kabar (gangguan supplier) tetap ditahan, gak pernah digagalin diam-diam. Hubungi CS dengan nomor
ref.
Setting di OtomaX
Tambah Server baru di OtomaX dengan koneksi H2H / IP (HTTP GET), lalu isi:
| Kolom | Isi |
|---|---|
| URL request | https://app.dotkas.com/h2h/trx?product=[kode]&dest=[tujuan]&refID=[trxid]&memberID=[memberid]&sign=[sign] |
| Rumus sign | OtomaX|[memberid]|[kode]|[tujuan]|[trxid]|[pin]|[password] → SHA1 → Base64URL (tanpa =) |
| PIN / Password | PIN API / API Key dari menu Akses API |
| URL report (callback) | Alamat report OtomaX lo, isi juga di menu Akses API |
| Parsing sukses | SUKSES. SN: (.+) atau status=2 |
| Parsing gagal | GAGAL atau status=0 |
Nama placeholder bisa beda tergantung versi OtomaX. Yang penting isinya sama dengan rumus di atas.
Contoh kode
# sign dihitung dulu (lihat bagian Sign), lalu:
curl "https://app.dotkas.com/h2h/trx?product=S10&dest=081234567890&refID=INV-0001&memberID=KP00012&sign=SIGN_LO"<?php $member = 'KP00012'; $pin = '1234'; $key = 'APIKEY_LO'; $kode = 'S10'; $tujuan = '081234567890'; $ref = 'INV-0001'; $raw = sha1("OtomaX|$member|$kode|$tujuan|$ref|$pin|$key", true); // true = byte mentah $sign = rtrim(strtr(base64_encode($raw), '+/', '-_'), '='); $url = 'https://app.dotkas.com/h2h/trx?' . http_build_query([ 'product' => $kode, 'dest' => $tujuan, 'refID' => $ref, 'memberID' => $member, 'sign' => $sign, ]); echo file_get_contents($url);
const crypto = require('crypto'); const member = 'KP00012', pin = '1234', key = 'APIKEY_LO'; const kode = 'S10', tujuan = '081234567890', ref = 'INV-0001'; const sign = crypto.createHash('sha1') .update(`OtomaX|${member}|${kode}|${tujuan}|${ref}|${pin}|${key}`) .digest('base64url'); // Node 16+: udah tanpa '=' const q = new URLSearchParams({ product: kode, dest: tujuan, refID: ref, memberID: member, sign }); fetch('https://app.dotkas.com/h2h/trx?' + q).then(r => r.text()).then(console.log);
import base64, hashlib, requests member, pin, key = "KP00012", "1234", "APIKEY_LO" kode, tujuan, ref = "S10", "081234567890", "INV-0001" raw = hashlib.sha1(f"OtomaX|{member}|{kode}|{tujuan}|{ref}|{pin}|{key}".encode()).digest() sign = base64.urlsafe_b64encode(raw).decode().rstrip("=") r = requests.get("https://app.dotkas.com/h2h/trx", params={ "product": kode, "dest": tujuan, "refID": ref, "memberID": member, "sign": sign}) print(r.text)
Mau langsung nyoba? Download koleksi Postman, isi variabel member_id, pin, api_key. Sign dihitung otomatis.
Daftar pesan gagal
| Pesan | Artinya |
|---|---|
Sign salah | Rumus / PIN / API Key gak cocok. Cek pakai kalkulator di bagian Sign. |
IP … gak terdaftar | IP server lo belum masuk whitelist |
Member ID gak terdaftar / akses API belum aktif | Member ID salah, atau akses belum disetujui admin |
Parameter kurang | Ada yang kosong: product, dest, refID, memberID, sign |
Produk … lagi gak tersedia | Kode salah, atau produk lagi ditutup / gangguan |
Saldo tidak cukup | Deposit dulu di app |
Trx dobel | Produk sama ke nomor sama dalam 30 menit. Pakai qty=2 kalau sengaja |
Kebanyakan request | Lewat 120 request per menit |
Server lagi tutup sementara | Maintenance. Coba lagi nanti |