zapo connects as a companion device — exactly like linking WhatsApp Web or Desktop. The first connection pairs the device; after that, credentials stored in your store are reused automatically.
The pairing flow
Pairing is driven entirely through events emitted duringconnect():
Once
auth_paired fires, the credentials are written to the store and reused on every subsequent connect() — you will not see auth_qr again unless the session is unlinked or cleared.
Paired. Credentials now live in your store — restart the process and
connect() resumes the session with no new QR.Pairing with a QR code
This is the default flow. Render theqr string as a QR image and scan it from WhatsApp → Linked devices → Link a device.
auth_qr fires again with a fresh value each time, so always render the latest one.
Pairing with a code
Prefer entering an 8-character code on the phone instead of scanning? Request one throughclient.auth after the connection is established. Listen for auth_pairing_required, then request the code for the target phone number (digits only, with country code):
requestPairingCode(phoneNumber, shouldShowPushNotification?, customCode?) requires an active connection and returns the code as a string. On the phone, open Linked devices → Link with phone number instead.Passkey-gated linking (Shortcake)
For some accounts, WhatsApp’s server refuses the plain QR / pairing-code flow and demands a WebAuthn passkey assertion from the account owner’s authenticator before a companion can link. The wire protocol behind this is documented in depth in WhatsApp passkey & Shortcake linking; this section covers how to opt in on the client side. The trigger is server-driven. When it fires,zapo emits auth_passkey_required as a heads-up (hasSigner tells you whether the handshake will actually proceed) and then runs the Shortcake handshake internally — provided you configured a signer.
The signer
SetsignPasskeyAssertion on WaClientOptions. zapo hands you the server’s raw WebAuthn request options, and you hand back the assertion + credential id:
zapo never touches passkey material directly.
auth_paired still fires on success — the Shortcake handshake is just an additional step slotted into the normal pairing flow (usually right after pair-device or a pairing-code companion_finish). No new “paired” event is introduced.
Credentials
After pairing, the current credentials are available synchronously:Logging out
logout() unpairs the companion device server-side (it removes this device from the account’s linked devices). It requires an authenticated session:
logoutStoreClear option — see Configuration.
Disconnect vs. logout
Use
disconnect() for a graceful shutdown you intend to resume; use logout() to permanently unlink.
Next
Stores
Where credentials and Signal state are persisted.
Reconnection
Handle
connection: close and reconnect.