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:
Waktu, Lifecycle & Cooldown Status
Setiap pesanan nomor virtual dan sewa email pada platform VTechOTP memiliki aturan waktu (timing), cooldown pembatalan, dan masa berlaku yang transparan untuk menjaga stabilitas sistem dan integritas saldo developer:
| Parameter Waktu | Durasi | Layanan Berlaku | Keterangan / Aksi Sistem |
|---|---|---|---|
| Timeout Masa Aktif (Expires) | 20 Menit (1.200 detik) |
OTP V1 & OTP V2, Sewa Email | Jika tidak ada SMS / OTP masuk hingga waktu habis, status otomatis menjadi EXPIRED dan saldo koin 100% dikembalikan secara instan via Atomic Refund. |
| Cooldown Pembatalan (V1) | 5 Menit (atau sesuai cancel_available_at) |
OTP Server 1 | Perlindungan sistem agar nomor tidak di-spam pembatalan. Setelah melewati waktu cooldown, order dapat dibatalkan melalui POST /otp/v1/order/{id}/cancel. |
| Cooldown Pembatalan (V2) | 2 Menit (120 detik) |
OTP Server 2 | Sistem mewajibkan nomor aktif minimal 120 detik sebelum bisa dibatalkan secara aman dengan refund penuh. |
| Cooldown Sewa Email | 2 Menit (120 detik) |
Sewa Email OTP | Pembatalan sewa email dapat dilakukan setelah 2 menit jika email verifikasi belum kunjung masuk. |
| Interval Polling Rekomendasi | 3 - 5 Detik |
Semua Layanan OTP | Jika tidak mengonfigurasi Webhook, lakukan polling GET detail order setiap 3-5 detik. Polling lebih cepat dari 1 detik dapat terkena HTTP 429 Rate Limit. |
| Idempotency TTL | 5 Menit |
Endpoint POST Create | Kirim header Idempotency-Key: your_uuid pada request pembuatan order / deposit untuk mencegah double-charge saat terjadi retry koneksi. |
Cek Saldo & Profil
Mengambil informasi saldo koin akun (1 koin = Rp 1), jumlah order aktif, dan status konfigurasi akun Anda.
curl -s https://app.otp.vtech.biz.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 sistem 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 5.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://app.otp.vtech.biz.id/api/v1/deposits/channels
{
"success": true,
"data": {
"payment_gateway": "vtechotp",
"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": 5000,
"maximum": 10000000,
"fee": "0.7%",
"icon_url": "https://app.otp.vtech.biz.id/images/qris-logo.png",
"status": "ON",
"is_active": true
},
{
"id": "1",
"service_id": "1",
"name": "Virtual Account Bank BCA",
"type": "VA",
"minimum": 5000,
"maximum": 10000000,
"fee": 4900,
"icon_url": "https://app.otp.vtech.biz.id/images/channels/bca.png",
"status": "ON",
"is_active": true
},
{
"id": "2",
"service_id": "2",
"name": "Virtual Account Bank BRI",
"type": "VA",
"minimum": 5000,
"maximum": 50000000,
"fee": 2500,
"icon_url": "https://app.otp.vtech.biz.id/images/channels/briva.png",
"status": "ON",
"is_active": true
},
{
"id": "18",
"service_id": "18",
"name": "ALFAMART",
"type": "RETAIL",
"minimum": 5000,
"maximum": 5000000,
"fee": 2500,
"icon_url": "https://app.otp.vtech.biz.id/images/channels/alfamart.png",
"status": "ON",
"is_active": true
}
]
}
}
Buat Tagihan Deposit (QRIS, VA, E-Wallet, Retail)
/deposit/create, /deposits)
Membuat tagihan invoice deposit saldo koin baru secara instan. 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 5.000 untuk QRIS, min. Rp 5.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://app.otp.vtech.biz.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": "qris",
"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://app.otp.vtech.biz.id/api/qr?data=00020101021226540014ID.LINKAJA.WWW0118...",
"qr_image_base64": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAUAAAAFACAYAAAD6umHTAA...",
"virtual_account": "",
"payment_code": "",
"payment_url": "https://app.otp.vtech.biz.id/pay/invoice/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 gateway pembayaran 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://app.otp.vtech.biz.id/api/v1/deposits/VTO1740645600000A1B \
-H "Authorization: Bearer vtk_your_api_token_here"
{
"success": true,
"data": {
"id": "66ce30d97960cf1c8152e9f1",
"internal_ref": "VTO1740645600000A1B",
"method": "QRIS",
"provider": "qris",
"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://app.otp.vtech.biz.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://app.otp.vtech.biz.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": "qris",
"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://app.otp.vtech.biz.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://app.otp.vtech.biz.id/api/v1/deposits/config
{
"success": true,
"data": {
"min_deposit": 5000,
"max_deposit": 5000000,
"deposit_fee_flat": 100,
"deposit_fee_percent": 0,
"payment_provider": "instant",
"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 |
| sort | string | Tidak | Mode pengurutan: cheapest (termurah) atau quality / recommended (kualitas terbaik & ketersediaan stok melimpah) |
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://app.otp.vtech.biz.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.
Cek Stok & Harga Akun Gmail
Mendapatkan informasi real-time mengenai ketersediaan stok dan harga beli akun Gmail fresh siap pakai.
{
"success": true,
"data": {
"price": 5980,
"raw_price": 4480,
"stock": 4376,
"active": true
}
}
Beli 1 Akun Gmail Siap Pakai
Membeli 1 akun Gmail secara instan. Saldo koin akan terpotong otomatis dan kredensial langsung dikembalikan pada payload response.
{
"success": true,
"data": {
"id": "67be5691024ad29fa114",
"order_id": 849201,
"email": "budi.santoso819@gmail.com",
"password": "PassSecure892!",
"recovery_email": "recov992@rambler.ru",
"price": 5980,
"status": "active",
"created_at": "2026-10-27T03:30:00.000Z",
"new_balance": 44020
}
}
Riwayat Pembelian Akun Gmail
Mendapatkan daftar seluruh akun Gmail yang pernah Anda beli melalui akun Anda.
Daftar Domain Sewa Email
Mengambil daftar domain email sekali pakai yang tersedia beserta tarif dan ketersediaan stok untuk situs target yang Anda tentukan.
| Query Param | Tipe | Wajib? | Deskripsi |
|---|---|---|---|
| site | string | Opsional | Domain situs target (default: google.com, contoh lain: telegram.com, tiktok.com) |
Mulai Sewa Alamat Email Sekali Pakai
Menyewa satu alamat email disposable. Anda memiliki waktu 20 menit untuk menerima kode OTP.
| Parameter Body | Tipe | Wajib? | Deskripsi |
|---|---|---|---|
| site | string | Wajib | Nama situs/layanan (misal: google.com) |
| domain | string | Wajib | Pilihan domain yang disewa (misal: gmail.com atau email.com) |
{
"success": true,
"data": {
"rental_id": "67be5691024ad29fa119",
"site": "google.com",
"domain": "gmail.com",
"email_address": "user8192@gmail.com",
"price": 1299,
"status": "waiting",
"expires_at": "2026-10-27T03:50:00.000Z",
"cancel_available_at": "2026-10-27T03:32:00.000Z"
}
}
Cek Status & Kode OTP Sewa Email
Memeriksa apakah email verifikasi atau kode OTP sudah diterima.
{
"success": true,
"data": {
"rental_id": "67be5691024ad29fa119",
"email_address": "user8192@gmail.com",
"code": "739104",
"message": "G-739104 is your Google verification code.",
"status": "received"
}
}
Batalkan Sewa Email & Refund Saldo
Membatalkan sewa email yang belum menerima OTP setelah masa tunggu minimum (2 menit). Saldo sewa akan dikembalikan 100%.
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 |
| GATEWAY_ERROR | 502 | Gagal berkomunikasi dengan gateway pembayaran |