Skip to main content
The Events feature creates WhatsApp event messages — the scheduled-event bubble with a date, location, and join link. It also sends RSVPs. Like polls, an event carries a per-message message_secret. Responders derive their RSVP encryption key from that secret. Keep the secret so you can send and decrypt responses later.

Access

Access event operations through the client:
let events = client.events();

Methods

create

Create and send an event message.
pub async fn create(
    &self,
    to: &Jid,
    params: EventCreationParams,
) -> Result<(SendResult, Vec<u8>)>
to
&Jid
required
Recipient JID — a direct message or group chat.
params
EventCreationParams
required
Event details. Only name is required; everything else is optional. See EventCreationParams.
(send_result, message_secret)
(SendResult, Vec<u8>)
A SendResult and the event’s 32-byte message_secret. Store the secret — it is required to decrypt the RSVPs that come back. A fresh secret is generated per event and attached as messageContextInfo.messageSecret; WhatsApp Web rejects an event without one.
Example:
use whatsapp_rust::features::EventCreationParams;

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

let (sent, secret) = client.events().create(&chat, EventCreationParams {
    name: "Team offsite".to_string(),
    description: Some("Bring a laptop".to_string()),
    start_time: Some(1_760_000_000),     // unix seconds
    end_time: Some(1_760_010_000),
    location: None,
    extra_guests_allowed: Some(true),
    ..Default::default()
}).await?;

// Persist `secret` keyed by `sent.message_id` so you can decrypt RSVPs later.
println!("Event sent: {}", sent.message_id);

respond

RSVP to an event. The RSVP is end-to-end encrypted against the event’s message_secret.
pub async fn respond(
    &self,
    chat_jid: &Jid,
    event_msg_id: &str,
    event_creator_jid: &Jid,
    message_secret: &[u8],
    response: EventResponseType,
    extra_guest_count: Option<i32>,
) -> Result<SendResult>
chat_jid
&Jid
required
Chat JID where the event was sent.
event_msg_id
&str
required
Message ID of the event creation message.
event_creator_jid
&Jid
required
JID of the user who created the event. It keys the RSVP’s encryption derivation and AAD, so it must match the creator exactly.
message_secret
&[u8]
required
The 32-byte secret from the event creation message.
response
EventResponseType
required
Going, NotGoing, or Maybe. See EventResponseType.
extra_guest_count
Option<i32>
Number of additional guests you’re bringing, when the event allows extra guests.
SendResult
SendResult
Result of the RSVP send. See SendResult.
Example:
use whatsapp_rust::features::EventResponseType;

let creator: Jid = "15551234567@s.whatsapp.net".parse()?;

client.events()
    .respond(
        &chat,
        &event_msg_id,
        &creator,
        &message_secret,
        EventResponseType::Going,
        Some(2), // bringing two guests
    )
    .await?;
The responder (self) JID also keys the derivation, so it must use the creator’s namespace: your own LID for a LID-addressed event, your PN otherwise (falling back to PN when your LID isn’t known). The library resolves this for you, mirroring the poll-vote path.

Decrypting inbound RSVPs

When you receive an EncEventResponseMessage, decrypt it with the event’s secret using the helpers in wacore::event:
use wacore::event::decrypt_event_response_with_secret;

let response = decrypt_event_response_with_secret(
    &enc_payload,
    &iv,
    &message_secret,       // the secret you stored at create() time
    &event_msg_id,
    &event_creator_jid,    // creator (non-AD form)
    &responder_jid,        // who sent the RSVP (non-AD form)
)?;

println!("RSVP: {:?}", response.response);            // Going / NotGoing / Maybe
println!("Extra guests: {:?}", response.extra_guest_count);
FunctionDescription
encrypt_event_response_with_secret(response, secret, stanza_id, creator, responder) -> (Vec<u8>, [u8; 12])Encrypt an EventResponseMessage against the event secret. Returns (payload_with_tag, iv).
decrypt_event_response_with_secret(payload, iv, secret, stanza_id, creator, responder) -> EventResponseMessageDecrypt an inbound RSVP. The creator + responder JIDs must match what the responder used, or decryption fails (rather than silently mis-decrypting).
Both are thin wrappers over the shared secret_enc_addon machinery specialized for the "Event Response" use-case, matching WhatsApp Web’s WAWebAddonEncryption.

Types

EventCreationParams

#[derive(Debug, Clone, Default)]
pub struct EventCreationParams {
    pub name: String,
    pub description: Option<String>,
    pub start_time: Option<i64>,
    pub end_time: Option<i64>,
    pub join_link: Option<String>,
    pub location: Option<wa::message::LocationMessage>,
    pub is_scheduled_call: Option<bool>,
    pub extra_guests_allowed: Option<bool>,
}
FieldTypeDescription
nameStringEvent title (required; must not be empty).
descriptionOption<String>Free-text description.
start_timeOption<i64>Start time in unix seconds.
end_timeOption<i64>End time in unix seconds.
join_linkOption<String>Call/join link.
locationOption<LocationMessage>Event location.
is_scheduled_callOption<bool>Mark the event as a scheduled call.
extra_guests_allowedOption<bool>Allow responders to bring extra guests.

EventResponseType

whatsapp_rust re-exports this enum from the generated proto.
pub enum EventResponseType {
    Unknown,   // 0
    Going,     // 1
    NotGoing,  // 2
    Maybe,     // 3
}

Error handling

All methods return Result<T, anyhow::Error>. Common errors:
  • Empty event name when calling create.
  • Not logged in — the responder’s own JID can’t be determined.
  • message_secret not 32 bytes — encryption/decryption rejects the wrong size.
  • GCM tag verification failed — wrong secret, wrong creator/responder JID, or a tampered payload.

See also

  • Polls — the closest analog; also uses a per-message secret
  • Send API — low-level send operations
  • Events — event types emitted on receive