Dokumentasi VTechOTP Developer API v1
Akses terprogram untuk sewa nomor virtual, otomatisasi penerimaan SMS/OTP, pengecekan saldo, dan notifikasi real-time webhook berbasis mata uang Rupiah (1 Coin = 1 IDR).
Autentikasi
Setiap request ke API harus menyertakan API Token Anda pada HTTP Header Authorization dengan format Bearer token:
Authorization: Bearer vtk_your_api_token_here
Anda dapat membuat atau memperbarui API Token kapan saja melalui menu Profil > Developer API & Webhook di aplikasi VTechOTP.
Base URL
Semua request API diarahkan ke endpoint resmi berikut:
Cek Saldo & Profil
Mengambil informasi saldo koin akun (1 koin = Rp 1), jumlah order aktif, dan status konfigurasi akun Anda.
curl -s https://vtechotp.web.id/api/v1/balance \
-H "Authorization: Bearer vtk_your_api_token_here"
{
"success": true,
"data": {
"user_id": "6a8218b04fb8bbfcd472a981",
"email": "user@example.com",
"display_name": "DevUser",
"balance": 75000,
"currency": "IDR",
"active_orders": 1,
"total_orders": 68,
"success_orders": 65,
"webhook_configured": true,
"api_enabled": true
}
}
Daftar Saluran Pembayaran & Cek Status Live (ON/OFF)
/deposit/channels)
Mendapatkan daftar seluruh metode/saluran pembayaran yang didukung payment gateway secara real-time. Endpoint ini menampilkan status aktif/gangguan (status: "ON" atau "OFF"), batas minimum/maksimum nominal, dan biaya fee pada masing-masing saluran sehingga bot atau aplikasi Anda dapat memvalidasi saluran mana yang sedang online sebelum membuat tagihan invoice.
11 (Min. Rp 100 / Rp 1.000, Max. Rp 10.000.000) - Rekomendasi Utama• Virtual Account (VA): BCA (
1), BRI (2), BNI (4), Mandiri (5), CIMB (3), Permata (7), Danamon (8), BSI (9), Neo (10), OCBC (21), Muamalat (22) (Min. Rp 10.000)• E-Wallet: OVO (
12 - butuh parameter phone)• Gerai Retail: Alfamart/Alfamidi (
18), Indomaret/Ceriamart (19) (Min. Rp 10.000)
curl -s https://vtechotp.web.id/api/v1/deposits/channels
{
"success": true,
"data": {
"payment_gateway": "configured_gateway",
"deposit_fee_flat": 100,
"deposit_fee_percent": 0,
"total_channels": 16,
"active_channels": 16,
"channels": [
{
"id": "11",
"service_id": "11",
"name": "QRIS Realtime",
"type": "QRIS",
"minimum": 1000,
"maximum": 10000000,
"fee": "0.7%",
"icon_url": "/assets/app-deposit.png",
"status": "ON",
"is_active": true
},
{
"id": "1",
"service_id": "1",
"name": "Virtual Account Bank BCA",
"type": "VA",
"minimum": 10000,
"maximum": 10000000,
"fee": 4900,
"icon_url": "/assets/app-deposit.png",
"status": "ON",
"is_active": true
},
{
"id": "2",
"service_id": "2",
"name": "Virtual Account Bank BRI",
"type": "VA",
"minimum": 10000,
"maximum": 50000000,
"fee": 2500,
"icon_url": "/assets/app-deposit.png",
"status": "ON",
"is_active": true
},
{
"id": "18",
"service_id": "18",
"name": "ALFAMART",
"type": "RETAIL",
"minimum": 10000,
"maximum": 5000000,
"fee": 2500,
"icon_url": "/assets/app-deposit.png",
"status": "ON",
"is_active": true
}
]
}
}
Buat Tagihan Deposit (QRIS, VA, E-Wallet, Retail)
/deposit/create, /deposits)
Membuat tagihan invoice deposit saldo koin baru via payment gateway. Mendukung pembuatan tagihan otomatis untuk QRIS Realtime (mengembalikan gambar PNG, Base64, dan raw payload), Virtual Account (mengembalikan nomor VA), E-Wallet, dan Gerai Retail (Alfamart/Indomaret).
| Parameter Body | Tipe | Wajib? | Deskripsi |
|---|---|---|---|
| amount | integer | Wajib | Nominal deposit dalam Rupiah (min. Rp 1.000 untuk QRIS, min. Rp 10.000 untuk VA/Retail) |
| service_id | string / integer | Opsional | Kode saluran pembayaran (contoh: "11" = QRIS, "1" = BCA VA, "2" = BRI VA, "4" = BNI VA, "18" = Alfamart, dll. Default: "11") |
| method | string | Opsional | Metode pembayaran jika tidak mengirim service_id: "QRIS", "VA", "E-Wallet", "Retail" |
| phone | string | Opsional | Nomor HP pelanggan (wajib jika memilih metode OVO / service_id "12") |
curl -s -X POST https://vtechotp.web.id/api/v1/deposits/create \
-H "Authorization: Bearer vtk_your_api_token_here" \
-H "Content-Type: application/json" \
-d '{
"amount": 10000,
"service_id": "11"
}'
{
"success": true,
"data": {
"id": "66ce30d97960cf1c8152e9f1",
"internal_ref": "VTO1740645600000A1B",
"method": "QRIS",
"provider": "configured_gateway",
"channel_code": "11",
"channel_name": "QRIS Realtime",
"amount": 10000,
"fee": 100,
"total_payment": 10100,
"net_coins": 10000,
"status": "pending",
"qr_string": "00020101021226540014ID.LINKAJA.WWW0118936009110022201382021520021610212345...",
"qr_image_url": "https://vtechotp.web.id/api/qr?data=00020101021226540014ID.LINKAJA.WWW0118...",
"qr_image_base64": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAUAAAAFACAYAAAD6umHTAA...",
"virtual_account": "",
"payment_code": "",
"payment_url": "https://vtechotp.web.id/payment/checkout/VTO1740645600000A1B",
"payment_guide": null,
"expires_at": "2026-08-30T17:40:00.000Z",
"paid_at": null,
"credited_at": null,
"created_at": "2026-08-30T17:10:00.000Z",
"instructions": "Silakan scan kode QRIS menggunakan aplikasi m-banking atau e-wallet (BCA, Mandiri, BRI, BNI, GoPay, OVO, DANA, ShopeePay). Saldo koin akan otomatis bertambah setelah pembayaran berhasil diverifikasi."
}
}
- Bot Telegram (Node.js/Telegraf):
ctx.replyWithPhoto(data.qr_image_url, { caption: 'Silakan scan QRIS di atas...' }) - Bot Telegram (Python/telebot):
bot.send_photo(chat_id, photo=data['qr_image_url'], caption="Scan QRIS...") - Aplikasi Web / Frontend: Gunakan tag
<img src="data.qr_image_url" alt="QRIS" width="280" />atau render inline viadata.qr_image_base64tanpa perlu download manual.
Cek Status & Sinkronisasi Live Deposit
/deposits/{id}/status, /deposit/{id})
Mengecek status tagihan deposit menggunakan ID MongoDB (_id) atau Kode Referensi Internal (internal_ref). Jika deposit berstatus pending, endpoint ini secara otomatis melakukan live-sync ke payment gateway untuk memeriksa status pembayaran, mengkreditkan koin ke saldo Anda, dan memicu notifikasi serta webhook real-time jika telah lunas.
| Parameter Path | Tipe | Wajib? | Deskripsi |
|---|---|---|---|
| id | string | Wajib | ID deposit (MongoDB ObjectId) atau kode internalRef (contoh: VTO1740645600000A1B) |
curl -s https://vtechotp.web.id/api/v1/deposits/VTO1740645600000A1B \
-H "Authorization: Bearer vtk_your_api_token_here"
{
"success": true,
"data": {
"id": "66ce30d97960cf1c8152e9f1",
"internal_ref": "VTO1740645600000A1B",
"method": "QRIS",
"provider": "configured_gateway",
"channel_code": "11",
"channel_name": "QRIS Realtime",
"amount": 10000,
"fee": 100,
"total_payment": 10100,
"net_coins": 10000,
"status": "credited",
"qr_string": "000201010212...",
"qr_image_url": "https://vtechotp.web.id/api/qr?data=000201010212...",
"qr_image_base64": "data:image/png;base64,iVBORw0KGgo...",
"expires_at": "2026-08-30T17:40:00.000Z",
"paid_at": "2026-08-30T17:15:42.000Z",
"credited_at": "2026-08-30T17:15:43.000Z",
"created_at": "2026-08-30T17:10:00.000Z",
"instructions": "Silakan scan kode QRIS menggunakan aplikasi m-banking atau e-wallet..."
}
}
Riwayat Transaksi Deposit
/deposit/history)
Mengambil daftar seluruh riwayat pembuatan tagihan deposit yang pernah dibuat pada akun Anda, lengkap dengan pagination dan filter status.
| Query Param | Tipe | Wajib? | Deskripsi |
|---|---|---|---|
| page | integer | Tidak | Halaman data (default: 1) |
| limit | integer | Tidak | Jumlah data per halaman (1 - 100, default: 20) |
| status | string | Tidak | Filter status transaksi: pending, credited, expired, failed |
curl -s "https://vtechotp.web.id/api/v1/deposits?page=1&limit=10&status=credited" \
-H "Authorization: Bearer vtk_your_api_token_here"
{
"success": true,
"data": {
"deposits": [
{
"id": "66ce30d97960cf1c8152e9f1",
"internal_ref": "VTO1740645600000A1B",
"method": "QRIS",
"provider": "configured_gateway",
"channel_code": "11",
"channel_name": "QRIS Realtime",
"amount": 10000,
"fee": 100,
"total_payment": 10100,
"net_coins": 10000,
"status": "credited",
"qr_string": "000201010212...",
"qr_image_url": "https://vtechotp.web.id/api/qr?data=000201010212...",
"qr_image_base64": "data:image/png;base64,iVBORw0KGgo...",
"expires_at": "2026-08-30T17:40:00.000Z",
"paid_at": "2026-08-30T17:15:42.000Z",
"credited_at": "2026-08-30T17:15:43.000Z",
"created_at": "2026-08-30T17:10:00.000Z"
}
],
"pagination": {
"page": 1,
"limit": 10,
"total": 1,
"total_pages": 1
}
}
}
Konfigurasi & Biaya Fee Deposit
/deposit/config)
Mendapatkan informasi batas minimum deposit, maksimum deposit, dan pengaturan biaya admin (fee) flat yang sedang aktif di sistem.
curl -s https://vtechotp.web.id/api/v1/deposits/config
{
"success": true,
"data": {
"min_deposit": 5000,
"max_deposit": 5000000,
"deposit_fee_flat": 100,
"deposit_fee_percent": 0,
"payment_provider": "configured_gateway",
"supported_methods": ["QRIS", "Virtual Account", "E-Wallet", "Retail"],
"currency": "IDR",
"notes": "1 Coin = Rp 1. Biaya admin fee ditambahkan ke total tagihan pembayaran."
}
}
Daftar Negara
Mendapatkan seluruh daftar negara yang tersedia beserta ID, kode ISO, dan kode panggilan telepon.
Daftar Layanan / Platform
Mendapatkan daftar platform/aplikasi yang didukung (seperti WhatsApp, Telegram, Google, TikTok, Instagram, dll.).
Daftar Harga Produk (Pricelist)
Mendapatkan daftar harga sewa nomor virtual real-time (setelah markup), ketersediaan stok, ID operator, dan catalog_product_id.
| Query Param | Tipe | Wajib? | Deskripsi |
|---|---|---|---|
| country_id | integer | Tidak | Filter berdasarkan ID negara (misal 6 untuk Indonesia) |
| platform_id | integer | Tidak | Filter berdasarkan ID layanan (misal 1 untuk WhatsApp) |
| operator_id | integer | Tidak | Filter berdasarkan ID operator tertentu |
Buat Order (Sewa Nomor Virtual)
Membuat pesanan sewa nomor baru. Saldo koin akun Anda akan dipotong otomatis sesuai harga setelah markup.
| Parameter Body | Tipe | Wajib? | Deskripsi |
|---|---|---|---|
| product_id | integer | Opsional | ID produk spesifik |
| catalog_product_id | integer | Opsional | ID katalog produk untuk routing otomatis |
| country_id | integer | Opsional | ID negara tujuan |
| platform_id | integer | Opsional | ID layanan/aplikasi |
| max_price | integer | Opsional | Batas harga maksimum dalam Rupiah |
| quantity | integer | Opsional | Jumlah nomor (1 - 10, default: 1) |
curl -s -X POST https://vtechotp.web.id/api/v1/orders/create \
-H "Authorization: Bearer vtk_your_api_token_here" \
-H "Content-Type: application/json" \
-d '{
"country_id": 6,
"platform_id": 1,
"max_price": 3000
}'
{
"success": true,
"data": {
"orders": [
{
"id": "6a85817c80524ba18c72834b",
"order_id": 982145,
"product_id": 142,
"service": "WhatsApp",
"country": "Indonesia",
"phone_number": "+6281234567890",
"price": 2500,
"status": "ACTIVE",
"expires_at": "2026-08-16T20:45:00.000Z",
"created_at": "2026-08-16T20:25:00.000Z"
}
]
}
}
Detail Order & Status OTP
Mengambil status terkini nomor, waktu kedaluwarsa, dan kode SMS/OTP yang telah masuk.
Batalkan Order & Refund Saldo
Membatalkan order yang masih berstatus ACTIVE (belum menerima SMS). Saldo koin yang telah dipotong akan langsung di-refund 100% ke akun Anda.
Selesaikan Order
Menandai pesanan telah selesai setelah Anda berhasil memverifikasi OTP di aplikasi tujuan.
Notifikasi Webhook Real-time
Alih-alih melakukan polling manual, daftarkan Webhook URL (HTTPS) agar server VTechOTP otomatis mengirimkan notifikasi HTTP POST instan saat SMS/OTP tiba atau pesanan selesai.
•
order.otp_received - Kode OTP telah masuk•
order.completed - Pesanan ditandai selesai•
order.canceled - Pesanan dibatalkan & saldo di-refund•
order.expired - Waktu sewa habis & saldo di-refund otomatis•
deposit.credited - Tagihan QRIS berhasil dibayar & saldo koin masuk ke akun
{
"event": "order.otp_received",
"timestamp": 1786905500,
"data": {
"order_id": 982145,
"service": "WhatsApp",
"country": "Indonesia",
"phone_number": "+6281234567890",
"price": 2500,
"status": "OTP_RECEIVED",
"otp_code": "482910",
"otp_message": "Kode WhatsApp Anda adalah 482-910",
"expires_at": "2026-08-16T20:45:00.000Z"
}
}
Verifikasi HMAC-SHA256 Signature
Setiap panggilan webhook menyertakan header X-Webhook-Signature untuk memastikan request benar-benar berasal dari server resmi VTechOTP.
const crypto = require('crypto');
app.post('/my-webhook-handler', (req, res) => {
const signature = req.headers['x-webhook-signature'];
const webhookSecret = 'sec_your_webhook_secret_here';
const expectedSig = 'sha256=' + crypto
.createHmac('sha256', webhookSecret)
.update(JSON.stringify(req.body))
.digest('hex');
if (signature !== expectedSig) {
return res.status(401).send('Invalid signature');
}
const { event, data } = req.body;
if (event === 'order.otp_received') {
console.log(`OTP Masuk: ${data.otp_code} untuk ${data.phone_number}`);
} else if (event === 'deposit.credited') {
console.log(`Deposit Berhasil: Rp ${data.net_coins} telah masuk.`);
}
res.status(200).send('OK');
});
Daftar Kode Error (Error Codes)
| Kode Error | HTTP Status | Keterangan |
|---|---|---|
| UNAUTHORIZED | 401 | Header API Token tidak disertakan dalam request |
| INVALID_TOKEN | 401 | API Token salah atau tidak terdaftar |
| PHONE_NOT_VERIFIED | 403 | Nomor WhatsApp belum diverifikasi pada akun Anda |
| API_ACCESS_DISABLED | 403 | Akses API untuk akun Anda dinonaktifkan oleh admin |
| SERVICE_MAINTENANCE | 503 | Layanan API secara global sedang dalam pemeliharaan |
| INSUFFICIENT_BALANCE | 409 | Saldo koin tidak mencukupi untuk melakukan order |
| MAX_ACTIVE_ORDERS_EXCEEDED | 429 | Maksimal 5 pesanan aktif secara bersamaan telah tercapai |
| NO_OFFER_AVAILABLE | 422 | Stok nomor untuk layanan/negara tersebut sedang kosong |
| ORDER_NOT_FOUND | 404 | Pesanan tidak ditemukan |
| MIN_DEPOSIT_ERROR | 422 | Nominal deposit di bawah batas minimum saluran pembayaran |
| MAX_DEPOSIT_ERROR | 422 | Nominal deposit melebihi batas maksimum saluran pembayaran |
| DEPOSIT_NOT_FOUND | 404 | Tagihan deposit tidak ditemukan |
| PAYMENT_CHANNEL_OFFLINE | 502 / 422 | Saluran pembayaran yang dipilih sedang gangguan/offline di payment gateway |
| GATEWAY_ERROR | 502 | Gagal berkomunikasi dengan gateway pembayaran |