Kirim Pesan

Semua jenis pesan dikirim lewat satu fungsi utama: sendMessage(jid, content, options). Plus relai manual pake relayMessage buat kasus advanced.

sendMessage — Fungsi Utama

Parameter

ParameterTipeKeterangan
jidstringTujuan JID. Contoh: 628xxx@s.whatsapp.net, xxx@g.us
contentAnyMessageContentObject yang isinya tergantung tipe pesan. Lihat tabel tiap tipe di bawah
optionsMiscMessageGenerationOptionsKonfigurasi tambahan: quoted, ephemeral, dll

Options (Parameter ke-3)

OptionTipeKeterangan
quotedWAMessagePesan yang mau di-reply. Isi dengan object WAMessage asli dari event
ephemeralExpirationnumber | stringBuat pesan disappearing. Nilai: 86400 (24h), 604800 (7d), 7776000 (90d)
timestampDateOverride timestamp pesan
mediaUploadTimeoutMsnumberTimeout upload media ke server WA
statusJidListstring[]Daftar JID buat broadcast status
backgroundColorstringWarna background status
fontnumberFont status
broadcastbooleanBroadcast message
useCachedGroupMetadatabooleanGunakan cache metadata grup (default true)
messageIdstringOverride ID pesan dengan kustom

Return Value

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.


Text

Tipe paling dasar. Field text berisi string yang mau dikirim. mentions buat nyebut orang, mentionAll buat nyebut semua.

Field Content

FieldTipeWajibKeterangan
textstringYaIsi pesan teks
mentionsstring[]TidakDaftar JID yang di-mention
mentionAllbooleanTidakMention semua peserta grup
contextInfoproto.IContextInfoTidakContext info kustom
linkPreviewWAUrlInfo | nullTidakOverride 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.

Gambar

Field image nerima Buffer, URL (via { url: string }), atau Readable stream.

Field Content

FieldTipeWajibKeterangan
imageWAMediaUploadYaBuffer / { url: string } / Readable stream
captionstringTidakKeterangan gambar
mentionsstring[]TidakMention di caption
jpegThumbnailstring / BufferTidakThumbnail custom (string Base64 atau Buffer)
width / heightnumberTidakDimensi gambar
contextInfoproto.IContextInfoTidakContext info
viewOncebooleanTidakView once
albumParentKeyWAMessageKeyTidakKey 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 })

Video

ptv: true = video note (lingkaran). gifPlayback: true = GIF animasi.

Field Content

FieldKeterangan
videoBuffer / URL / stream
captionKeterangan
gifPlaybacktrue = kirim sebagai GIF
ptvtrue = video note (lingkaran)
jpegThumbnailThumbnail custom
width / heightDimensi
mentionsMention 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 })

Audio / Voice Note

ptt: true = voice note. seconds bisa dikasih tau durasinya (opsional).

Field Content

FieldKeterangan
audioBuffer / URL / stream
ptttrue = voice note
secondsDurasi audio dalam detik
mimetypeMisal: 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' })

Document

Kirim file apa aja. mimetype harus sesuai.

Field Content

FieldKeterangan
documentBuffer / URL / stream
fileNameNama file yang tampil
mimetypeWajib. Contoh: application/pdf
captionKeterangan
contextInfoContext info
await sock.sendMessage(jid, {
  document: { url: './file.pdf' },
  fileName: 'dokumen.pdf',
  mimetype: 'application/pdf',
  caption: 'Ini file PDF',
})

Sticker

Kirim sticker. isAnimated kalo sticker animated (webp dengan frame banyak).

Field Content

FieldKeterangan
stickerBuffer / URL (webp)
isAnimatedtrue kalo sticker animasi
width / heightDimensi opsional
await sock.sendMessage(jid, { sticker: fs.readFileSync('./sticker.webp') })
await sock.sendMessage(jid, { sticker: { url: './animasi.webp' }, isAnimated: true })

Poll

Buat polling dengan pilihan. selectableCount: 1 = pilih satu, >1 = pilih banyak. values: array pilihan.

PollMessageOptions

FieldTipeKeterangan
namestringPertanyaan polling
valuesstring[]Pilihan yang tersedia
selectableCountnumber1 =单选, >1 = multi-select
messageSecretUint8Array32 byte secret buat enkripsi vote
toAnnouncementGroupbooleanUntuk 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,
  }
})

Location

Kirim lokasi peta. Pake object proto.Message.ILocationMessage.

Field Content

FieldKeterangan
degreesLatitudeGaris lintang (-6.2)
degreesLongitudeGaris bujur (106.8)
nameNama lokasi (opsional)
addressAlamat (opsional)
commentKomentar (opsional)
await sock.sendMessage(jid, {
  location: { degreesLatitude: -6.2, degreesLongitude: 106.8, name: 'Jakarta' }
})

Contact (vCard)

Kirim kontak berupa vCard.

Field Content

FieldKeterangan
contacts.displayNameNama yang tampil
contacts.contactsArray { 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 }]
  }
})

Reaction

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 } })

Edit Pesan

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

Hapus pesan. delete diisi MessageKey.

Catatan Penting

// 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 }
})

Forward

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 })

View Once

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 })

Disappearing Messages

Dua mode: set disappearing buat seluruh chat, atau kirim 1 pesan yang ilang.

Mode 1: Set untuk seluruh chat (grup doang)

Pake field disappearingMessagesInChat. Tipe boolean | number:

Ini 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 })

Mode 2: Satu pesan doang

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 })

Album (Multi Media)

Kirim beberapa media yang tergabung jadi satu album. Gambar/video pertama jadi cover/sampul.

Cara Kerja

  1. Kirim media pertama pake album: { expectedImageCount, expectedVideoCount } — ini jadi parent album
  2. Simpen albumParentKey dari hasil kiriman pertama (= sent.key)
  3. Kirim media berikutnya pake 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 })

Event (Kalender)

Buat undangan event dengan tanggal, deskripsi, lokasi, dan tombol RSVP otomatis dari WA.

EventMessageOptions

FieldTipeKeterangan
namestringNama event
descriptionstringDeskripsi event
startDateDateWaktu mulai
endDateDateWaktu selesai (opsional)
locationWALocationMessageLokasi (latitude, longitude, name)
call'audio' | 'video'Tambah tombol call link
isCancelledbooleanTandai event dibatalkan
isScheduleCallbooleanJadwalkan panggilan
extraGuestsAllowedbooleanIzinkan 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',
  }
})

Pin Message

Sematkan pesan di chat. Butuh MessageKey pesan target.

Field Content

FieldTipeKeterangan
pinWAMessageKeyKey pesan yang mau di-pin
typeproto.PinInChat.Type1 = PINNED, 2 = UNPINNED
time86400 | 604800 | 2592000Durasi 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,
})

HD Media

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.

Keep In Chat

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
})

Product

Kirim pesan produk dari katalog bisnis.

Field Content

FieldKeterangan
product.productImageGambar produk (Buffer/URL)
product.titleJudul produk
product.descriptionDeskripsi produk
product.currencyCodeKode mata uang (IDR)
product.priceAmountHarga dalam sen (10000 = Rp100)
product.retailerIdSKU produk
businessOwnerJidJID pemilik bisnis
bodyPesan tambahan
footerFooter
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',
})

Group Invite

Kirim undangan grup.

await sock.sendMessage(jid, {
  groupInvite: {
    inviteCode: 'abc123',
    inviteExpiration: 86400,
    text: 'Gabung grup kita!',
    jid: '123456@g.us',
    subject: 'Grup Seru',
  }
})

Share Phone Number

Bagikan nomor HP sendiri ke chat.

await sock.sendMessage(jid, { sharePhoneNumber: true })

Limit Sharing

Batasi forward/sharing pesan.

await sock.sendMessage(jid, { limitSharing: true })

Status / Story Broadcast

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.

Text Status

await sock.sendMessage('status@broadcast', {
  text: 'Halo dunia! 🌍',
}, {
  statusJidList: [
    '628xxx@s.whatsapp.net',
    '628yyy@s.whatsapp.net',
  ],
  backgroundColor: '#4a9eff',
  font: 1,
})

Image Status

await sock.sendMessage('status@broadcast', {
  image: { url: './status.jpg' },
  caption: 'Coba fitur baru!',
}, {
  statusJidList: ['628xxx@s.whatsapp.net'],
})

Parameter Opsional

ParamTipeKeterangan
statusJidListstring[]Daftar JID yg bisa liat status. Kalo kosong, semua kontak bisa liat
backgroundColorstringWarna background (hex). Contoh: '#4a9eff'
fontnumberJenis 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.


RelayMessage — Kirim Pesan Manual

Kalo butuh kontrol lebih (misal: nambah nodes kustom, atur participant manual), pake relayMessage langsung:

Parameter relayMessage

ParamTipeKeterangan
jidstringTujuan
messageproto.IMessageProtobuf message yang udah di-generate
optionsMessageRelayOptionsConfig 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 })
← Kembali Lanjut: Tombol →