Fitur Lanjutan

Business tools, communities, labels, Signal, USync, download media, proxy, dan utility functions.

Business Profile

Fitur buat akun WhatsApp Business.

getBusinessProfile

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)

updateBussinesProfile

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' },
    ],
  },
})

updateCoverPhoto & removeCoverPhoto

const photoId = await sock.updateCoverPhoto({ url: './cover.jpg' })
await sock.removeCoverPhoto(photoId)

Katalog & Produk

getCatalog

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

getCollections

const collections = await sock.getCollections('628xxx@s.whatsapp.net', 20)

productCreate / productUpdate / productDelete

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

Communities

Fitur komunitas — grup besar yang punya sub-grup.

Membuat & Mengelola Community

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

Partisipan & Invite Community

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

Settings Community

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

Labels

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

Signal (Enkripsi)

Akses langsung ke Signal Repository untuk debug atau operasi manual.

decryptMessage

Dekripsi pesan pribadi (1-on-1).

const decrypted = await sock.signalRepository.decryptMessage({
  jid: '628xxx@s.whatsapp.net',
  type: 'pkmsg',  // atau 'msg'
  ciphertext: buffer,
})

decryptGroupMessage

Dekripsi pesan grup (sender key).

const decrypted = await sock.signalRepository.decryptGroupMessage({
  group: '123@g.us',
  data: cipherBuffer,
  meId: sock.user?.id,
})

encryptMessage / encryptGroupMessage

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

Signal Events

Library otomatis handle session management, pre-key upload, dll. Tapi lu bisa dengerin event creds.update buat liat perubahan key.


USync

Protokol query WhatsApp buat fetch data user (device, status, dll).

executeUSyncQuery

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 }

USyncUser

MethodKeterangan
withId(jid)Cari user berdasarkan JID
withPhone(phone)Cari user berdasarkan nomor (format: +628xxx)

USyncQuery Protocols

ProtocolMethodKeterangan
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

onWhatsApp

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

Call Links

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

Contact Management

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

Quick Reply

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

Media Download

Download media dari pesan (gambar, video, audio, document).

downloadContentFromMessage

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'

downloadMediaMessage

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

Proxy

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.


Utilities

fetchLatestVersion

Ambil versi WA Web terbaru.

const [version, isNew] = await fetchLatestVersion()
console.log('Versi:', version.join('.'))

BufferJSON

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)

getContentType

Ambil tipe konten dari message.

import { getContentType } from '@mataram/wa'

const type = getContentType(msg.message)
// 'conversation' | 'imageMessage' | 'videoMessage' | 'extendedTextMessage' | 'pollCreationMessage' | ...

getDevice

Deteksi device dari mana pesan dikirim.

import { getDevice } from '@mataram/wa'

const device = getDevice(msg.key.id)
// 'ios' | 'android' | 'web' | 'unknown'

makeCacheableSignalKeyStore

Bungkus key store dengan cache biar ga每次都 baca dari disk.

import { makeCacheableSignalKeyStore } from '@mataram/wa'

const cachedKeys = makeCacheableSignalKeyStore(authState.keys)

delay

Helper sleep sederhana.

import { delay } from '@mataram/wa'

await delay(3000)  // tunggu 3 detik

fetchStatus

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

fetchDisappearingDuration

const result = await sock.fetchDisappearingDuration('628xxx@s.whatsapp.net')
console.log(result)

presenceSubscribe

Subscribe ke presence update user tertentu.

await sock.presenceSubscribe('628xxx@s.whatsapp.net')

getBotListV2

Ambil daftar bot yang tersedia di WA.

const bots = await sock.getBotListV2()
console.log(bots)

updateMemberLabel

Update label anggota grup.

await sock.updateMemberLabel('123@g.us', 'member')

updateMediaMessage

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

Logout dari WhatsApp secara eksplisit.

await sock.logout()

Account State & Pembatasan

WA punya sistem anti-spam yang bisa nge-restrict akun bot. Ini cara ngecek status akun.

Reachout Timelock

Fitur buat ngecek apakah akun lu kena pembatasan sementara dari WhatsApp. Biasanya gara-gara kirim pesan ke terlalu banyak nomor baru dalam waktu singkat.

fetchAccountReachoutTimelock

ReturnTipeKeterangan
isActivebooleanApakah akun lagi kena restrict
timeEnforcementEndsDate | undefinedKapan restrict selesai (kalo ada)
enforcementTypeReachoutTimelockEnforcementTypeJenis pembatasan
Nilai enforcementTypeArti
DEFAULTNormal, ga kena restrict
WEB_COMPANION_ONLYCuma perangkat companion/web yang diblokir, HP utama aman
RESTRICT_ALL_COMPANIONSSemua perangkat diblokir kirim pesan ke kontak baru
BIZ_QUALITYKualitas 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.

Message Capping

WA juga punya sistem kuota chat baru per siklus. Bedanya sama reachout timelock: ini batas jumlah, bukan blokir total.

fetchNewChatMessageCap

FieldTipeKeterangan
capping_statusstringNONE (aman) / FIRST_WARNING / SECOND_WARNING / CAPPED
total_quotanumberTotal kuota chat baru dalam siklus ini
used_quotanumberKuota yang udah dipake
cycle_start_timestampstringUnix timestamp mulai siklus
cycle_end_timestampstringUnix timestamp siklus berakhir
ote_statusstringNOT_ELIGIBLE / ELIGIBLE / ACTIVE_IN_CURRENT_CYCLE / EXHAUSTED
mv_statusstringNOT_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)

Rich Response

Kirim pesan dengan format markdown kaya Meta AI — tabel, code block, syntax highlighting, suggested prompts.

sendMessage dengan rich: true

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
})
MarkdownHasil
# HeadingHeading besar
**bold**Bold
*italic*Italic
~~strikethrough~~Coret
`code`Inline code
```js ... ```Code block + syntax highlighting (js, ts, python, go, java, rust)
| col1 | col2 |Tabel
![alt](url)Gambar
> quoteBlockquote
:::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.

Message Retry & Error Handling

@mataram/wa punya sistem retry otomatis yang jauh lebih canggih dari Baileys original.

FiturBaileys Original@mataram/wa
Retry cacheGa adaLRU cache 512 entry, TTL 5 menit
Retry counterBasic counterPer-message, max configurable
Auto session recreateManualOtomatis (bisa dimatiin)
Base key collisionGa dicekDetect + recreate session
MAC errorGa dihandleAuto recreate session
Error 463 (restricted)Ga dihandleAuto issue tctoken + recovery
Error 479 (smax-invalid)Ga dihandleLogged, skip retry
Retry >24hMasih retrySkip (expired)
Phone requestGa adaDelayed 3s, timeout 8s

Config retry

OptionDefaultKeterangan
maxMsgRetryCount5Maks percobaan ulang per pesan
enableRecentMessageCachetrueCache pesan terbaru buat resend pas retry
enableAutoSessionRecreationtrueAuto bikin ulang session Signal kalo corrupt
getMessage() => undefinedCallback buat ambil pesan dari DB lu

Signal Retry Error Codes

KodeNamaPenyebab
0UnknownErrorError ga dikenal
1NoSessionBelum ada session Signal
2InvalidKeyKunci ga valid
3InvalidKeyIdID kunci salah
4InvalidMessagePesan korup
5InvalidSignatureTanda tangan salah
6FutureMessagePesan dari masa depan (counter ga sinkron)
7BadMacMAC check gagal — recreate session otomatis
8InvalidSessionSession ga valid — recreate otomatis
9InvalidMsgKeyKunci pesan salah
10BadBroadcastEphemeralSettingSetting ephemeral broadcast salah
11UnknownCompanionNoPrekeyCompanion ga punya pre-key
12AdvFailureAdvanced failure
13StatusRevokeDelayDelay revoke status
← Kembali Lanjut: Error Codes →