Skip to content

How to handle an incoming call#

Beta version

The functionality is in beta mode. Features are subject to change and may also work unstably. There may be additional charges for functionality in the future.
You can request access to the functionality via GREEN-API support

The connection reports an incoming call with the incoming-call event. It occurs once and contains in event.detail the call ID id, the WhatsApp ID of the other party wid and their name name, if WhatsApp provided the name.

To accept a call, use the accept method of the client, and audio transmission is started after it, in exactly this order (for the reason, see Audio transmission).

const audioElement = document.createElement('audio');

calls.addEventListener('incoming-call', async (event) => {
  const { id, wid, name } = event.detail;
  console.log('Incoming call from:', name || wid, 'Call ID:', id);

  // Show your own incoming call window here;
  // in this example, the call is accepted immediately.
  try {
    await client.accept();
    await calls.startAudioBridge();
    console.log('Call accepted.');
  } catch (error) {
    console.error('Error accepting the call:', error);
  }
});

calls.addEventListener('remote-stream-ready', (event) => {
  audioElement.srcObject = event.detail;
  audioElement.play();
});

Incoming call window#

In the examples, incoming calls are shown in a pop-up window with two buttons — accept and reject.

const incomingCallPortal = document.getElementById('incoming-call-portal');
const incomingCallPhone = document.getElementById('incoming-call-phone');
const acceptCallButton = document.getElementById('acceptCallButton');
const rejectCallButton = document.getElementById('rejectCallButton');

calls.addEventListener('incoming-call', (event) => {
  const { wid, name } = event.detail;

  incomingCallPhone.textContent = name || wid;
  incomingCallPortal.style.display = 'flex';
});

acceptCallButton.addEventListener('click', async () => {
  incomingCallPortal.style.display = 'none';

  await client.accept();
  await calls.startAudioBridge();
});

rejectCallButton.addEventListener('click', async () => {
  incomingCallPortal.style.display = 'none';

  await client.reject();
});

The window must also be hidden when the call ends by itself — on the end-call event: the caller may hang up, and the call may be accepted on another device of the same account. Handling of this event is described in the Handling call states section.

Window markup and styles:

    <div id="incoming-call-portal">
      <section class="incoming-call-modal">
        <section>
          Incoming call: <span id="incoming-call-phone">79836200181</span>
        </section>
        <section>
          <button class="incoming-call-reject" id="rejectCallButton">reject</button>
          <button class="incoming-call-accept" id="acceptCallButton">accept</button>
        </section>
      </section>
    </div>

And CSS

.incoming-call-modal {
    width: 300px;
    height: 100px;

    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    gap: 20px;

    background: white;
    box-shadow: 0 0 10px #000000;
}

.incoming-call-reject {
    border: none;
    background: none;

    width: 100px;
    height: 30px;

    border-radius: 10px;

    color: #e8e8e8;
    background: #c53c3c;
}

.incoming-call-reject:hover {
    cursor: pointer;
    color: white;
    background: #e34242;
}

.incoming-call-accept {
    border: none;
    background: none;

    width: 100px;
    height: 30px;

    border-radius: 10px;

    color: #e8e8e8;
    background: #11911d;
}

.incoming-call-accept:hover {
    cursor: pointer;
    color: white;
    background: #11a41e;
}

The reject method rejects an incoming call, and a conversation that has already been accepted is ended with the hangUp method — see How to end or reject a call.