Mulai
DITOPUP by Ditnov API memungkinkan website, bot, atau aplikasi kamu menjual produk DITOPUP by Ditnov secara otomatis (H2H). Saldo yang dipakai adalah saldo akun kamu di DITOPUP by Ditnov, dengan harga reseller.
- Aktifkan langganan reseller di halaman Akun → Reseller.
- Buka Akun → API, klik Buat API Key, simpan API key dan callback secret.
- Daftarkan IP server kamu di whitelist (wajib), dan isi Callback URL untuk menerima update status.
- Isi saldo, ambil daftar produk, lalu kirim pesanan.
| Base URL | https://ditnov.com/api/v1 |
| Format | JSON (UTF-8), request body application/json |
| Mata uang | IDR (Rupiah, bilangan bulat) |
| Waktu | ISO 8601 UTC |
| Batas request | 120 request / menit / API key |
Autentikasi
Kirim API key di header X-API-Key pada setiap request. Header Authorization: Bearer <key> juga diterima.
GET /v1/balance HTTP/1.1
Host: ditnov.com
X-API-Key: dk_live_xxxxxxxxxxxxxxxxxxxxxxxx
Accept: application/jsonFormat Respons
Semua respons memakai pola yang sama.
{
"success": true,
"data": { ... }
}{
"success": false,
"error": {
"code": "insufficient_balance",
"message": "Saldo tidak mencukupi. Silakan deposit terlebih dahulu."
}
}Daftar Endpoint
/balanceCek saldo/categoriesDaftar kategori/productsDaftar produk & harga/validateCek nama akun tujuan/orderBuat transaksi/order/{ref_id}Cek status transaksi/ordersRiwayat transaksiCek Saldo
/balancecurl https://ditnov.com/api/v1/balance \
-H "X-API-Key: $API_KEY"{
"success": true,
"data": {
"balance": 500000,
"currency": "IDR",
"tier": "reseller",
"reseller_until": "2026-11-23T03:00:00+00:00"
}
}Daftar Produk
/products| Parameter | Keterangan |
|---|---|
category | Opsional. Nama kategori persis, mis. Game. |
q | Opsional. Kata kunci nama produk. |
code | Opsional. Satu kode produk. |
curl "https://ditnov.com/api/v1/products?category=Game" \
-H "X-API-Key: $API_KEY"{
"success": true,
"data": [
{
"code": "TIK1",
"product": "Tiktok",
"name": "TikTok Saves (100/20k) {5k-10k/day} [R30]",
"category": "SMM",
"price": 19500,
"normal_price": 19500,
"promo": false,
"status": "available",
"stock": null,
"max_qty": 1,
"fields": [
{ "key": "target", "label": "User ID", "required": true },
{ "key": "zone", "label": "Server / Zone ID", "required": true }
],
"validate": true,
"image": null
}
]
}- code dipakai saat order. Kode bersifat tetap, tapi produk bisa nonaktif sewaktu-waktu.
- price adalah harga yang dipotong dari saldo kamu per unit (sudah termasuk promo bila ada).
- fields menunjukkan data yang wajib dikirim saat order:
target(ID/nomor tujuan) danzone(server/zone). - stock berisi angka untuk produk berstok terbatas,
nullberarti tidak dibatasi. - Harga bisa berubah. Ambil ulang daftar produk secara berkala (mis. tiap 15–60 menit) dan simpan di cache kamu.
Cek Nama Akun
/validateUntuk produk dengan "validate": true, cek nama akun tujuan sebelum order. Opsional, tidak memotong saldo.
curl -X POST https://ditnov.com/api/v1/validate \
-H "X-API-Key: $API_KEY" \
-H "Content-Type: application/json" \
-d '{"product":"TIK1","target":"12345678","zone":"1234"}'{
"success": true,
"data": { "product": "TIK1", "target": "12345678", "zone": "1234", "name": "NamaPemain" }
}Buat Transaksi
/order| Field | Keterangan |
|---|---|
ref_id | Wajib. ID transaksi dari sistem kamu, unik, 4–64 karakter (huruf, angka, . - _). |
product | Wajib. Kode produk dari /products. |
target | ID / nomor / email tujuan (sesuai fields). |
zone | Server / Zone ID bila diperlukan. |
qty | Opsional, default 1. Maksimal sesuai max_qty. |
curl -X POST https://ditnov.com/api/v1/order \
-H "X-API-Key: $API_KEY" \
-H "Content-Type: application/json" \
-d '{"ref_id":"INV-20261024-0001","product":"TIK1","target":"12345678","zone":"1234"}'{
"success": true,
"data": {
"ref_id": "INV-20261024-0001",
"trx_id": "TS2610241030451234",
"product": "TIK1",
"product_name": "Tiktok TikTok Saves (100/20k) {5k-10k/day} [R30]",
"item_name": "TikTok Saves (100/20k) {5k-10k/day} [R30]",
"qty": 1,
"target": "12345678",
"zone": "1234",
"price": 19500,
"total": 19500,
"refunded": 0,
"status": "processing",
"message": "",
"sn": null,
"data": [],
"note": null,
"created_at": "2026-10-24T03:30:45+00:00",
"updated_at": "2026-10-24T03:30:46+00:00",
"balance": 480500
}
}ref_id yang sama. Sistem tidak akan membuat transaksi dobel, dan mengembalikan transaksi yang sudah ada dengan "duplicate": true.Saldo langsung dipotong saat transaksi dibuat. Bila transaksi gagal, dana dikembalikan otomatis ke saldo (lihat field refunded).
Status Transaksi
/order/{ref_id}Isi {ref_id} dengan ref_id kamu atau trx_id.
curl https://ditnov.com/api/v1/order/INV-20261024-0001 \
-H "X-API-Key: $API_KEY"| status | Arti | Final |
|---|---|---|
pending | Transaksi diterima, menunggu diproses | Tidak |
processing | Sedang diproses | Tidak |
success | Berhasil. Cek sn (nomor seri/bukti) atau data (akun/lisensi/voucher) | Ya |
failed | Gagal, dana dikembalikan ke saldo | Ya |
canceled | Dibatalkan, dana dikembalikan ke saldo | Ya |
Untuk produk berisi akun/lisensi (mis. aplikasi premium), data dikirim di array data dan petunjuk tambahan di note.
Riwayat Transaksi
/orders| Parameter | Keterangan |
|---|---|
status | Opsional: pending, processing, success, failed, canceled |
from / to | Opsional, format YYYY-MM-DD |
page / per_page | Default 1 / 50, maksimal 100 per halaman |
Callback (Webhook)
Setiap status transaksi berubah, sistem mengirim POST ke Callback URL kamu. Callback URL wajib https://.
POST /callback HTTP/1.1
Content-Type: application/json
X-Event: order.updated
X-Timestamp: 1761276650
X-Signature: 5f2b...c91e{
"event": "order.updated",
"data": { ...sama dengan respons /order/{ref_id}... }
}- Verifikasi setiap callback:
X-Signature= HMAC-SHA256 dari raw body dengan callback secret kamu (hex). - Balas dengan HTTP
2xxdalam 10 detik. Selain itu dianggap gagal dan dikirim ulang hingga 5 kali (1, 5, 15, 30, 60 menit). - Callback bisa datang lebih dari sekali atau tidak berurutan. Proses berdasarkan
ref_id+status, dan abaikan bila status di sistem kamu sudah final. - Tetap sediakan pengecekan berkala lewat
/order/{ref_id}sebagai cadangan. - Tombol Tes Callback di Akun → API mengirim event
ping.
<?php
$secret = 'whsec_xxxxxxxxxxxxxxxx';
$raw = file_get_contents('php://input');
$sig = $_SERVER['HTTP_X_SIGNATURE'] ?? '';
if (!hash_equals(hash_hmac('sha256', $raw, $secret), $sig)) {
http_response_code(401);
exit('invalid signature');
}
$event = json_decode($raw, true);
if ($event['event'] === 'order.updated') {
$o = $event['data'];
// update transaksi $o['ref_id'] di database kamu menjadi $o['status']
}
http_response_code(200);
echo 'OK';const crypto = require('crypto');
app.post('/callback', express.raw({ type: 'application/json' }), (req, res) => {
const sig = crypto.createHmac('sha256', process.env.CALLBACK_SECRET).update(req.body).digest('hex');
if (sig !== req.get('X-Signature')) return res.status(401).send('invalid signature');
const event = JSON.parse(req.body);
// proses event.data.ref_id & event.data.status
res.send('OK');
});Contoh Kode
<?php
function api($method, $path, $body = null) {
$ch = curl_init('https://ditnov.com/api/v1' . $path);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => $method,
CURLOPT_TIMEOUT => 60,
CURLOPT_HTTPHEADER => ['X-API-Key: ' . getenv('API_KEY'), 'Content-Type: application/json'],
]);
if ($body) curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($body));
$res = json_decode(curl_exec($ch), true);
curl_close($ch);
return $res;
}
$order = api('POST', '/order', [
'ref_id' => 'INV-' . time(),
'product' => 'TIK1',
'target' => '12345678',
'zone' => '1234',
]);
if ($order['success']) {
echo $order['data']['status'];
} else {
echo $order['error']['code'] . ': ' . $order['error']['message'];
}const BASE = 'https://ditnov.com/api/v1';
async function api(method, path, body) {
const r = await fetch(BASE + path, {
method,
headers: { 'X-API-Key': process.env.API_KEY, 'Content-Type': 'application/json' },
body: body ? JSON.stringify(body) : undefined,
});
return r.json();
}
const order = await api('POST', '/order', {
ref_id: 'INV-' + Date.now(),
product: 'TIK1',
target: '12345678',
zone: '1234',
});
console.log(order.success ? order.data.status : order.error);import os, time, requests
BASE = 'https://ditnov.com/api/v1'
H = {'X-API-Key': os.environ['API_KEY']}
r = requests.post(BASE + '/order', headers=H, timeout=60, json={
'ref_id': f'INV-{int(time.time())}',
'product': 'TIK1',
'target': '12345678',
'zone': '1234',
}).json()
print(r['data']['status'] if r['success'] else r['error'])Kode Error
| HTTP | code | Arti |
|---|---|---|
| 400 | invalid_request | Parameter kurang atau salah format |
| 401 | unauthorized | API key tidak dikirim atau salah |
| 402 | insufficient_balance | Saldo tidak mencukupi |
| 403 | ip_not_whitelisted | IP server belum didaftarkan |
| 403 | reseller_required | Langganan reseller tidak aktif |
| 403 | key_disabled / account_disabled | Akses dicabut admin |
| 404 | product_unavailable | Kode produk salah, nonaktif, atau stok habis |
| 404 | order_not_found | ref_id tidak ditemukan |
| 409 | duplicate_ref_id | ref_id sedang diproses bersamaan |
| 422 | order_rejected | Transaksi ditolak. Dana sudah dikembalikan, detail ada di data |
| 422 | target_not_found | ID tujuan tidak ditemukan saat cek nama |
| 429 | rate_limited | Terlalu banyak request, ulangi setelah header Retry-After |
| 503 | api_disabled / service_unavailable | Layanan sedang tidak tersedia |
Untuk error 5xx atau timeout saat membuat transaksi, jangan langsung anggap gagal. Cek dulu lewat /order/{ref_id} atau kirim ulang dengan ref_id yang sama.
Ketentuan Pemakaian
- API hanya untuk reseller aktif dan dipakai untuk menjual kembali ke pelanggan kamu sendiri.
- Kamu bertanggung jawab atas data tujuan yang dikirim. Transaksi yang sudah sukses ke tujuan yang salah tidak bisa dibatalkan.
- Dilarang membebani sistem secara berlebihan, menguji celah keamanan, atau membagikan API key ke pihak lain.
- Akses API bisa dicabut bila terjadi penyalahgunaan. Ketentuan lain mengikuti Syarat & Ketentuan.