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
Building a request
Each persisted operation lives in its own module underwacore::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".VARIABLE_KEYS— every variable name the persisted document declares, e.g.&["fetch_viewer_metadata", "fetch_full_image", ...].Variables— a typed struct matching the operation’s input shape.Response— a typed struct matching the operation’s output shape.
MexRequest with MexRequest::new using those constants and a Variables value:
A generated
Variables does not implement Default. The server binds a persisted query’s variables by name and answers a bare 400 Bad Request when it can’t bind one of them, so every variable the operation declares has to be named at the call site — ..Default::default() does not compile, and neither does Variables::default(). Passing None for an Option field is still how you send a variable WhatsApp Web itself omits; nested input objects (for example Updates on update_newsletter) are unaffected and keep Default.Methods
query
Execute a GraphQL query.mutate
Execute a GraphQL mutation.serde_json:
fetch_new_chat_message_capping_info
Fetch the cap on how many new one-on-one conversations you can start in the current cycle.wa_individual_new_chat_msg_capping_fetch_ttl_seconds, 1 hour), gated on wa_individual_new_chat_msg_capping_enabled. If the cap doesn’t apply to your account, you still get an answer — the status just reports NONE.
Example:
get_username
Read this account’s own username, its state, and its username key.None— no username is set on this account. WhatsApp Web reads the same 404 the server sends for this case.Some(OwnUsername)— the account’s username info.
Only reads are exposed.
set_username and set_username_key are not wrapped. They change the account’s identity in a way the server does not undo. A wrong call can burn a handle that someone else could otherwise take, and there is no way to test either safely.Types
MexDoc
A persisted-query descriptor. Re-exported fromwacore::iq::mex.
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.
declared_variables— the variable names the persisted document declares (an operation module’sVARIABLE_KEYS), carried somissing_variablescan check a payload against them even whenvariablesis a loosely-typedSerializevalue.
new
Pair an operation’sNAME, DOC_ID, and VARIABLE_KEYS with its variables. Prefer this over building MexRequest as a struct literal.
missing_variables
Declared variables this request’s payload does not carry, found by serializingvariables and checking which of declared_variables are absent.
Serialize form of a request, where the compiler can’t check a json! payload against the operation’s declared variables the way it checks a Variables struct literal.
MexResponse
Response from a GraphQL operation.has_data()—trueif the response contains data.has_errors()—trueif the response contains errors.fatal_error()— the first fatal error (any error with anerror_code), if any.
MexGraphQLError
error_code()— the numeric error code, if present.is_summary()—truewhen the error is marked as a summary.has_error_code()—truewhen an error code is set.
MexGraphQLError is re-exported from the crate root as whatsapp_rust::MexGraphQLError, alongside MexError, MexErrorExtensions, MexFatalError, MexRequest, MexResponse, and OwnUsername.MexErrorExtensions
MexFatalError
The typed cause behind a fatal GraphQL error, fromwacore::iq::mex. WhatsApp Web treats a GraphQL error carrying an extension code as fatal to the whole request. This struct is what lets that code survive the trip through IqError::ParseError’s source() chain instead of being flattened into a plain message.
query/mutate already downcast it for you and hand back MexError::ExtensionError. It’s public for callers working with wacore::iq::mex::MexQuerySpec directly, below the whatsapp_rust::features::mex::Mex wrapper.
OwnUsername
This account’s own Meta username, asget_username reports it. Every field is optional because the server omits the ones that don’t apply.
NewChatMessageCapping
How many new one-on-one conversations you can still start in the current cycle, and why. Every field is optional — the server omits any that don’t apply to your account’s tier.total_quota/used_quota— new chats allowed / already started this cyclecycle_start_timestamp/cycle_end_timestamp/server_sent_timestamp— Unix seconds. The cap lifts oncecycle_end_timestamppasses.
remaining_quota() -> Option<u64>— saturating subtraction ofused_quotafromtotal_quota, when both are present; returnsSome(0)whenused_quotaexceedstotal_quota
CappingStatus
Where you stand against the cap.CappingOteStatus
Whether you’re eligible for the one-time extension that lifts the cap for a cycle.CappingMvStatus
Your Meta Verified subscription state, which lifts the cap permanently.NewChatMessageCapping, CappingStatus, CappingOteStatus, and CappingMvStatus are re-exported from the crate root, alongside the other Mex types.Error handling
query and mutate automatically convert any fatal GraphQL error (any error with an error_code) into MexError::ExtensionError. This lets you match on it without inspecting response.errors yourself. This now happens for every MEX operation via a typed MexFatalError carried inside IqError::ParseError’s source chain. Previously the code could be lost, surfacing only as a message inside MexError::Request(IqError::ParseError(_)).
get_username treats a fatal 404 as “no username set” rather than a failure. It arrives as either MexError::ExtensionError { code: 404, .. } or MexError::Request(IqError::ServerError { code: 404, .. }) — the two shapes WhatsApp Web’s own MEX client raises a 404 from. Either shape returns Ok(None) instead of an error.
Response handling
Check for data
Handle non-fatal errors
Errors without anerror_code are non-fatal and surface in response.errors alongside any partial data.
Decode the typed response
Generated operation modules also expose aResponse struct that mirrors the GraphQL schema. Decode it from response.data with serde_json:
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.