Skip to main content

New features

Forward messages with Client::forward_message Client::forward_message(to, &message) is a high-level wrapper that turns any received message into a properly forwarded one:
  • Sets context_info.is_forwarded = true so recipients see the Forwarded label.
  • Bumps forwarding_score, jumping to the 127 Forwarded many times sentinel at 5.
  • Strips the source reply/quote chain and mentions.
  • Drops the source message_secret so the send path mints a fresh one.
  • Unwraps ephemeral and view-once wrappers before sending the inner content.
  • Relays existing media from the same CDN blob — no re-download or re-upload.
// `received` is a `wa::Message` from an incoming event.
client.forward_message(destination_jid, &received).await?;
If you need to tweak the prepared body before sending (custom caption, extra stanza nodes), use the underlying MessageExt::prepare_for_forward helper directly and pass the result to send_message_with_options. See forward_message and the Forwarding messages guide for details. Send played receipts for voice and video notes Client::mark_as_played(chat, sender, message_ids) now sends <receipt type="played"> (or played-self for newsletters) so recipients can signal that a voice note or video note was played. Pass Some(sender) for groups, broadcast lists, and status broadcasts; pass None for DMs. Extra message IDs are batched into a <list> child, matching mark_as_read.
let chat_jid: Jid = "15551234567@s.whatsapp.net".parse()?;

client.mark_as_played(
    &chat_jid,
    None, // No participant for DMs
    vec!["VOICE_MSG_ID".to_string()],
).await?;
Inbound Played / PlayedSelf receipts were already parsed into Event::Receipt; this closes the gap on the outbound side. See the receipt API reference.
Set or remove a group’s profile picture The Groups feature now exposes admin-side methods for managing a group’s display picture, mirroring the existing own-picture API on Profile:
  • Groups::set_profile_picture(group_jid, image_data) — upload JPEG bytes as the group avatar.
  • Groups::remove_profile_picture(group_jid) — clear the group’s current picture.
Both calls require the authenticated user to be a group admin. Passing empty bytes to set_profile_picture routes to removal, so callers that already model “no image” as an empty buffer keep working. The caller is responsible for sizing and cropping the JPEG (WhatsApp uses 640x640).
use std::fs;

let group_jid: Jid = "120363012345678@g.us".parse()?;

// Set
let image_bytes = fs::read("group_avatar.jpg")?;
let response = client.groups().set_profile_picture(&group_jid, image_bytes).await?;
println!("New picture ID: {:?}", response.id);

// Remove
client.groups().remove_profile_picture(&group_jid).await?;
See Groups API reference and the Group management guide for details.
Surface verified business names from contact lookups IsOnWhatsAppResult and UserInfo now expose verified_name: Option<VerifiedName> alongside the existing is_business flag. The certificate carried in the <business><verified_name> response is decoded, so you can show the verified display name (the green-checkmark name) without a second request. verified_name is Some only for verified business accounts; regular accounts and unverified businesses stay None. VerifiedName re-exports from whatsapp_rust::features and exposes name, serial, issuer, and the raw certificate bytes.
use whatsapp_rust::features::VerifiedName;

let results = client.contacts().is_on_whatsapp(&[
    Jid::pn("15551234567"),
]).await?;

for result in results {
    if let Some(VerifiedName { name: Some(name), .. }) = &result.verified_name {
        println!("{} → verified as {}", result.jid, name);
    }
}
Because IsOnWhatsAppResult is #[non_exhaustive], adding this field is not a breaking change for consumers that construct it via the parser. See the contacts API reference for the full field list.