Semua jenis pesan dikirim lewat satu fungsi utama: sendMessage(jid, content, options). Plus relai manual pake relayMessage buat kasus advanced.
| Parameter | Tipe | Keterangan |
|---|---|---|
jid | string | Tujuan JID. Contoh: 628xxx@s.whatsapp.net, xxx@g.us |
content | AnyMessageContent | Object yang isinya tergantung tipe pesan. Lihat tabel tiap tipe di bawah |
options | MiscMessageGenerationOptions | Konfigurasi tambahan: quoted, ephemeral, dll |
| Option | Tipe | Keterangan |
|---|---|---|
quoted | WAMessage | Pesan yang mau di-reply. Isi dengan object WAMessage asli dari event |
ephemeralExpiration | number | string | Buat pesan disappearing. Nilai: 86400 (24h), 604800 (7d), 7776000 (90d) |
timestamp | Date | Override timestamp pesan |
mediaUploadTimeoutMs | number | Timeout upload media ke server WA |
statusJidList | string[] | Daftar JID buat broadcast status |
backgroundColor | string | Warna background status |
font | number | Font status |
broadcast | boolean | Broadcast message |
useCachedGroupMetadata | boolean | Gunakan cache metadata grup (default true) |
messageId | string | Override ID pesan dengan kustom |
sendMessage balik Promise<WAMessage>. Object ini punya .key (MessageKey) yang bisa dipake buat edit, delete, reply:
const sent = await sock.sendMessage(jid, { text: 'Halo' }) console.log(sent.key.id) // ID pesan console.log(sent.key) // { id, remoteJid, fromMe }
Kalo emitOwnEvents: true (default), pesan yang dikirim bakal muncul juga di event messages.upsert — jadi lu bisa handle pesan sendiri lewat event listener.
Tipe paling dasar. Field text berisi string yang mau dikirim. mentions buat nyebut orang, mentionAll buat nyebut semua.
| Field | Tipe | Wajib | Keterangan |
|---|---|---|---|
text | string | Ya | Isi pesan teks |
mentions | string[] | Tidak | Daftar JID yang di-mention |
mentionAll | boolean | Tidak | Mention semua peserta grup |
contextInfo | proto.IContextInfo | Tidak | Context info kustom |
linkPreview | WAUrlInfo | null | Tidak | Override link preview. Null = matikan preview |
await sock.sendMessage('6281234567890@s.whatsapp.net', { text: 'Halo! Pesan dari bot.' }) // Pake mention await sock.sendMessage('123@g.us', { text: 'Halo @6281234567890!', mentions: ['6281234567890@s.whatsapp.net'], }) // Pake mention all await sock.sendMessage('123@g.us', { text: 'Halo semua!', mentionAll: true, }) // Reply / quote await sock.sendMessage(jid, { text: 'Ini balasan' }, { quoted: originalMsg }) // Disappearing message await sock.sendMessage(jid, { text: 'Lenyap 24 jam' }, { ephemeralExpiration: 86400 }) // View once await sock.sendMessage(jid, { text: 'Sekali lihat', viewOnce: true }) // Edit pesan yang udah terkirim await sock.sendMessage(jid, { text: 'Teks baru', edit: messageKey })
originalMsg adalah object WAMessage lengkap dari event messages.upsert. Cukup simpen di memory/database, tinggal oper ke quoted.
Field image nerima Buffer, URL (via { url: string }), atau Readable stream.
| Field | Tipe | Wajib | Keterangan |
|---|---|---|---|
image | WAMediaUpload | Ya | Buffer / { url: string } / Readable stream |
caption | string | Tidak | Keterangan gambar |
mentions | string[] | Tidak | Mention di caption |
jpegThumbnail | string / Buffer | Tidak | Thumbnail custom (string Base64 atau Buffer) |
width / height | number | Tidak | Dimensi gambar |
contextInfo | proto.IContextInfo | Tidak | Context info |
viewOnce | boolean | Tidak | View once |
albumParentKey | WAMessageKey | Tidak | Key album parent (kalo bagian dari album) |
// Dari URL await sock.sendMessage(jid, { image: { url: 'https://example.com/foto.jpg' }, caption: 'Keren' }) // Dari Buffer await sock.sendMessage(jid, { image: fs.readFileSync('./foto.jpg'), caption: 'Lokal' }) // View once image await sock.sendMessage(jid, { image: { url: './foto.jpg' }, viewOnce: true })
ptv: true = video note (lingkaran). gifPlayback: true = GIF animasi.
| Field | Keterangan |
|---|---|
video | Buffer / URL / stream |
caption | Keterangan |
gifPlayback | true = kirim sebagai GIF |
ptv | true = video note (lingkaran) |
jpegThumbnail | Thumbnail custom |
width / height | Dimensi |
mentions | Mention di caption |
await sock.sendMessage(jid, { video: { url: './video.mp4' }, caption: 'Video' }) await sock.sendMessage(jid, { video: { url: './video.mp4' }, ptv: true }) await sock.sendMessage(jid, { video: { url: './video.gif' }, gifPlayback: true })
ptt: true = voice note. seconds bisa dikasih tau durasinya (opsional).
| Field | Keterangan |
|---|---|
audio | Buffer / URL / stream |
ptt | true = voice note |
seconds | Durasi audio dalam detik |
mimetype | Misal: audio/ogg; codecs=opus, audio/mp4, audio/aac |
// Voice note await sock.sendMessage(jid, { audio: { url: './voice.ogg' }, mimetype: 'audio/ogg; codecs=opus', ptt: true }) // Audio biasa await sock.sendMessage(jid, { audio: { url: './lagu.mp3' }, mimetype: 'audio/mp4' })
Kirim file apa aja. mimetype harus sesuai.
| Field | Keterangan |
|---|---|
document | Buffer / URL / stream |
fileName | Nama file yang tampil |
mimetype | Wajib. Contoh: application/pdf |
caption | Keterangan |
contextInfo | Context info |
await sock.sendMessage(jid, { document: { url: './file.pdf' }, fileName: 'dokumen.pdf', mimetype: 'application/pdf', caption: 'Ini file PDF', })
Kirim sticker. isAnimated kalo sticker animated (webp dengan frame banyak).
| Field | Keterangan |
|---|---|
sticker | Buffer / URL (webp) |
isAnimated | true kalo sticker animasi |
width / height | Dimensi opsional |
await sock.sendMessage(jid, { sticker: fs.readFileSync('./sticker.webp') }) await sock.sendMessage(jid, { sticker: { url: './animasi.webp' }, isAnimated: true })
Buat polling dengan pilihan. selectableCount: 1 = pilih satu, >1 = pilih banyak. values: array pilihan.
| Field | Tipe | Keterangan |
|---|---|---|
name | string | Pertanyaan polling |
values | string[] | Pilihan yang tersedia |
selectableCount | number | 1 =单选, >1 = multi-select |
messageSecret | Uint8Array | 32 byte secret buat enkripsi vote |
toAnnouncementGroup | boolean | Untuk grup announcement |
await sock.sendMessage(jid, { poll: { name: 'Framework favorit?', values: ['Next.js', 'React', 'Vue', 'Svelte'], selectableCount: 1, } }) // Multi-select await sock.sendMessage(jid, { poll: { name: 'Skill apa yang lu kuasai?', values: ['TypeScript', 'Python', 'Go', 'Rust'], selectableCount: 3, } })
Kirim lokasi peta. Pake object proto.Message.ILocationMessage.
| Field | Keterangan |
|---|---|
degreesLatitude | Garis lintang (-6.2) |
degreesLongitude | Garis bujur (106.8) |
name | Nama lokasi (opsional) |
address | Alamat (opsional) |
comment | Komentar (opsional) |
await sock.sendMessage(jid, { location: { degreesLatitude: -6.2, degreesLongitude: 106.8, name: 'Jakarta' } })
Kirim kontak berupa vCard.
| Field | Keterangan |
|---|---|
contacts.displayName | Nama yang tampil |
contacts.contacts | Array { vcard: string } |
const vcard = [ 'BEGIN:VCARD', 'VERSION:3.0', 'FN:Nama Kontak', 'TEL;waid=628xxx:+6281234567890', 'END:VCARD', ].join('\n') await sock.sendMessage(jid, { contacts: { displayName: 'Nama Kontak', contacts: [{ vcard }] } })
Kasih atau hapus reaksi emoji ke pesan yang udah ada. react.text = emoji, kalo string kosong berarti hapus reaksi.
Harus pake sendMessage — bukan fungsi separate.
// Kasih reaksi 🔥 await sock.sendMessage(jid, { react: { text: '🔥', key: messageKey } }) // Hapus reaksi await sock.sendMessage(jid, { react: { text: '', key: messageKey } })
Ubah teks pesan yang udah dikirim. edit diisi MessageKey pesan target. Text baru lewat text atau caption.
Hanya bisa edit pesan sendiri (fromMe: true). Batas waktu: ga ada yg pasti, tapi biasanya masih bisa dalam 24 jam.
// Edit teks await sock.sendMessage(jid, { text: 'Teks yang diedit', edit: messageKey }) // Edit caption media await sock.sendMessage(jid, { image: { url: 'foto.jpg' }, caption: 'Caption baru', edit: messageKey })
messageKey didapat dari sent.key kalo dikirim sendiri, atau dari msg.key di event messages.upsert.
Hapus pesan. delete diisi MessageKey.
delete: messageKey ajaremoteJid di messageKey, dan fromMe: falseedit = '7' untuk delete sendiri, edit = '8' untuk admin delete// Hapus pesan sendiri await sock.sendMessage(jid, { delete: messageKey }) // Admin hapus pesan orang di grup await sock.sendMessage(jid, { delete: { id: msgKey.id, remoteJid: jid, fromMe: false, participant: msgKey.participant } })
Teruskan pesan dari satu chat ke chat lain. forward = object WAMessage asli yang mau diforward. force: true untuk ilangin label "Forwarded".
// Forward biasa (ada label "Forwarded") await sock.sendMessage(jidTujuan, { forward: originalMessage }) // Force forward (tanpa label) await sock.sendMessage(jidTujuan, { forward: originalMessage, force: true })
Tambah viewOnce: true ke tipe pesan apa pun. Penerima cuma bisa liat sekali.
await sock.sendMessage(jid, { image: { url: './rahasia.jpg' }, viewOnce: true }) await sock.sendMessage(jid, { video: { url: './video.mp4' }, viewOnce: true }) await sock.sendMessage(jid, { text: 'Pesan sekali lihat', viewOnce: true }) await sock.sendMessage(jid, { audio: { url: './voice.ogg' }, viewOnce: true, ptt: true })
Dua mode: set disappearing buat seluruh chat, atau kirim 1 pesan yang ilang.
Pake field disappearingMessagesInChat. Tipe boolean | number:
true = 7 hari (default WA)86400 = 24 jam604800 = 7 hari7776000 = 90 hari0 = matikanIni cuma bisa di grup. Kalo di personal chat pake updateDefaultDisappearingMode.
// Set 24 jam di grup await sock.sendMessage(jid, { disappearingMessagesInChat: 86400 }) // Matikan await sock.sendMessage(jid, { disappearingMessagesInChat: 0 })
Pake option ephemeralExpiration di parameter ke-3:
await sock.sendMessage(jid, { text: 'Pesan rahasia' }, { ephemeralExpiration: 86400 }) await sock.sendMessage(jid, { image: { url: './foto.jpg' } }, { ephemeralExpiration: 604800 })
Kirim beberapa media yang tergabung jadi satu album. Gambar/video pertama jadi cover/sampul.
album: { expectedImageCount, expectedVideoCount } — ini jadi parent albumalbumParentKey dari hasil kiriman pertama (= sent.key)albumParentKey di tiap media// 1. Kirim gambar pertama (parent album) const album = await sock.sendMessage(jid, { image: { url: './1.jpg' }, caption: 'Album liburan', album: { expectedImageCount: 3 }, }) // 2. Kirim gambar kedua dan ketiga await sock.sendMessage(jid, { image: { url: './2.jpg' }, albumParentKey: album.key }) await sock.sendMessage(jid, { image: { url: './3.jpg' }, albumParentKey: album.key })
Buat undangan event dengan tanggal, deskripsi, lokasi, dan tombol RSVP otomatis dari WA.
| Field | Tipe | Keterangan |
|---|---|---|
name | string | Nama event |
description | string | Deskripsi event |
startDate | Date | Waktu mulai |
endDate | Date | Waktu selesai (opsional) |
location | WALocationMessage | Lokasi (latitude, longitude, name) |
call | 'audio' | 'video' | Tambah tombol call link |
isCancelled | boolean | Tandai event dibatalkan |
isScheduleCall | boolean | Jadwalkan panggilan |
extraGuestsAllowed | boolean | Izinkan tamu tambahan |
await sock.sendMessage(jid, { event: { name: 'Meetup Komunitas', description: 'Diskusi santai tentang teknologi terkini', startDate: new Date('2025-07-01T10:00:00+07:00'), endDate: new Date('2025-07-01T12:00:00+07:00'), location: { degreesLatitude: -6.2, degreesLongitude: 106.8, name: 'Jakarta Pusat', }, call: 'video', } })
Sematkan pesan di chat. Butuh MessageKey pesan target.
| Field | Tipe | Keterangan |
|---|---|---|
pin | WAMessageKey | Key pesan yang mau di-pin |
type | proto.PinInChat.Type | 1 = PINNED, 2 = UNPINNED |
time | 86400 | 604800 | 2592000 | Durasi pin: 24h / 7d / 30d |
// Pin pesan selama 7 hari await sock.sendMessage(jid, { pin: messageKey, time: 604800, }) // Unpin await sock.sendMessage(jid, { pin: messageKey, type: 2, })
Kirim gambar/video kualitas HD (tanpa kompresi berlebihan). Cukup tambah isHd: true.
// HD Image await sock.sendMessage(jid, { image: { url: './foto.jpg' }, caption: 'Foto HD!', isHd: true, }) // HD Video await sock.sendMessage(jid, { video: { url: './video.mp4' }, caption: 'Video HD!', isHd: true, })
isHd bikin WhatsApp nampilin badge "HD" di pesan. File yang diupload tetap original quality — yang diubah cuma cara client nampilinnya. Bekerja di WhatsApp yg support HD media (Android/Web). iOS mungkin nampilin sebagai gambar biasa.
Simpan pesan yang udah diatur disappearing biar gak ilang. Berguna buat nyimpen pesan penting di chat dengan disappearing aktif.
// Keep message (cegah ilang) await sock.sendMessage(jid, { keepInChat: messageKey, type: 1, // KEEP_FOR_ALL }) // Undo keep (balikin ke disappearing) await sock.sendMessage(jid, { keepInChat: messageKey, type: 2, // UNDO_KEEP_FOR_ALL })
Kirim pesan produk dari katalog bisnis.
| Field | Keterangan |
|---|---|
product.productImage | Gambar produk (Buffer/URL) |
product.title | Judul produk |
product.description | Deskripsi produk |
product.currencyCode | Kode mata uang (IDR) |
product.priceAmount | Harga dalam sen (10000 = Rp100) |
product.retailerId | SKU produk |
businessOwnerJid | JID pemilik bisnis |
body | Pesan tambahan |
footer | Footer |
await sock.sendMessage(jid, { product: { productImage: { url: './produk.jpg' }, title: 'Kaos Polos', description: 'Kaos katun nyaman dipake', currencyCode: 'IDR', priceAmount: 5000000, retailerId: 'K001', }, businessOwnerJid: '628xxx@s.whatsapp.net', body: 'Lihat produk ini!', footer: 'Toko Kita', })
Kirim undangan grup.
await sock.sendMessage(jid, { groupInvite: { inviteCode: 'abc123', inviteExpiration: 86400, text: 'Gabung grup kita!', jid: '123456@g.us', subject: 'Grup Seru', } })
Bagikan nomor HP sendiri ke chat.
await sock.sendMessage(jid, { sharePhoneNumber: true })
Batasi forward/sharing pesan.
await sock.sendMessage(jid, { limitSharing: true })
Kirim status/story kaya yg muncul di atas chat WA. Bedanya dari chat biasa: tujuannya status@broadcast & lu tentuin siapa aja yg bisa liat lewat statusJidList.
await sock.sendMessage('status@broadcast', { text: 'Halo dunia! 🌍', }, { statusJidList: [ '628xxx@s.whatsapp.net', '628yyy@s.whatsapp.net', ], backgroundColor: '#4a9eff', font: 1, })
await sock.sendMessage('status@broadcast', { image: { url: './status.jpg' }, caption: 'Coba fitur baru!', }, { statusJidList: ['628xxx@s.whatsapp.net'], })
| Param | Tipe | Keterangan |
|---|---|---|
| statusJidList | string[] | Daftar JID yg bisa liat status. Kalo kosong, semua kontak bisa liat |
| backgroundColor | string | Warna background (hex). Contoh: '#4a9eff' |
| font | number | Jenis font. 0-3 (tersedia di WA) |
status@broadcast beda dari broadcast biasa. statusJidList opsional — kalo ga dikasih, WA otomatis nentuin viewer berdasarkan privacy setting akun. Tapi kalo dikasih, status cuma bisa diliat sama JID di daftar itu.
Kalo butuh kontrol lebih (misal: nambah nodes kustom, atur participant manual), pake relayMessage langsung:
| Param | Tipe | Keterangan |
|---|---|---|
jid | string | Tujuan |
message | proto.IMessage | Protobuf message yang udah di-generate |
options | MessageRelayOptions | Config relai tambahan |
import { generateWAMessage, proto } from '@mataram/wa' const msg = await generateWAMessage(jid, { text: 'Manual' }, { userJid: sock.user?.id }) await sock.relayMessage(jid, msg.message!, { messageId: msg.key.id })