Business tools, communities, labels, Signal, USync, download media, proxy, dan utility functions.
Fitur buat akun WhatsApp Business.
Ambil profil bisnis user lain.
const profile = await sock.getBusinessProfile('628xxx@s.whatsapp.net') console.log(profile.description, profile.email, profile.website, profile.address) console.log(profile.category, profile.business_hours)
Update profil bisnis sendiri.
await sock.updateBussinesProfile({ address: 'Jl. Merdeka No. 1', email: 'toko@example.com', description: 'Toko online terpercaya', websites: ['https://example.com'], hours: { timezone: 'Asia/Jakarta', days: [ { day: 'mon', mode: 'specific_hours', openTimeInMinutes: 480, closeTimeInMinutes: 1020 }, { day: 'tue', mode: 'open_24h' }, { day: 'sun', mode: 'closed' }, ], }, })
const photoId = await sock.updateCoverPhoto({ url: './cover.jpg' }) await sock.removeCoverPhoto(photoId)
Ambil daftar produk dari katalog.
const catalog = await sock.getCatalog({ jid: '628xxx@s.whatsapp.net', limit: 20 }) console.log(catalog.products) console.log(catalog.cursor) // buat pagination const nextPage = await sock.getCatalog({ jid, cursor: catalog.cursor })
const collections = await sock.getCollections('628xxx@s.whatsapp.net', 20)
// Buat produk baru const product = await sock.productCreate({ name: 'Kaos Polos', description: 'Kaos katun 100%', images: [{ url: 'https://example.com/kaos.jpg' }], currency: 'IDR', price: 5000000, // Rp50.000 (harga dalam sen x 100) originCountryCode: 'ID', isHidden: false, }) // Update produk await sock.productUpdate(productId, { name: 'Kaos Polos Premium', price: 7500000, }) // Hapus produk const result = await sock.productDelete([productId]) console.log('Terhapus:', result.deleted) // Detail order const order = await sock.getOrderDetails(orderId, tokenBase64)
Fitur komunitas — grup besar yang punya sub-grup.
// Buat community const community = await sock.communityCreate('Nama Komunitas', 'Deskripsi komunitas') // Buat grup di dalam community const group = await sock.communityCreateGroup( 'Sub Grup', ['628xxx@s.whatsapp.net'], '123456@g.us' // JID community parent ) // Dapetin metadata community const meta = await sock.communityMetadata('123456@g.us') // Link / unlink grup ke community await sock.communityLinkGroup('subgroup@g.us', 'community@g.us') await sock.communityUnlinkGroup('subgroup@g.us', 'community@g.us') // Fetch semua grup yang ter-link const linked = await sock.communityFetchLinkedGroups('community@g.us') console.log(linked.linkedGroups) // Keluar dari community await sock.communityLeave('123456@g.us') // Update nama & deskripsi await sock.communityUpdateSubject('123456@g.us', 'Nama Baru') await sock.communityUpdateDescription('123456@g.us', 'Deskripsi baru')
// Tambah / keluarkan anggota await sock.communityParticipantsUpdate('123@g.us', ['628xxx@s.whatsapp.net'], 'add') await sock.communityParticipantsUpdate('123@g.us', ['628xxx@s.whatsapp.net'], 'remove') await sock.communityParticipantsUpdate('123@g.us', ['628xxx@s.whatsapp.net'], 'promote') // Invite code const inviteCode = await sock.communityInviteCode('123@g.us') await sock.communityRevokeInvite('123@g.us') const jid = await sock.communityAcceptInvite('invitecode') const info = await sock.communityGetInviteInfo('invitecode') // Daftar minta gabung const requests = await sock.communityRequestParticipantsList('123@g.us') await sock.communityRequestParticipantsUpdate('123@g.us', ['628xxx@s.whatsapp.net'], 'approve')
await sock.communitySettingUpdate('123@g.us', 'announcement') await sock.communityToggleEphemeral('123@g.us', 86400) await sock.communityJoinApprovalMode('123@g.us', 'on') await sock.communityMemberAddMode('123@g.us', 'admin_add') // Fetch semua community const all = await sock.communityFetchAllParticipating()
Fitur label — bisa dipake di chat dan pesan.
// Tambah label await sock.addLabel('123@g.us', { name: 'Penting', labelColor: 1 }) // Label ke chat await sock.addChatLabel('628xxx@s.whatsapp.net', 'label_id') await sock.removeChatLabel('628xxx@s.whatsapp.net', 'label_id') // Label ke pesan spesifik await sock.addMessageLabel('628xxx@s.whatsapp.net', 'message_id', 'label_id') await sock.removeMessageLabel('628xxx@s.whatsapp.net', 'message_id', 'label_id')
Akses langsung ke Signal Repository untuk debug atau operasi manual.
Dekripsi pesan pribadi (1-on-1).
const decrypted = await sock.signalRepository.decryptMessage({ jid: '628xxx@s.whatsapp.net', type: 'pkmsg', // atau 'msg' ciphertext: buffer, })
Dekripsi pesan grup (sender key).
const decrypted = await sock.signalRepository.decryptGroupMessage({ group: '123@g.us', data: cipherBuffer, meId: sock.user?.id, })
// Enkripsi 1-on-1 const { type, ciphertext } = await sock.signalRepository.encryptMessage({ jid: '628xxx@s.whatsapp.net', data: plaintextBuffer, }) // Enkripsi grup const result = await sock.signalRepository.encryptGroupMessage({ group: '123@g.us', data: plaintextBuffer, meId: sock.user?.id, })
Library otomatis handle session management, pre-key upload, dll. Tapi lu bisa dengerin event creds.update buat liat perubahan key.
Protokol query WhatsApp buat fetch data user (device, status, dll).
import { USyncQuery, USyncUser } from '@mataram/wa' const query = new USyncQuery() .withContext('business') .withDeviceProtocol() .withContactProtocol() .withLIDProtocol() .withStatusProtocol() .withDisappearingModeProtocol() .withUser(new USyncUser().withId('628xxx@s.whatsapp.net')) .withUser(new USyncUser().withPhone('+6281234567890')) const result = await sock.executeUSyncQuery(query) console.log(result.list) // Setiap item: { id, device, contact, lid, status, disappearingMode }
| Method | Keterangan |
|---|---|
withId(jid) | Cari user berdasarkan JID |
withPhone(phone) | Cari user berdasarkan nomor (format: +628xxx) |
| Protocol | Method | Keterangan |
|---|---|---|
| Device | .withDeviceProtocol() | Dapetin daftar device user |
| Contact | .withContactProtocol() | Cek apakah nomor terdaftar di WA |
| LID | .withLIDProtocol() | Dapetin mapping LID ke PN |
| Status | .withStatusProtocol() | Dapetin status/about user |
| Disappearing Mode | .withDisappearingModeProtocol() | Dapetin setelan disappearing mode |
Cek apakah nomor terdaftar di WhatsApp. Lebih simple daripada USync manual.
const results = await sock.onWhatsApp('6281234567890', '6289876543210') for (const { jid, exists } of results) { console.log(jid, exists ? 'Terdaftar' : 'Tidak terdaftar') }
Buat link panggilan audio/video.
// Buat link panggilan video const token = await sock.createCallLink('video') console.log('Link panggilan:', `https://call.whatsapp.com/video/${token}`) // Dengan jadwal const token2 = await sock.createCallLink('audio', { startTime: new Date('2025-07-01T10:00:00').getTime() })
// Tambah / edit kontak await sock.addOrEditContact('628xxx@s.whatsapp.net', { firstName: 'John', fullName: 'John Doe', phoneNumber: [{ phone: '+6281234567890' }], }) // Hapus kontak await sock.removeContact('628xxx@s.whatsapp.net') // Block / unblock user await sock.updateBlockStatus('628xxx@s.whatsapp.net', 'block') await sock.updateBlockStatus('628xxx@s.whatsapp.net', 'unblock') // Fetch blocklist const blocklist = await sock.fetchBlocklist()
// Tambah / edit quick reply await sock.addOrEditQuickReply({ name: '.help', shortcut: '.help', message: 'Daftar perintah:\n!menu - Menu\n!about - Tentang', }) // Hapus quick reply await sock.removeQuickReply(timestamp)
Download media dari pesan (gambar, video, audio, document).
Low-level function. Download & decrypt stream langsung dari server WA.
import { downloadContentFromMessage, toBuffer } from '@mataram/wa' const downloadMedia = async (msg) => { const content = msg.message?.imageMessage // atau videoMessage, audioMessage, documentMessage if (!content) return const stream = await downloadContentFromMessage(content, 'image') const buffer = await toBuffer(stream) // Simpen ke file fs.writeFileSync('./download.jpg', buffer) } // Tipe media yang didukung // 'image' | 'video' | 'audio' | 'document' | 'sticker'
High-level function. Download langsung dari WAMessage object.
import { downloadMediaMessage } from '@mataram/wa' const buffer = await downloadMediaMessage(msg, 'buffer') // langsung dapet Buffer const stream = await downloadMediaMessage(msg, 'stream') // dapet Readable stream
Gunakan proxy untuk koneksi WebSocket dan fetch request.
import { SocksProxyAgent } from 'socks-proxy-agent' const agent = new SocksProxyAgent('socks5://127.0.0.1:1080') const sock = makeWASocket({ auth: state, agent, // proxy buat WebSocket fetchAgent: agent, // proxy buat upload/download media })
Proxy HTTP/HTTPS juga bisa pake HttpsProxyAgent dari https-proxy-agent.
Ambil versi WA Web terbaru.
const [version, isNew] = await fetchLatestVersion() console.log('Versi:', version.join('.'))
Serializer/deserializer JSON yang support Buffer. Dipake internal buat simpan creds.
import { BufferJSON } from '@mataram/wa' const data = { buffer: Buffer.from('hello') } const json = JSON.stringify(data, BufferJSON.replacer) const parsed = JSON.parse(json, BufferJSON.reviver)
Ambil tipe konten dari message.
import { getContentType } from '@mataram/wa' const type = getContentType(msg.message) // 'conversation' | 'imageMessage' | 'videoMessage' | 'extendedTextMessage' | 'pollCreationMessage' | ...
Deteksi device dari mana pesan dikirim.
import { getDevice } from '@mataram/wa' const device = getDevice(msg.key.id) // 'ios' | 'android' | 'web' | 'unknown'
Bungkus key store dengan cache biar ga每次都 baca dari disk.
import { makeCacheableSignalKeyStore } from '@mataram/wa' const cachedKeys = makeCacheableSignalKeyStore(authState.keys)
Helper sleep sederhana.
import { delay } from '@mataram/wa' await delay(3000) // tunggu 3 detik
const statusList = await sock.fetchStatus('628xxx@s.whatsapp.net', '628yyy@s.whatsapp.net') for (const { id, status, setAt } of statusList) { console.log(id, status, setAt) }
const result = await sock.fetchDisappearingDuration('628xxx@s.whatsapp.net') console.log(result)
Subscribe ke presence update user tertentu.
await sock.presenceSubscribe('628xxx@s.whatsapp.net')
Ambil daftar bot yang tersedia di WA.
const bots = await sock.getBotListV2() console.log(bots)
Update label anggota grup.
await sock.updateMemberLabel('123@g.us', 'member')
Minta ulang media yang gagal download (retry).
try { await sock.updateMediaMessage(msg) console.log('Media updated!') } catch (err) { console.log('Gagal update media', err) }
Logout dari WhatsApp secara eksplisit.
await sock.logout()
WA punya sistem anti-spam yang bisa nge-restrict akun bot. Ini cara ngecek status akun.
Fitur buat ngecek apakah akun lu kena pembatasan sementara dari WhatsApp. Biasanya gara-gara kirim pesan ke terlalu banyak nomor baru dalam waktu singkat.
| Return | Tipe | Keterangan |
|---|---|---|
| isActive | boolean | Apakah akun lagi kena restrict |
| timeEnforcementEnds | Date | undefined | Kapan restrict selesai (kalo ada) |
| enforcementType | ReachoutTimelockEnforcementType | Jenis pembatasan |
| Nilai enforcementType | Arti |
|---|---|
| DEFAULT | Normal, ga kena restrict |
| WEB_COMPANION_ONLY | Cuma perangkat companion/web yang diblokir, HP utama aman |
| RESTRICT_ALL_COMPANIONS | Semua perangkat diblokir kirim pesan ke kontak baru |
| BIZ_QUALITY | Kualitas bisnis rendah |
| BIZ_COMMERCE_VIOLATION_* | Pelanggaran commerce (ALKOHOL, OBAT, SENJATA, dll — 15 jenis) |
const timelock = await sock.fetchAccountReachoutTimelock() if (timelock.isActive) { console.log('Akun kena restrict:', timelock.enforcementType) console.log('Selesai:', timelock.timeEnforcementEnds) }
Restrict ini beda sama banned. Biasanya temporary (24-72 jam). Selama kena restrict, jangan kirim pesan ke nomor baru — retry cuma bikin makin parah. @mataram/wa otomatis handle error 463 (SenderReachoutTimelocked) dan fetch status ini.
WA juga punya sistem kuota chat baru per siklus. Bedanya sama reachout timelock: ini batas jumlah, bukan blokir total.
| Field | Tipe | Keterangan |
|---|---|---|
| capping_status | string | NONE (aman) / FIRST_WARNING / SECOND_WARNING / CAPPED |
| total_quota | number | Total kuota chat baru dalam siklus ini |
| used_quota | number | Kuota yang udah dipake |
| cycle_start_timestamp | string | Unix timestamp mulai siklus |
| cycle_end_timestamp | string | Unix timestamp siklus berakhir |
| ote_status | string | NOT_ELIGIBLE / ELIGIBLE / ACTIVE_IN_CURRENT_CYCLE / EXHAUSTED |
| mv_status | string | NOT_ELIGIBLE / NOT_ACTIVE / ACTIVE / ACTIVE_UPGRADE_AVAILABLE |
const cap = await sock.fetchNewChatMessageCap() console.log('Status:', cap.capping_status) console.log('Kuota:', cap.used_quota + '/' + cap.total_quota)
Kirim pesan dengan format markdown kaya Meta AI — tabel, code block, syntax highlighting, suggested prompts.
Aktifin fitur rich response tambah rich: true di object content. @mataram/wa otomatis render markdown jadi native interactive message yang WhatsApp render sebagai AI bot response.
await sock.sendMessage(jid, { text: '# Dashboard Bot\n\n| Metrik | Nilai |\n|--------|-------|\n| User | 1.234 |\n\n```js\nconsole.log("ok")\n```\n\n> Catatan: bot jalan 24 jam\n\n:::suggest\nCek Status | Restart Bot | Bantuan\n:::', rich: true })
| Markdown | Hasil |
|---|---|
# Heading | Heading besar |
**bold** | Bold |
*italic* | Italic |
~~strikethrough~~ | Coret |
`code` | Inline code |
```js ... ``` | Code block + syntax highlighting (js, ts, python, go, java, rust) |
| col1 | col2 | | Tabel |
 | Gambar |
> quote | Blockquote |
:::suggest ... ::: | Suggested prompt pills (tombol rekomendasi) |
Rich response pake botForwardedMessage — internal message type-nya Meta AI. Cuma jalan di WhatsApp version yang udah support AI bot. Kalo WhatsApp nampilin "Versi tidak mendukung", berarti klien belom support.
@mataram/wa punya sistem retry otomatis yang jauh lebih canggih dari Baileys original.
| Fitur | Baileys Original | @mataram/wa |
|---|---|---|
| Retry cache | Ga ada | LRU cache 512 entry, TTL 5 menit |
| Retry counter | Basic counter | Per-message, max configurable |
| Auto session recreate | Manual | Otomatis (bisa dimatiin) |
| Base key collision | Ga dicek | Detect + recreate session |
| MAC error | Ga dihandle | Auto recreate session |
| Error 463 (restricted) | Ga dihandle | Auto issue tctoken + recovery |
| Error 479 (smax-invalid) | Ga dihandle | Logged, skip retry |
| Retry >24h | Masih retry | Skip (expired) |
| Phone request | Ga ada | Delayed 3s, timeout 8s |
| Option | Default | Keterangan |
|---|---|---|
| maxMsgRetryCount | 5 | Maks percobaan ulang per pesan |
| enableRecentMessageCache | true | Cache pesan terbaru buat resend pas retry |
| enableAutoSessionRecreation | true | Auto bikin ulang session Signal kalo corrupt |
| getMessage | () => undefined | Callback buat ambil pesan dari DB lu |
| Kode | Nama | Penyebab |
|---|---|---|
| 0 | UnknownError | Error ga dikenal |
| 1 | NoSession | Belum ada session Signal |
| 2 | InvalidKey | Kunci ga valid |
| 3 | InvalidKeyId | ID kunci salah |
| 4 | InvalidMessage | Pesan korup |
| 5 | InvalidSignature | Tanda tangan salah |
| 6 | FutureMessage | Pesan dari masa depan (counter ga sinkron) |
| 7 | BadMac | MAC check gagal — recreate session otomatis |
| 8 | InvalidSession | Session ga valid — recreate otomatis |
| 9 | InvalidMsgKey | Kunci pesan salah |
| 10 | BadBroadcastEphemeralSetting | Setting ephemeral broadcast salah |
| 11 | UnknownCompanionNoPrekey | Companion ga punya pre-key |
| 12 | AdvFailure | Advanced failure |
| 13 | StatusRevokeDelay | Delay revoke status |