Newsletter feature provides methods for managing WhatsApp newsletter channels, including creation, subscription management, admin operations, reactions, and live updates. Newsletter operations use MEX (GraphQL) for metadata/management and IQ stanzas for message operations.
Newsletter message sending is handled by the unified client.send_message() method — see the Send API. Reactions remain on the Newsletter struct because they use a different stanza format.
Newsletter messages are plaintext — they are not encrypted with the Signal protocol.
Access
Access newsletter operations through the client:Methods
list_subscribed
List all newsletters the user is subscribed to.Vec<NewsletterMetadata>— List of subscribed newsletters
get_metadata
Fetch metadata for a newsletter by its JID.jid— Newsletter JID (server must benewsletter)
NewsletterMetadata— Full newsletter metadata
get_metadata_by_invite
Fetch metadata for a newsletter by its invite code.invite_code— Newsletter invite code string
NewsletterMetadata— Full newsletter metadata
create
Create a new newsletter.name— Newsletter namedescription— Optional description
NewsletterMetadata— Metadata of the newly created newsletter
join
Join (subscribe to) a newsletter.jid— Newsletter JID to join
NewsletterMetadata— Metadata with the viewer’s role set toSubscriber
leave
Leave (unsubscribe from) a newsletter.jid— Newsletter JID to leave
update
Update a newsletter’s name and/or description.jid— Newsletter JIDname— New name, orNoneto keep the current namedescription— New description, orNoneto keep the current description
NewsletterMetadata— Updated metadata
set_picture
Replace a newsletter’s picture. Carried by the same mutation asupdate — WhatsApp Web edits the picture as base64-encoded JPEG bytes — so the response is the newsletter’s refreshed metadata.
jid— Newsletter JIDjpeg— JPEG-encoded image bytes
NewsletterMetadata— Updated metadata
remove_picture
Remove a newsletter’s picture.jid— Newsletter JID
NewsletterMetadata— Updated metadata
delete
Delete a newsletter. Owner-only.jid— Newsletter JID
change_owner
Transfer a newsletter’s ownership to another user. Owner-only.jid— Newsletter JIDuser— The new owner. May be a LID or a phone-number JID — a phone-number JID is resolved to its LID before the request. If no LID is known for the target, the call fails withNewsletterError::InvalidRequestrather than sending an address the server can’t route.
demote_admin
Demote an admin of a newsletter back to subscriber. Owner-only.jid— Newsletter JIDuser— The admin to demote. Same LID resolution aschange_owner.
get_admin_info
Fetch a newsletter’s admin-side information, including its admin count.jid— Newsletter JID
NewsletterAdminInfo— Admin count, the viewer’s own admin profile, and the admin-profiles setting
The admin count has no query of its own — it rides along with the admin profile and the admin-profiles setting in this one response. The server only answers it for admins and owners, so
admin_count is None for everyone else.get_followers
List up tocount of a newsletter’s followers (subscribers).
jid— Newsletter JIDcount— Maximum number of followers to return
This operation takes no cursor — WhatsApp Web asks for a single page clamped to its subscriber-list limit, so
count is the whole request. There is no built-in pagination.Vec<NewsletterFollower>— One page of followers
set_follower_mute
Mute or unmute a newsletter’s follower-activity notifications (WhatsApp Web’sMUTE_FOLLOWER_ACTIVITY). Sent via MEX as a user-setting update.
jid— Newsletter JIDmuted—truesilences notifications,falsere-enables them
set_admin_mute
Mute or unmute a newsletter’s admin-activity notifications (WhatsApp Web’sMUTE_ADMIN_ACTIVITY). Only meaningful for owners/admins.
jid— Newsletter JIDmuted—truesilences admin-activity notifications,falsere-enables them
The mute state is sent as
ON/OFF; the mute expiration is local database state and is never put on the wire, matching WhatsApp Web’s WAWebNewsletterUpdateUserSettingJob.Sending messages
Newsletter message sending is handled by the unifiedclient.send_message() method. See the Send API reference for full details.
type and mediatype stanza attributes inferred from the message content. Stanza-level <meta> nodes (for polls, events, etc.) are also included automatically, matching WhatsApp Web behavior.
Newsletter::send_message() was removed. Use client.send_message() instead — it accepts newsletter, group, and direct message JIDs.send_reaction
Send a reaction to a newsletter message.jid— Newsletter JIDserver_id— Server-assigned ID of the message to react toreaction— Emoji code (e.g.,"👍","❤️"), or empty string to remove
edit_message
Edit a previously-sent newsletter message. Channel messages are plaintext, so the edit is sent as a<message edit="1"> stanza with the new protobuf body — not through the E2E send path.
jid— Newsletter JID. Non-newsletter JIDs are rejected with an error; useClient::edit_messagefor DMs and groups.message_id— The target message’smessage_id(the wire stanza id, as returned bysend_messageor carried onNewsletterMessage). This is not theserver_idused by reactions. Empty IDs are rejected.new_content— Replacement message body. Typically awa::Message { conversation: Some(..), .. }for text edits.
revoke_message
Revoke (delete) a previously-sent newsletter message. Likeedit_message, this goes through the plaintext channel path, not the E2E send path.
jid— Newsletter JID. Non-newsletter JIDs are rejected; useClient::revoke_messagefor DMs and groups.message_id— The target message’smessage_id(wire stanza id, notserver_id). Empty IDs are rejected.
Newsletter JIDs are now also rejected at the root of the E2E send path. If your code accidentally routes a channel JID through
send_message_impl, pin_message, or the standard edit_message / revoke_message on Client, you get an error that names the mis-route instead of a malformed encrypted fan-out.get_messages
Fetch message history from a newsletter.jid— Newsletter JIDcount— Maximum number of messages to returnbefore— If set, return messages before thisserver_id(for pagination)
Vec<NewsletterMessage>— List of newsletter messages
subscribe_live_updates
Subscribe to live updates for a newsletter (reaction counts, message changes).jid— Newsletter JID
u64— Subscription duration in seconds (typically 300)
Event::NewsletterLiveUpdate events with updated reaction counts. You need to re-subscribe periodically when the duration expires.
Example:
Types
NewsletterMetadata
Metadata for a newsletter channel. ImplementsPartialEq and Eq for direct comparison.
NewsletterVerification
NewsletterState
NewsletterRole
The viewer’s role in a newsletter.#[non_exhaustive], so match statements should include a wildcard arm to handle future variants.
NewsletterAdminProfile
An admin’s public profile within a newsletter, carried onNewsletterAdminInfo and on a NewsletterFollower who is an admin.
id is the profile’s own identifier, not a JID — the server hands it back as an opaque string and WhatsApp Web never parses it.NewsletterAdminInfo
Admin-side information about a newsletter, returned byget_admin_info.
admin_count— How many admins the newsletter has. The server only answers this for admins and owners, so it’sNonefor everyone else — never a0that would misleadingly read as “no admins”.admin_profile— The viewer’s own admin profile, present once they’ve set one up.admin_profiles_enabled— Whether admin profiles are enabled for this newsletter.
NewsletterFollower
A follower (subscriber) of a newsletter, returned byget_followers.
jid— The follower’s identity JID — a LID on accounts that have migrated.phone_jid— The follower’s phone-number JID, withheld by the server when the follower’s privacy settings hide it.role— The follower’s role in the newsletter.follow_time— When the follower subscribed (Unix seconds).admin_profile— Set when the follower is an admin who has published a profile.
NewsletterMessage
A message from a newsletter’s history.#[non_exhaustive] — construct it from parsed responses rather than by struct literal, so newly-added counters land as fields, not breaks.
message_id— Wire stanza id. Pass this toedit_messageandrevoke_message; it is not the same asserver_id, which reactions use. Empty when the server omitted it.server_id— Server-assigned monotonic id. Use it as the pagination cursor inget_messagesand as the target forsend_reaction.timestamp— Message timestamp (Unix seconds). Moves with an edit.message_type—Text,Media, orPollon the wire. An edit or revocation is not a message type; seeedit. Reactions are counts on the reacted-to message, not a type.edit—AdminEdit(3) for an edited message,AdminRevoke(8) for a revoked one,Emptyotherwise. A revoked message keeps its envelope, drops its body, its forward counter, andmessagebecomesNone.message— Decoded protobuf message from the<plaintext>bytes.Nonewhen the server sent no body (for example, after a revocation, or when the payload was empty).media_type— Hint about the payload readable without decoding it. Unknown values are kept asNewsletterMediaType::Other.reactions— Aggregated per-emoji counts.votes— Per-option tallies when this is a poll message; empty otherwise. SeeNewsletterPollVote.forwards_count— How many times the message was forwarded.Nonemeans the server omitted the counter; treat it as distinct fromSome(0).views_count,responses_count— View count and channel-question response count. Contract-derived; a follower-side capture never carried them, so expectNoneunless the viewer’s role in the channel entitles them to those figures.original_timestamp—<meta original_msg_t>in Unix seconds: when the message was first posted, as opposed totimestamp, which moves with an edit.last_edit_timestamp_ms—<meta msg_edit_t>in Unix milliseconds (unlike every other timestamp on this struct): when the message was last edited.poll_type— The poll’s lifecycle stage (creation, quiz creation, result snapshot). Populated only whenmessage_typeisPoll, matching WhatsApp Web’s scoping.content_type,question_type,message_association_type—<meta>classifiers.question_typeisquestionfor a channel question orreplyfor an admin reply.message_association_typerecords how this media relates to another message (media_poll,motion_photo,poll_add_option, …).is_wamo_sub—<meta is_wamo_sub="true">.admin_profile— Publishing admin’s public profile, on channels that enabled admin profiles.rcat—<rcat>payload bytes. Opaque receiver-side token WhatsApp Web associates withtype="media"+mediatype="url"link previews; carried verbatim and not interpreted.
NewsletterMessageType
Thetype attribute of a newsletter history <message>. Uses a wire enum with an Other(String) fallback so a future value on the wire deserializes rather than fails.
Text, Media, and Poll are produced by the wire; the other named variants are kept for source compatibility with earlier releases and will never match a parsed response. Read edits and revocations from NewsletterMessage::edit, poll stage from NewsletterMessage::poll_type, poll totals from NewsletterMessage::votes, and reaction totals from NewsletterMessage::reactions.
Methods:
as_str()— Wire-protocol string representation.From<&str>— Parse from a wire string; unknown values becomeOther(String).
NewsletterMediaType
Themediatype attribute of newsletter <plaintext>. Known values match the whatspec IR; anything else is kept as Other(String) for forward compatibility.
NewsletterQuestionType
Thequestiontype attribute in newsletter <meta>.
NewsletterMessageAssociationType
Themessage_association_type attribute in newsletter <meta>. Describes how a media message relates to another message.
NewsletterReactionCount
A reaction count on a newsletter message.NewsletterPollVote
A poll option’s vote tally on a newsletter message. Channel polls are counted server-side, so unlike a DM or group vote the totals arrive in plaintext — nothing to decrypt.count are dropped during parsing; a valid count="0" is preserved and remains distinct from absence.
Error handling
All newsletter methods returnResult<T, NewsletterError>: