Skip to main content

Documentation Index

Fetch the complete documentation index at: https://zapo.to/llms.txt

Use this file to discover all available pages before exploring further.

You’re almost certainly running on the in-memory store, which loses credentials when the process exits. Use a durable backend (SQLite, Postgres, …) for the auth domain, and keep a stable sessionId across runs — changing it orphans the previous credentials. See Stores.
By design — zapo does not auto-reconnect. Listen for the connection event with status: 'close' and call connect() again (skip it when isLogout is true). See the reconnection pattern.
Media still uploads without @zapo-js/media-utils — but without it there’s no processor to generate thumbnails/previews, image-video dimensions, or voice-note waveforms, so it can render as a plain attachment or with no preview. For proper media, install it (npm i @zapo-js/media-utils, plus ffmpeg/ffprobe) and wire a processor through the media option. See Media.
Pass a file path (string) or a Readable stream to media, not a Bufferzapo streams the bytes through the pipeline so memory stays flat for large files. On download, prefer downloadToFile/download over downloadBytes.
The proxy.ws leg needs the ws package (the runtime’s native WebSocket can’t take an HTTP Agent). Media/link-preview legs use an undici dispatcher. See the proxy examples for SOCKS/HTTP/HTTPS and IPv4/IPv6.
Always reply to event.chatJid (the group JID), never a participant’s JID. When you have a peer’s LID, prefer the LID — it’s the privacy-preserving, forward-compatible identity. See Identities (PN vs LID).
That’s multi-device sync — your own sends come back on the message event flagged isSender: true. Filter them out if you only want inbound traffic. See Receiving messages.
Import the event type from the package root — all coordinator and event types are exported:
import type { WaIncomingMessageEvent, WaGroupCoordinator } from 'zapo-js'

client.on('message', (event: WaIncomingMessageEvent) => { /* ... */ })
const groups: WaGroupCoordinator = client.group
No. Mobile connections are stable, but zapo intentionally does not provide a registration API — registering a number is complex and requires a physical phone. You connect with already-registered credentials. See Mobile connections.
Both work. QR is the default (auth_qr event). For an 8-digit code, call client.auth.requestPairingCode(phone) after the auth_pairing_required event. See Authentication.
disconnect() closes the socket but keeps credentials so you can resume later. logout() unlinks the device server-side and clears stored state (per logoutStoreClear). See Authentication.
Some operations are gated: editBusinessProfile, cover-photo ops, and broadcast lists are business-only; email binding is mobile-only; several community/newsletter ops require an active MEX transport. The coordinator reference flags each.

Still stuck?

Architecture in depth

Understand the layers to debug at the protocol level.

Low-level API

Inspect raw stanzas with the debug events and lowlevel.
Last modified on May 27, 2026