Newsletter (Channels)
client.newsletter is the domain namespace for WhatsApp Channels — the broadcast-only
publishing surface built into WhatsApp. Every method proxies to the live socket and requires an
active connection.
import { Client } from 'zaileys'
const client = new Client({ sessionId: 'default' })
client.on('connect', async () => {
const channel = await client.newsletter.create('My Channel', {
description: 'Updates and announcements',
})
console.log('created', channel.id)
})Newsletter JIDs look like xxxxxxxxxxxxxxxxxx@newsletter — they are distinct from user
(@s.whatsapp.net), group (@g.us), and community JIDs.
NOT_CONNECTED guard. Every client.newsletter method calls requireSocket() internally.
If the client is not yet connected, the call throws ZaileysDomainError with code NOT_CONNECTED.
Always call newsletter methods inside a 'connect' handler or after await client.connect().
See Error Handling.
Methods at a glance
| Method | Signature | Returns | Description |
|---|---|---|---|
create | create(name, opts?) | Promise<NewsletterMetadata> | Create a new channel. |
follow | follow(jid) | Promise<void> | Follow a channel. |
unfollow | unfollow(jid) | Promise<void> | Unfollow a channel. |
metadata | metadata(jid) | Promise<NewsletterMetadata> | Fetch channel metadata. |
updateName | updateName(jid, name) | Promise<void> | Rename the channel. |
updateDescription | updateDescription(jid, description) | Promise<void> | Update the channel description. |
updatePicture | updatePicture(jid, picture) | Promise<void> | Update the channel picture. |
mute | mute(jid) | Promise<void> | Mute channel notifications. |
unmute | unmute(jid) | Promise<void> | Unmute channel notifications. |
delete | delete(jid) | Promise<void> | Permanently delete the channel. |
Ban safety — operationGuard is ON by default. Creating a channel and follow/unfollow
operations are spaced by the built-in operationGuard to avoid the rapid-fire pattern WhatsApp
flags as automated abuse:
| Category | Default interval |
|---|---|
newsletter.create | 120 s |
newsletter.follow | 2 s |
newsletter.update | 3 s |
Calls queue behind each other per category and automatically wait until the interval has
elapsed. You can tune or disable this via the operationGuard option when constructing the
client. See Configuration and Troubleshooting.
create
create(
name: string,
opts?: { description?: string; picture?: Buffer },
): Promise<NewsletterMetadata>Creates a new WhatsApp Channel with the given display name. Optionally sets a description and a
cover picture in the same call. Returns NewsletterMetadata with at minimum the channel’s id
(a @newsletter JID) that you will use for subsequent calls.
When picture is provided, create first creates the channel and then uploads the picture as a
second step — both steps run inside the newsletter.create guard slot.
| Parameter | Type | Required | Description |
|---|---|---|---|
name | string | yes | Display name for the channel. |
opts.description | string | no | Short channel description shown on the info screen. |
opts.picture | Buffer | no | Channel cover image as a Buffer. |
import { readFileSync } from 'node:fs'
import { Client } from 'zaileys'
const client = new Client()
client.on('connect', async () => {
const picture = readFileSync('./channel-cover.jpg')
const channel = await client.newsletter.create('zaileys updates', {
description: 'Release notes, tips, and announcements',
picture,
})
console.log('Channel JID:', channel.id)
})follow
follow(jid: string): Promise<void>Follows the channel identified by jid. Subject to the newsletter.follow guard (2 s between
calls).
| Parameter | Type | Description |
|---|---|---|
jid | string | The @newsletter JID of the channel to follow. |
await client.newsletter.follow('xxxxxxxxxxxxxxxxxx@newsletter')unfollow
unfollow(jid: string): Promise<void>Unfollows the channel identified by jid. Shares the same newsletter.follow guard slot as
follow (2 s spacing between any follow/unfollow operations).
| Parameter | Type | Description |
|---|---|---|
jid | string | The @newsletter JID of the channel to unfollow. |
await client.newsletter.unfollow('xxxxxxxxxxxxxxxxxx@newsletter')metadata
metadata(jid: string): Promise<NewsletterMetadata>Fetches the metadata for the given channel. Throws ZaileysDomainError with code
NEWSLETTER_NOT_FOUND if the channel does not exist or is not accessible.
This method does not go through the operationGuard — it is a read-only lookup with no throttling.
| Parameter | Type | Description |
|---|---|---|
jid | string | The @newsletter JID to look up. |
import { ZaileysDomainError } from 'zaileys'
try {
const info = await client.newsletter.metadata('xxxxxxxxxxxxxxxxxx@newsletter')
console.log('Channel name:', info.name)
console.log('Subscribers:', info.subscriberCount)
} catch (err) {
if (err instanceof ZaileysDomainError && err.code === 'NEWSLETTER_NOT_FOUND') {
console.error('Channel not found or inaccessible.')
}
}updateName
updateName(jid: string, name: string): Promise<void>Renames the channel. You must be the channel owner.
| Parameter | Type | Description |
|---|---|---|
jid | string | The @newsletter JID of your channel. |
name | string | New display name. |
await client.newsletter.updateName('xxxxxxxxxxxxxxxxxx@newsletter', 'zaileys — official')updateDescription
updateDescription(jid: string, description: string): Promise<void>Replaces the channel description. You must be the channel owner.
| Parameter | Type | Description |
|---|---|---|
jid | string | The @newsletter JID of your channel. |
description | string | New description text. |
await client.newsletter.updateDescription(
'xxxxxxxxxxxxxxxxxx@newsletter',
'Now including weekly deep-dives and changelogs.',
)updatePicture
updatePicture(jid: string, picture: Buffer): Promise<void>Replaces the channel cover picture. picture must be a Buffer containing the image data. You
must be the channel owner.
| Parameter | Type | Description |
|---|---|---|
jid | string | The @newsletter JID of your channel. |
picture | Buffer | New cover image as a Buffer. |
import { readFileSync } from 'node:fs'
const newCover = readFileSync('./new-cover.png')
await client.newsletter.updatePicture('xxxxxxxxxxxxxxxxxx@newsletter', newCover)mute
mute(jid: string): Promise<void>Mutes push notifications from the channel without unfollowing it.
| Parameter | Type | Description |
|---|---|---|
jid | string | The @newsletter JID to mute. |
await client.newsletter.mute('xxxxxxxxxxxxxxxxxx@newsletter')unmute
unmute(jid: string): Promise<void>Re-enables push notifications for a previously muted channel.
| Parameter | Type | Description |
|---|---|---|
jid | string | The @newsletter JID to unmute. |
await client.newsletter.unmute('xxxxxxxxxxxxxxxxxx@newsletter')delete
delete(jid: string): Promise<void>Permanently deletes the channel. This action is irreversible. You must be the channel owner.
| Parameter | Type | Description |
|---|---|---|
jid | string | The @newsletter JID of the channel to delete. |
await client.newsletter.delete('xxxxxxxxxxxxxxxxxx@newsletter')delete is permanent. There is no confirmation step — the channel and all its published content
are removed immediately. Make sure you are passing the correct JID before calling this.
Error handling
All client.newsletter methods throw ZaileysDomainError on failure. Import it from zaileys
to handle errors precisely.
import { Client, ZaileysDomainError } from 'zaileys'
try {
const info = await client.newsletter.metadata('xxxxxxxxxxxxxxxxxx@newsletter')
console.log(info.name)
} catch (err) {
if (err instanceof ZaileysDomainError) {
switch (err.code) {
case 'NOT_CONNECTED':
console.error('Client is not connected. Wait for the connect event.')
break
case 'NEWSLETTER_NOT_FOUND':
console.error('Channel not found or no longer exists.')
break
default:
throw err
}
}
}| Code | Raised by | When |
|---|---|---|
NOT_CONNECTED | every method | Client socket is not open. |
NEWSLETTER_NOT_FOUND | metadata | The requested channel does not exist or is inaccessible. |
See Error Handling for the full error taxonomy.
Complete example
import { readFileSync } from 'node:fs'
import { Client, ZaileysDomainError } from 'zaileys'
const client = new Client({ sessionId: 'default' })
client.on('connect', async () => {
// Create a channel with a picture
const picture = readFileSync('./cover.jpg')
const channel = await client.newsletter.create('My Project Updates', {
description: 'Changelogs and feature announcements',
picture,
})
console.log('Created:', channel.id)
// Follow another channel
await client.newsletter.follow('xxxxxxxxxxxxxxxxxx@newsletter')
// Fetch and log metadata
const info = await client.newsletter.metadata(channel.id)
console.log('Subscribers:', info.subscriberCount)
// Update details later
await client.newsletter.updateName(channel.id, 'My Project — Updates')
await client.newsletter.updateDescription(channel.id, 'Now with release notes!')
// Mute and then unmute notifications on a followed channel
await client.newsletter.mute('xxxxxxxxxxxxxxxxxx@newsletter')
await client.newsletter.unmute('xxxxxxxxxxxxxxxxxx@newsletter')
})See also
- Client & Lifecycle —
client.newsletternamespace overview and other domain modules. - Configuration — tune or disable the operationGuard intervals.
- Error Handling — full error taxonomy and
ZaileysDomainError. - Troubleshooting — what to do when operations are throttled or accounts are flagged.