> ## 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.

# June 8, 2026 — Forward messages, played receipts, and group pictures

> Forward messages with a new high-level API, send played receipts for voice/video notes, and manage group profile pictures.

## 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.

```rust theme={null}
// `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`](/api/send#forward_message) and the [Forwarding messages guide](/guides/sending-messages#forwarding-messages) 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`.

```rust theme={null}
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](/api/receipt#mark_as_played).

***

**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).

```rust theme={null}
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](/api/groups#set_profile_picture) and the [Group management guide](/guides/group-management#set-or-remove-the-group-picture) 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.

```rust theme={null}
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](/api/contacts#is_on_whatsapp) for the full field list.
