Skip to main content
The Mex feature wraps WhatsApp’s Meta Exchange (MEX) GraphQL API. Operations are persisted: you reference each query or mutation by a (name, id) pair pulled from a generated operation module, and pass its typed Variables. WhatsApp Web bundle updates rotate the numeric id, so the human-readable name keeps diagnostics stable across releases.

Access

let mex = client.mex();

Building a request

Each persisted operation lives in its own module under wacore::iq::mex_operations. Every module exposes:
  • NAME — the operation name (e.g. "WAWebJoinNewsletterMutation").
  • DOC_ID — the current persisted document ID.
  • OPERATION_KIND"query" or "mutation".
  • Variables — a typed struct matching the operation’s input shape.
  • Response — a typed struct matching the operation’s output shape.
Construct a MexRequest with MexRequest::new using those constants and a Variables value:
use wacore::iq::mex_operations::fetch_newsletter;
use whatsapp_rust::features::mex::MexRequest;

let request = MexRequest::new(
    fetch_newsletter::NAME,
    fetch_newsletter::DOC_ID,
    fetch_newsletter::Variables {
        input: Some(fetch_newsletter::Input {
            key: Some(jid.to_string()),
            r#type: Some("JID".into()),
            view_role: Some("GUEST".into()),
        }),
        fetch_viewer_metadata: Some(true),
        fetch_full_image: Some(true),
        fetch_creation_time: Some(true),
    },
);

let response = client.mex().query(request).await?;
For operations whose Variables schema is too permissive to model exactly, pass any serde::Serialize value (for example a serde_json::json!({...})) as the variables — query and mutate are generic over V: Serialize.

Methods

query

Execute a GraphQL query.
pub async fn query<V: Serialize>(
    &self,
    request: MexRequest<V>,
) -> Result<MexResponse, MexError>

mutate

Execute a GraphQL mutation.
pub async fn mutate<V: Serialize>(
    &self,
    request: MexRequest<V>,
) -> Result<MexResponse, MexError>
Example — mutation with typed variables:
use wacore::iq::mex_operations::join_newsletter;
use whatsapp_rust::features::mex::MexRequest;

let request = MexRequest::new(
    join_newsletter::NAME,
    join_newsletter::DOC_ID,
    join_newsletter::Variables {
        newsletter_id: Some(jid.to_string()),
    },
);

let response = client.mex().mutate(request).await?;
Example — loosely-typed variables with serde_json:
use serde_json::json;
use wacore::iq::mex::MexDoc;
use whatsapp_rust::features::mex::MexRequest;

let request = MexRequest {
    doc: MexDoc {
        name: "WAWebUpdateGroupPropertyMutation",
        id: "8014515568645029",
    },
    variables: json!({
        "group_id": group_jid.to_string(),
        "property": "announcement",
        "value": true,
    }),
};

let response = client.mex().mutate(request).await?;

Types

MexDoc

A persisted-query descriptor. Re-exported from wacore::iq::mex.
pub struct MexDoc {
    /// Human-readable operation name (stable across bundle releases).
    pub name: &'static str,
    /// Numeric persisted-query ID (rotates with bundle releases).
    pub id: &'static str,
}

MexRequest

A persisted-query descriptor plus its typed variables. V is the variables type — usually the generated Variables struct for an operation, but any Serialize value works.
pub struct MexRequest<V> {
    pub doc: MexDoc,
    pub variables: V,
}

new

Pair an operation’s NAME and DOC_ID with its variables.
pub fn new(
    name: &'static str,
    id: &'static str,
    variables: V,
) -> MexRequest<V>

MexResponse

Response from a GraphQL operation.
pub struct MexResponse {
    /// Response data (if successful).
    pub data: Option<serde_json::Value>,
    /// List of errors (if any).
    pub errors: Option<Vec<MexGraphQLError>>,
}
Methods:
  • has_data()true if the response contains data.
  • has_errors()true if the response contains errors.
  • fatal_error() — the first fatal error (any error with an error_code), if any.

MexGraphQLError

pub struct MexGraphQLError {
    pub message: String,
    pub extensions: Option<MexErrorExtensions>,
}
Methods:
  • error_code() — the numeric error code, if present.
  • is_summary()true when the error is marked as a summary.
  • has_error_code()true when an error code is set.

MexErrorExtensions

pub struct MexErrorExtensions {
    pub error_code: Option<i32>,
    pub is_summary: Option<bool>,
    pub is_retryable: Option<bool>,
    pub severity: Option<String>,
}

Error handling

pub enum MexError {
    /// Payload missing or malformed with only a descriptive message.
    PayloadParsing(String),
    /// Payload contained an invalid JID.
    InvalidJid(JidError),
    /// GraphQL error with a numeric code surfaced as a typed error.
    ExtensionError { code: i32, message: String },
    /// Underlying IQ request failed.
    Request(IqError),
    /// JSON serialization or deserialization error.
    Json(serde_json::Error),
}
query and mutate automatically convert any fatal GraphQL error (any error with an error_code) into MexError::ExtensionError so you can match on it without inspecting response.errors yourself.
use whatsapp_rust::features::mex::MexError;

match client.mex().query(request).await {
    Ok(response) => {
        if response.has_data() {
            println!("Success: {:?}", response.data);
        }
    }
    Err(MexError::ExtensionError { code, message }) => {
        eprintln!("MEX error {}: {}", code, message);
    }
    Err(e) => eprintln!("Request failed: {}", e),
}

Response handling

Check for data

let response = client.mex().query(request).await?;

if response.has_data() {
    let data = response.data.unwrap();
    // Process data
}

Handle non-fatal errors

Errors without an error_code are non-fatal and surface in response.errors alongside any partial data.
let response = client.mex().query(request).await?;

if response.has_errors() {
    for error in response.errors.as_ref().unwrap() {
        if !error.is_summary() && !error.has_error_code() {
            eprintln!("Warning: {}", error.message);
        }
    }
}

Decode the typed response

Generated operation modules also expose a Response struct that mirrors the GraphQL schema. Decode it from response.data with serde_json:
use wacore::iq::mex_operations::fetch_newsletter;

let response = client.mex().query(request).await?;

if let Some(data) = response.data {
    let decoded: fetch_newsletter::Response = serde_json::from_value(data)?;
    if let Some(newsletter) = decoded.xwa2_newsletter {
        println!("Newsletter: {:?}", newsletter);
    }
}
The persisted DOC_ID for each operation is regenerated from the latest WhatsApp Web bundle. Pin to a specific crate version if you need a stable wire format.