Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/wppconnect-team/wa-js/llms.txt

Use this file to discover all available pages before exploring further.

The WPP.call module exposes WhatsApp Web’s calling layer through five functions and one event. It lets you send outgoing call offers (voice or video), accept or reject incoming calls identified by their call ID, terminate active or ringing calls, and enable the calling UI on WhatsApp Web desktop. All signalling is performed over WhatsApp’s SMAX WebSocket protocol — the functions negotiate codecs and encryption keys, then dispatch the appropriate stanza to the peer.
The call functions only handle call signalling (offer, accept, reject, end). They do not set up an audio/video pipeline. WhatsApp Web’s native calling interface must be present to process actual media streams, or you must supply your own media handling layer.

Functions

offer

Send a call offer to a contact, initiating a voice or video call.
// Voice call
WPP.call.offer('[number]@c.us');

// Video call
WPP.call.offer('[number]@c.us', { isVideo: true });
to
string
required
The JID of the contact to call. Must be a user JID ([number]@c.us). Group call JIDs are not supported by this function.
options
object
Returns Promise<CallModel> — the internal CallModel instance for the outgoing call, with the initial state OUTGOING_CALLING. The model’s id can be used with end to cancel the call.
offer builds a call offer stanza with Opus audio codec (at 16 kHz and 8 kHz) and, when isVideo is true, VP8 video. A 256-bit encryption key is generated client-side and included in the offer via <dest> elements.

accept

Accept an incoming call. If no callId is provided, the first call in INCOMING_RING state (or the first group call) is accepted.
// Accept the first incoming call automatically
WPP.call.accept();

// Accept a specific call by ID
WPP.call.accept(callId);

// Common pattern: accept after a short delay
WPP.on('call.incoming_call', (call) => {
  setTimeout(() => {
    WPP.call.accept(call.id);
  }, 1000);
});
callId
string
The call ID to accept. Omit to accept the first available incoming call automatically.
Returns Promise<boolean> — resolves true after the accept stanza is successfully sent to the peer. The accept stanza negotiates the same Opus audio codecs as the original offer, plus VP8 video if the incoming call is a video call.
Throws a WPPError with code call_not_found if no matching call exists, or call_is_not_incoming_ring if the specified call is not currently ringing.

reject

Reject an incoming call. Sends a reject stanza to the caller. If no callId is given, the first ringing call (including group calls) is rejected.
// Reject the first incoming call
WPP.call.reject();

// Reject a specific call
WPP.call.reject(callId);

// Auto-reject all incoming calls
WPP.on('call.incoming_call', (call) => {
  WPP.call.reject(call.id);
});
reject is also exported as the alias rejectCall:
WPP.call.rejectCall(callId);
callId
string
The call ID to reject. Omit to reject the first available incoming call.
Returns Promise<boolean> — resolves true after the reject stanza is sent.
Throws a WPPError with code call_not_found if the call cannot be found, or call_is_not_incoming_ring if the call is not in a rejectable state.

end

End an active or outgoing call. Works for calls in ACTIVE, OUTGOING_CALLING, OUTGOING_RING, or CallActive states. If callId is omitted, the store’s active call is used.
// End the current active call
WPP.call.end();

// End a call by its ID
WPP.call.end(callId);
callId
string
The call ID to terminate. Omit to end the currently active call.
Returns Promise<boolean> — resolves true after the terminate stanza is sent to the peer.
Throws a WPPError with code call_not_found if no active call is found, or call_is_not_outcoming_calling if the call is not in a terminable state.

enableCallInterface

Patch WhatsApp Web’s internal A/B feature flags to enable the calling UI on the web/desktop client. This is necessary because WhatsApp Web disables calling by default unless an internal flag (enable_web_calling) is set.
// Call once when WA-JS is initialised
WPP.call.enableCallInterface();
Returns void — this function applies a wrapModuleFunction patch that intercepts getABPropConfigValue and overrides the following keys:
KeyOverridden value
enable_web_callingtrue
enable_web_group_callingtrue
web_voip_call_tab_new_calltrue
calling_lid_version1
heartbeat_interval_s5
Call enableCallInterface() early in your injection script so the flags are active before WhatsApp Web renders the call button.

Events

call.incoming_call

Emitted when WhatsApp Web processes an incoming call offer via CallStore.processIncomingCall.
WPP.on('call.incoming_call', (call) => {
  console.log('Incoming call from', call.sender.toString());
  console.log('Video?', call.isVideo);
  console.log('Group call?', call.isGroup);

  // Auto-reject
  WPP.call.reject(call.id);
});

Event payload fields

FieldTypeDescription
idstringUnique call ID. Pass this to accept, reject, or end.
isGroupbooleantrue if this is a group call.
isVideobooleantrue if the call includes a video track.
offerTimenumberUnix timestamp when the offer was sent.
senderWidWhatsApp ID of the caller (without device suffix).
peerJidWidFull peer JID including device ID.
Each unique call ID is tracked internally so that the event fires only once per incoming call, even if processIncomingCall is invoked multiple times for the same call.

Common patterns

// 1. Enable the calling UI
WPP.call.enableCallInterface();

// 2. Send a call offer
const callModel = await WPP.call.offer('[number]@c.us');
console.log('Outgoing call ID:', callModel.id);

// 3. End the call after 30 seconds
setTimeout(() => WPP.call.end(callModel.id), 30000);
WPP.on('call.incoming_call', async (call) => {
  console.log('Rejecting call from', call.sender.toString());
  await WPP.call.reject(call.id);
});
WPP.on('call.incoming_call', async (call) => {
  if (!call.isGroup && !call.isVideo) {
    await WPP.call.accept(call.id);

    setTimeout(async () => {
      await WPP.call.end(call.id);
    }, 10000);
  }
});
WPP.on('call.incoming_call', (call) => {
  console.table({
    id: call.id,
    from: call.sender.toString(),
    isVideo: call.isVideo,
    isGroup: call.isGroup,
    time: new Date(call.offerTime * 1000).toISOString()
  });
});

Build docs developers (and LLMs) love