Node.js adalah pilihan populer para developer backend untuk membangun sistem notifikasi, bot, dan integrasi API — dan kini semakin banyak yang memanfaatkannya untuk mengirim pesan WhatsApp secara otomatis. Dengan wagate.id, Anda bisa mengirim pesan teks maupun attachment (gambar, PDF, video, audio) langsung dari kode Node.js Anda dalam hitungan menit.
Panduan ini mencakup segalanya: setup awal, kirim teks, kirim berbagai jenis attachment, menerima pesan masuk via webhook, hingga contoh integrasi di aplikasi Express.js.
💡 wagate.id adalah platform WhatsApp Gateway lokal buatan Indonesia dengan REST API yang sederhana, harga terjangkau mulai Rp 25.000/bulan per perangkat, dan uji coba gratis 7 hari — tanpa kartu kredit. Daftar sekarang →
Prasyarat
- Node.js v18 atau lebih baru
- npm atau yarn
- Akun wagate.id dengan perangkat WhatsApp yang sudah terhubung
- API Key dan Device ID dari dashboard wagate.id
Langkah 1: Daftar & Siapkan Kredensial
- Daftar di wagate.id/register
- Hubungkan perangkat WhatsApp: menu Perangkat WA → Tambah → Scan QR
- Buat API Key: menu API Keys → Tambah — salin key-nya
- Catat Device ID dari halaman detail perangkat
Setelah selesai, Anda punya dua nilai penting:
API_KEY— format:wgk_live_xxxxxxxxxxxxxxxxDEVICE_ID— ID unik perangkat WhatsApp Anda
Langkah 2: Setup Project Node.js
mkdir wa-notifikasi && cd wa-notifikasi
npm init -y
npm install axios form-data dotenv
Buat file .env:
WA_API_KEY=wgk_live_GANTI_DENGAN_API_KEY_ANDA
WA_DEVICE_ID=GANTI_DENGAN_DEVICE_ID_ANDA
WA_BASE_URL=https://wagate.id/api
🔒 Jangan pernah commit file.envke Git. Tambahkan.envke.gitignoreAnda.
Bagian 1: Kirim Pesan Teks
Buat file wagateway.js:
require('dotenv').config();
const axios = require('axios');
const client = axios.create({
baseURL: process.env.WA_BASE_URL,
headers: {
'X-Api-Key': process.env.WA_API_KEY,
'Content-Type': 'application/json',
'Accept': 'application/json',
},
timeout: 15000,
});
/**
* Kirim pesan teks ke satu nomor WhatsApp.
* @param {string} phone - Format internasional tanpa +, contoh: 6281234567890
* @param {string} message - Teks pesan (mendukung *bold*, _italic_, ~coret~)
*/
async function kirimPesan(phone, message) {
try {
const { data } = await client.post('/send', {
device_id: process.env.WA_DEVICE_ID,
phone: normalizePhone(phone),
message,
});
return { success: data.success, messageId: data.message_id };
} catch (err) {
const msg = err.response?.data?.message ?? err.message;
console.error(`[WA] Gagal kirim ke ${phone}:`, msg);
return { success: false, error: msg };
}
}
/** Normalisasi nomor: 081234... → 6281234... */
function normalizePhone(phone) {
phone = phone.replace(/\D/g, '');
if (phone.startsWith('0')) phone = '62' + phone.slice(1);
return phone;
}
module.exports = { kirimPesan, normalizePhone, client };
Contoh Penggunaan
const { kirimPesan } = require('./wagateway');
// Notifikasi pesanan
await kirimPesan('6281234567890',
`Halo! 👋 Pesanan Anda *ORD-2024-001* sudah dikonfirmasi.\n\n` +
`📦 Estimasi pengiriman: 2–3 hari kerja\n` +
`🔍 Lacak: https://toko.com/lacak/ORD-2024-001`
);
// Kode OTP
const otp = Math.floor(100000 + Math.random() * 900000);
await kirimPesan('6281234567890',
`🔐 Kode OTP Anda: *${otp}*\n\nBerlaku 5 menit. Jangan bagikan ke siapapun!`
);
// Auto-reply bot sederhana
async function handleIncoming(from, text) {
const cmd = text.toLowerCase().trim();
const replies = {
'harga' : '💰 Lihat harga kami di https://wagate.id/pricing',
'daftar' : '📝 Daftar gratis di https://wagate.id/register',
'bantuan': '🆘 Hubungi kami: support@wagate.id',
};
const balas = replies[cmd] ?? '👋 Ketik *bantuan* untuk melihat menu layanan kami.';
await kirimPesan(from, balas);
}
Bagian 2: Kirim Attachment (File)
Untuk mengirim file seperti gambar, PDF, video, atau audio, kita menggunakan multipart/form-data dengan package form-data.
Fungsi Kirim Attachment Universal
require('dotenv').config();
const axios = require('axios');
const FormData = require('form-data');
const fs = require('fs');
const path = require('path');
const { normalizePhone } = require('./wagateway');
/**
* Kirim file attachment ke WhatsApp.
*
* @param {string} phone - Nomor tujuan (628xxx)
* @param {string} filePath - Path lokal file yang akan dikirim
* @param {string} [caption] - Keterangan gambar/video (opsional)
* @returns {Promise<{success: boolean, messageId?: string, error?: string}>}
*/
async function kirimAttachment(phone, filePath, caption = '') {
const form = new FormData();
form.append('device_id', process.env.WA_DEVICE_ID);
form.append('phone', normalizePhone(phone));
form.append('file', fs.createReadStream(filePath), path.basename(filePath));
if (caption) {
form.append('caption', caption);
}
try {
const { data } = await axios.post(
`${process.env.WA_BASE_URL}/send`,
form,
{
headers: {
...form.getHeaders(),
'X-Api-Key': process.env.WA_API_KEY,
},
timeout: 30000, // file upload butuh timeout lebih lama
}
);
return { success: data.success, messageId: data.message_id };
} catch (err) {
const msg = err.response?.data?.message ?? err.message;
console.error(`[WA] Gagal kirim attachment ke ${phone}:`, msg);
return { success: false, error: msg };
}
}
module.exports = { kirimAttachment };
Contoh: Kirim Gambar dengan Caption
const { kirimAttachment } = require('./attachment');
// Kirim gambar promosi
await kirimAttachment(
'6281234567890',
'./assets/promo-flash-sale.jpg',
'🔥 *Flash Sale 11.11!*\nDiskon hingga 70% — hanya hari ini!\nhttps://toko.com/sale'
);
// Kirim struk pembelian (PDF)
await kirimAttachment(
'6281234567890',
`./invoices/INV-${orderId}.pdf`,
`📄 Invoice pesanan #${orderId} terlampir.`
);
Contoh: Kirim Video
// Kirim video tutorial produk
await kirimAttachment(
'6285678901234',
'./videos/cara-pakai-produk.mp4',
'🎬 Video panduan penggunaan produk Anda. Selamat menikmati!'
);
Contoh: Kirim Dokumen Word / Excel
// Kirim laporan Excel
await kirimAttachment(
'6289012345678',
'./reports/laporan-penjualan-juni.xlsx',
'📊 Laporan penjualan bulan Juni 2025 terlampir.'
);
// Kirim e-ticket
await kirimAttachment(
'6281234567890',
'./tickets/eticket-booking-001.pdf',
'🎫 E-ticket Anda sudah siap! Tunjukkan QR code ini saat check-in.'
);
Jenis File yang Didukung
| Jenis | Ekstensi | Ukuran Maks |
|---|---|---|
| 🖼️ Gambar | jpg, jpeg, png, webp, gif | 16 MB |
| 📄 Dokumen | pdf, doc, docx, xls, xlsx, ppt | 100 MB |
| 🎬 Video | mp4, 3gp, mkv | 64 MB |
| 🎵 Audio | mp3, ogg, m4a, wav | 16 MB |
Bagian 3: Kirim ke Banyak Nomor (Broadcast)
const { kirimPesan } = require('./wagateway');
/**
* Broadcast pesan ke banyak nomor dengan delay aman.
* @param {string[]} phones - Array nomor tujuan
* @param {string} message - Teks pesan
* @param {number} delayMs - Jeda antar pesan (default 3 detik)
*/
async function broadcast(phones, message, delayMs = 3000) {
let sent = 0, failed = 0;
for (let i = 0; i < phones.length; i++) {
const result = await kirimPesan(phones[i], message);
result.success ? sent++ : failed++;
console.log(`[${i + 1}/${phones.length}] ${phones[i]} → ${result.success ? '✓' : '✗'}`);
// Delay antar pesan (kecuali terakhir)
if (i < phones.length - 1) {
await new Promise(r => setTimeout(r, delayMs));
}
}
console.log(`\nBroadcast selesai: ${sent} berhasil, ${failed} gagal.`);
return { sent, failed };
}
// Contoh penggunaan
const daftarKontak = [
'6281234567890',
'6285678901234',
'6289012345678',
];
await broadcast(
daftarKontak,
'🎉 Halo! Ada promo spesial untuk Anda.\nDiskon 20% untuk semua produk hari ini!\nhttps://toko.com/promo',
3000 // 3 detik antar pesan
);
⏱️ Penting: Selalu beri jeda minimal 2–3 detik antar pesan broadcast. Pengiriman terlalu cepat bisa memicu sistem anti-spam WhatsApp dan berujung pada pembatasan nomor Anda.
Bagian 4: Terima Pesan Masuk via Webhook (Express.js)
Agar aplikasi Anda bisa memproses balasan dari pelanggan secara real-time, buat server webhook dengan Express.js:
npm install express
// webhook-server.js
require('dotenv').config();
const express = require('express');
const { kirimPesan } = require('./wagateway');
const app = express();
app.use(express.json());
/**
* Endpoint webhook — daftarkan URL ini di dashboard wagate.id
* Pengaturan Perangkat → Webhook URL → https://yourdomain.com/webhook/wa
*/
app.post('/webhook/wa', async (req, res) => {
const { event, from, message, sessionId } = req.body;
// Hanya proses pesan masuk
if (event !== 'message.received') {
return res.json({ ok: true });
}
console.log(`[WA] Pesan dari ${from}: ${message}`);
const teks = (message ?? '').toLowerCase().trim();
// Router kata kunci sederhana
if (teks.includes('harga') || teks.includes('price')) {
await kirimPesan(from, '💰 Cek harga lengkap kami di https://wagate.id/pricing\n\nMulai dari Rp 25.000/bulan per perangkat.');
} else if (teks.includes('daftar') || teks.includes('register')) {
await kirimPesan(from, '📝 Daftar gratis 7 hari di https://wagate.id/register\nTidak perlu kartu kredit!');
} else if (teks.includes('demo') || teks.includes('coba')) {
await kirimPesan(from, '🚀 Coba langsung wagate.id gratis 7 hari:\nhttps://wagate.id/register\n\nOr hubungi kami di https://wagate.id/contact');
} else if (teks === 'bantuan' || teks === 'help') {
await kirimPesan(from,
'🤖 *Menu Bantuan*\n\n' +
'Ketik salah satu kata kunci:\n' +
'• *harga* — info tarif berlangganan\n' +
'• *daftar* — cara mendaftar\n' +
'• *demo* — minta demo langsung\n' +
'• *cs* — hubungi tim kami'
);
} else if (teks === 'cs' || teks.includes('manusia') || teks.includes('agen')) {
await kirimPesan(from, '👤 Menghubungkan Anda ke tim CS kami...\nMohon tunggu sebentar atau email ke support@wagate.id');
} else {
// Default reply
await kirimPesan(from, '👋 Halo! Saya adalah bot wagate.id.\n\nKetik *bantuan* untuk melihat menu, atau langsung bertanya — saya siap membantu! 😊');
}
res.json({ ok: true });
});
const PORT = process.env.PORT || 3001;
app.listen(PORT, () => console.log(`Webhook server berjalan di port ${PORT}`));
Jalankan server:
node webhook-server.js
# Webhook server berjalan di port 3001
Daftarkan URL webhook di dashboard wagate.id: Pengaturan Perangkat → Webhook URL, isi dengan URL publik server Anda (contoh: https://api.toko.com/webhook/wa).
🌐 Untuk development lokal, gunakan ngrok untuk expose server lokal ke internet: ngrok http 3001
Bagian 5: Integrasi di Aplikasi Express/NestJS yang Sudah Ada
Sebagai Modul Reusable
// services/whatsapp.service.js
require('dotenv').config();
const axios = require('axios');
const FormData = require('form-data');
const fs = require('fs');
const path = require('path');
class WhatsAppService {
constructor() {
this.http = axios.create({
baseURL: process.env.WA_BASE_URL ?? 'https://wagate.id/api',
headers: {
'X-Api-Key': process.env.WA_API_KEY,
Accept: 'application/json',
},
timeout: 20000,
});
this.deviceId = process.env.WA_DEVICE_ID;
}
normalizePhone(phone) {
phone = phone.replace(/\D/g, '');
return phone.startsWith('0') ? '62' + phone.slice(1) : phone;
}
async sendText(phone, message) {
const { data } = await this.http.post('/send', {
device_id: this.deviceId,
phone: this.normalizePhone(phone),
message,
});
return data.success;
}
async sendFile(phone, filePath, caption = '') {
const form = new FormData();
form.append('device_id', this.deviceId);
form.append('phone', this.normalizePhone(phone));
form.append('file', fs.createReadStream(filePath), path.basename(filePath));
if (caption) form.append('caption', caption);
const { data } = await this.http.post('/send', form, {
headers: { ...form.getHeaders(), timeout: 30000 },
});
return data.success;
}
async broadcast(phones, message, delayMs = 3000) {
const results = [];
for (let i = 0; i < phones.length; i++) {
const ok = await this.sendText(phones[i], message).catch(() => false);
results.push({ phone: phones[i], sent: ok });
if (i < phones.length - 1) await new Promise(r => setTimeout(r, delayMs));
}
return results;
}
}
module.exports = new WhatsAppService();
Penggunaan di Route Express
const express = require('express');
const wa = require('./services/whatsapp.service');
const router = express.Router();
// POST /api/orders — buat pesanan + kirim notifikasi WA
router.post('/orders', async (req, res) => {
const { customerPhone, customerName, orderId, total } = req.body;
// Simpan ke database (contoh)
// await Order.create(req.body);
// Kirim notifikasi WA
await wa.sendText(customerPhone,
`Halo ${customerName}! 👋\n\n` +
`✅ Pesanan *#${orderId}* berhasil dibuat.\n` +
`💰 Total: Rp ${Number(total).toLocaleString('id-ID')}\n\n` +
`Kami akan segera memprosesnya. Terima kasih! 🙏`
);
res.json({ success: true, orderId });
});
// POST /api/invoices/:id/send — kirim invoice PDF via WA
router.post('/invoices/:id/send', async (req, res) => {
const { phone } = req.body;
const filePath = `./storage/invoices/INV-${req.params.id}.pdf`;
const ok = await wa.sendFile(phone, filePath,
`📄 Invoice *#${req.params.id}* terlampir. Terima kasih atas kepercayaan Anda!`
);
res.json({ success: ok });
});
module.exports = router;
Tips & Best Practices
- 🔒 Simpan API Key di environment variable — jangan hardcode di kode atau commit ke Git
- ⏱️ Gunakan delay 2–3 detik untuk broadcast agar tidak terkena rate-limit WhatsApp
- 📱 Normalisasi nomor — selalu convert ke format
628xxxsebelum kirim - 🔄 Implement retry dengan backoff — jika gagal, coba lagi setelah 5–10 detik
- 📋 Log setiap pengiriman — simpan ke database untuk audit dan debugging
- 🧪 Test di nomor sendiri dulu sebelum deploy ke production
- 📂 Compress file besar sebelum kirim — gambar di bawah 1MB lebih cepat tersampaikan
- ⚠️ Handle error dengan graceful — jangan biarkan error kirim WA merusak alur utama aplikasi
Kenapa Pilih wagate.id untuk Proyek Node.js Anda?
Dibanding alternatif lain, wagate.id menawarkan keunggulan yang membuatnya ideal untuk developer Node.js:
| Fitur | wagate.id |
|---|---|
| REST API standar | ✅ JSON + multipart/form-data |
| Webhook real-time | ✅ HTTP POST ke endpoint Anda |
| Multi-device | ✅ Kelola banyak nomor WA |
| Shared CS Inbox | ✅ Satu nomor, banyak agen CS |
| Broadcast massal | ✅ 1000+ kontak sekaligus |
| Jadwal pesan | ✅ Kirim di waktu tertentu |
| Dashboard monitoring | ✅ Log & status real-time |
| Harga | ✅ Mulai Rp 25.000/bulan/perangkat |
| Trial | ✅ Gratis 7 hari, tanpa kartu kredit |
🚀 Sedang membangun sistem notifikasi, bot, atau platform SaaS? wagate.id mendukung multi-device dan multi-API-key — cocok untuk memisahkan environment (dev/staging/production) atau melayani banyak klien dari satu akun. Lihat paket harga →
Kesimpulan
Mengintegrasikan WhatsApp ke aplikasi Node.js kini semudah install package dan panggil satu fungsi. Dengan wagate.id, Anda mendapatkan:
- ✅ Kirim pesan teks dengan format WhatsApp (bold, italic, emoji)
- ✅ Kirim attachment: gambar, PDF, video, audio hingga 100 MB
- ✅ Webhook real-time untuk auto-reply dan chatbot
- ✅ Broadcast ke ribuan kontak dengan delay aman
- ✅ Dashboard monitoring status pengiriman
- ✅ CS Inbox — tim support balas chat langsung dari browser
Daftar sekarang di wagate.id/register — gratis 7 hari, tidak perlu kartu kredit, dan kirim pesan pertama Anda dari Node.js dalam 10 menit.