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

# Events

> Create WhatsApp event messages and collect encrypted RSVPs

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:

```rust theme={null}
let events = client.events();
```

## Methods

### create

Create and send an event message.

```rust theme={null}
pub async fn create(
    &self,
    to: &Jid,
    params: EventCreationParams,
) -> Result<(SendResult, Vec<u8>)>
```

<ParamField path="to" type="&Jid" required>
  Recipient JID — a direct message or group chat.
</ParamField>

<ParamField path="params" type="EventCreationParams" required>
  Event details. Only `name` is required; everything else is optional. See [EventCreationParams](#eventcreationparams).
</ParamField>

<ResponseField name="(send_result, message_secret)" type="(SendResult, Vec<u8>)">
  A [`SendResult`](/api/send#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.
</ResponseField>

**Example:**

```rust theme={null}
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`.

```rust theme={null}
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>
```

<ParamField path="chat_jid" type="&Jid" required>
  Chat JID where the event was sent.
</ParamField>

<ParamField path="event_msg_id" type="&str" required>
  Message ID of the event creation message.
</ParamField>

<ParamField path="event_creator_jid" type="&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.
</ParamField>

<ParamField path="message_secret" type="&[u8]" required>
  The 32-byte secret from the event creation message.
</ParamField>

<ParamField path="response" type="EventResponseType" required>
  `Going`, `NotGoing`, or `Maybe`. See [EventResponseType](#eventresponsetype).
</ParamField>

<ParamField path="extra_guest_count" type="Option<i32>">
  Number of additional guests you're bringing, when the event allows extra guests.
</ParamField>

<ResponseField name="SendResult" type="SendResult">
  Result of the RSVP send. See [SendResult](/api/send#sendresult).
</ResponseField>

**Example:**

```rust theme={null}
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?;
```

<Note>
  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.
</Note>

## Decrypting inbound RSVPs

When you receive an `EncEventResponseMessage`, decrypt it with the event's secret using the helpers in `wacore::event`:

```rust theme={null}
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);
```

| Function                                                                                                         | Description                                                                                                                                          |
| ---------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| `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) -> EventResponseMessage` | Decrypt 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

```rust theme={null}
#[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>,
}
```

| Field                  | Type                      | Description                                |
| ---------------------- | ------------------------- | ------------------------------------------ |
| `name`                 | `String`                  | Event title (required; must not be empty). |
| `description`          | `Option<String>`          | Free-text description.                     |
| `start_time`           | `Option<i64>`             | Start time in unix seconds.                |
| `end_time`             | `Option<i64>`             | End time in unix seconds.                  |
| `join_link`            | `Option<String>`          | Call/join link.                            |
| `location`             | `Option<LocationMessage>` | Event location.                            |
| `is_scheduled_call`    | `Option<bool>`            | Mark the event as a scheduled call.        |
| `extra_guests_allowed` | `Option<bool>`            | Allow responders to bring extra guests.    |

### EventResponseType

`whatsapp_rust` re-exports this enum from the generated proto.

```rust theme={null}
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](/api/polls) — the closest analog; also uses a per-message secret
* [Send API](/api/send) — low-level send operations
* [Events](/concepts/events) — event types emitted on receive
