Documentation Index
Fetch the complete documentation index at: https://whatsapp-rust.jlucaso.com/llms.txt
Use this file to discover all available pages before exploring further.
The Newsletter feature provides methods for managing WhatsApp newsletter channels, including creation, subscription management, 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:
let newsletter = client.newsletter();
Methods
list_subscribed
List all newsletters the user is subscribed to.
pub async fn list_subscribed(&self) -> Result<Vec<NewsletterMetadata>, MexError>
Returns:
Vec<NewsletterMetadata> — List of subscribed newsletters
Example:
let newsletters = client.newsletter().list_subscribed().await?;
for nl in &newsletters {
println!("{}: {} ({} subscribers)", nl.jid, nl.name, nl.subscriber_count);
}
Fetch metadata for a newsletter by its JID.
pub async fn get_metadata(&self, jid: &Jid) -> Result<NewsletterMetadata, MexError>
Parameters:
jid — Newsletter JID (server must be newsletter)
Returns:
NewsletterMetadata — Full newsletter metadata
Example:
let metadata = client.newsletter().get_metadata(&newsletter_jid).await?;
println!("Name: {}", metadata.name);
println!("Subscribers: {}", metadata.subscriber_count);
println!("Verified: {:?}", metadata.verification);
Fetch metadata for a newsletter by its invite code.
pub async fn get_metadata_by_invite(
&self,
invite_code: &str,
) -> Result<NewsletterMetadata, MexError>
Parameters:
invite_code — Newsletter invite code string
Returns:
NewsletterMetadata — Full newsletter metadata
Example:
let metadata = client.newsletter()
.get_metadata_by_invite("ABC123")
.await?;
println!("Found: {} ({})", metadata.name, metadata.jid);
create
Create a new newsletter.
pub async fn create(
&self,
name: &str,
description: Option<&str>,
) -> Result<NewsletterMetadata, MexError>
Parameters:
name — Newsletter name
description — Optional description
Returns:
NewsletterMetadata — Metadata of the newly created newsletter
Example:
let created = client.newsletter()
.create("My Channel", Some("A description"))
.await?;
println!("Created: {} ({})", created.name, created.jid);
join
Join (subscribe to) a newsletter.
pub async fn join(&self, jid: &Jid) -> Result<NewsletterMetadata, MexError>
Parameters:
jid — Newsletter JID to join
Returns:
NewsletterMetadata — Metadata with the viewer’s role set to Subscriber
Example:
let joined = client.newsletter().join(&newsletter_jid).await?;
println!("Joined '{}' as {:?}", joined.name, joined.role);
leave
Leave (unsubscribe from) a newsletter.
pub async fn leave(&self, jid: &Jid) -> Result<(), MexError>
Parameters:
jid — Newsletter JID to leave
Example:
client.newsletter().leave(&newsletter_jid).await?;
update
Update a newsletter’s name and/or description.
pub async fn update(
&self,
jid: &Jid,
name: Option<&str>,
description: Option<&str>,
) -> Result<NewsletterMetadata, MexError>
Parameters:
jid — Newsletter JID
name — New name, or None to keep the current name
description — New description, or None to keep the current description
Returns:
NewsletterMetadata — Updated metadata
Example:
let updated = client.newsletter()
.update(&newsletter_jid, Some("New Name"), None)
.await?;
println!("Updated: {}", updated.name);
Sending messages
Newsletter message sending is handled by the unified client.send_message() method. See the Send API reference for full details.
use waproto::whatsapp as wa;
let message = wa::Message {
conversation: Some("Hello subscribers!".to_string()),
..Default::default()
};
// Pass a newsletter JID directly to send_message
let msg_id = client.send_message(newsletter_jid, message).await?;
The library detects newsletter recipients automatically and sends messages as plaintext (no Signal encryption), with the correct 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.
pub async fn send_reaction(
&self,
jid: &Jid,
server_id: u64,
reaction: &str,
) -> Result<(), anyhow::Error>
Parameters:
jid — Newsletter JID
server_id — Server-assigned ID of the message to react to
reaction — Emoji code (e.g., "👍", "❤️"), or empty string to remove
Example:
// Add a reaction
client.newsletter()
.send_reaction(&newsletter_jid, server_id, "👍")
.await?;
// Remove a reaction
client.newsletter()
.send_reaction(&newsletter_jid, server_id, "")
.await?;
get_messages
Fetch message history from a newsletter.
pub async fn get_messages(
&self,
jid: &Jid,
count: u32,
before: Option<u64>,
) -> Result<Vec<NewsletterMessage>, anyhow::Error>
Parameters:
jid — Newsletter JID
count — Maximum number of messages to return
before — If set, return messages before this server_id (for pagination)
Returns:
Vec<NewsletterMessage> — List of newsletter messages
Example:
// Fetch latest 50 messages
let messages = client.newsletter()
.get_messages(&newsletter_jid, 50, None)
.await?;
// Paginate backwards
if let Some(oldest) = messages.last() {
let older = client.newsletter()
.get_messages(&newsletter_jid, 50, Some(oldest.server_id))
.await?;
}
subscribe_live_updates
Subscribe to live updates for a newsletter (reaction counts, message changes).
pub async fn subscribe_live_updates(
&self,
jid: &Jid,
) -> Result<u64, anyhow::Error>
Parameters:
Returns:
u64 — Subscription duration in seconds (typically 300)
The server sends Event::NewsletterLiveUpdate events with updated reaction counts. You need to re-subscribe periodically when the duration expires.
Example:
let duration = client.newsletter()
.subscribe_live_updates(&newsletter_jid)
.await?;
println!("Subscribed for {}s", duration);
Types
Metadata for a newsletter channel. Implements PartialEq and Eq for direct comparison.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct NewsletterMetadata {
pub jid: Jid,
pub name: String,
pub description: Option<String>,
pub subscriber_count: u64,
pub verification: NewsletterVerification,
pub state: NewsletterState,
pub picture_url: Option<String>,
pub preview_url: Option<String>,
pub invite_code: Option<String>,
pub role: Option<NewsletterRole>,
pub creation_time: Option<u64>,
}
NewsletterVerification
#[non_exhaustive]
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum NewsletterVerification {
Verified,
Unverified,
}
NewsletterState
#[non_exhaustive]
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum NewsletterState {
Active,
Suspended,
Geosuspended,
}
NewsletterRole
The viewer’s role in a newsletter.
#[non_exhaustive]
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum NewsletterRole {
Owner,
Admin,
Subscriber,
Guest,
}
All newsletter enums are #[non_exhaustive], so match statements should include a wildcard arm to handle future variants.
NewsletterMessage
A message from a newsletter’s history.
pub struct NewsletterMessage {
/// Server-assigned message ID (monotonic, used for pagination cursors).
pub server_id: u64,
/// Message timestamp (Unix seconds).
pub timestamp: u64,
/// Message type (Text, Media, Reaction, etc.).
pub message_type: NewsletterMessageType,
/// Whether the viewer is the sender.
pub is_sender: bool,
/// Decoded protobuf message (from plaintext bytes).
pub message: Option<wa::Message>,
/// Reaction counts on this message.
pub reactions: Vec<NewsletterReactionCount>,
}
NewsletterMessageType
The type of a newsletter message. Uses a StringEnum for type-safe wire-protocol mapping. Implements PartialEq and Eq.
#[non_exhaustive]
pub enum NewsletterMessageType {
Text, // "text"
Media, // "media"
Reaction, // "reaction"
Revoke, // "revoke"
PollCreation, // "poll_creation"
PollVote, // "poll_vote"
Edit, // "edit"
Other(String), // Unknown/future types
}
Methods:
as_str() - Returns the wire-protocol string representation
From<&str> - Parse from wire string, unknown values become Other(String)
NewsletterReactionCount
A reaction count on a newsletter message.
pub struct NewsletterReactionCount {
pub code: String,
pub count: u64,
}
Error handling
Metadata and management methods return MexError:
pub enum MexError {
PayloadParsing(String),
// ... other variants
}
Message operations (send_reaction, get_messages, subscribe_live_updates) return anyhow::Error. Newsletter message sending uses client.send_message() which also returns anyhow::Error.
match client.newsletter().create("Test", None).await {
Ok(metadata) => println!("Created: {}", metadata.name),
Err(e) => eprintln!("Failed: {}", e),
}