Handling call states#
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
CallsConnection is an EventTarget, and the entire call lifecycle can be seen from its events. Build the interface based on the state that arrives in the connection, not on the results of the methods you call: a call can end without your participation — for example, it can be accepted on another device of the same account.
The state event#
The state event arrives on every change of the call state, as well as right after connecting and reconnecting. Because of this, a page reloaded in the middle of a conversation immediately shows the correct state.
event.detail.state— one of the values:idle(no call),inc-call(an incoming call has arrived),out-call(an outgoing call is in progress),on-call(the call is established);event.detail.info— the call description for the states in which there is a call:id(call ID),wid(WhatsApp ID of the other party) andname(the name, if WhatsApp provided it).
calls.addEventListener('state', (event) => {
const { state, info } = event.detail;
console.log('Call state:', state, info ?? '');
// for example, show "Calling..." for 'out-call'
// and the accept/reject buttons for 'inc-call'
});
You can also read the current state without waiting for the event — in calls.state.state. The client.getCallState() method returns the call state via REST if you need it outside the connection.
Who is on the other side#
The wid field contains either 79991234567@c.us — if you have the phone number of the other party, or 1062110180230@lid — if there is no number. The info.name field is filled in only when WhatsApp has a profile name (pushname), and for a party that comes with @lid, it is usually missing.
To show a name instead of digits, look up the contact by both addresses: the getContacts method returns both id and lid for the same person, so the contact can be found by either of them.
The end-call event#
The end-call event is sent after the call has ended. The event.detail.reason field tells what exactly happened:
call-ended— the call has been ended on the server side: the other party ended the call, the timeout expired, or the call was accepted on another device.connection-lost— the connection to the server was lost during the call and could not be restored.
For call-ended, the event may also contain the cause field — the server's word on what happened. Known values: hangup, timeout, accepted_elsewhere (the call was accepted on another device of the same account, for example on the phone), rejected_elsewhere, no-media, connect-timeout, instance-gone, rejected:<reason>. The list is open, so it is better to display an unknown value as is instead of discarding it. If the server has not specified a reason, there is no cause field; with connection-lost, it is never present.
calls.addEventListener('end-call', (event) => {
const { reason, cause } = event.detail;
if (reason === 'connection-lost') {
console.log('Call ended: connection to the server was lost.');
} else if (cause === 'accepted_elsewhere') {
console.log('Call accepted on another device.');
} else if (cause === 'timeout') {
console.log('Call ended due to a timeout.');
} else {
console.log('Call ended.', cause ? `Reason: ${cause}` : '');
}
// Return the interface to its initial state here
});
The library turns off audio transmission by itself when the call ends, see Audio transmission.
All connection events#
| Event | What it contains |
|---|---|
connect | the connection is established |
disconnect | the connection is lost, the reason is in detail.reason |
error | an error, the text is in detail.message |
state | the call state: detail.state and detail.info |
incoming-call | an incoming call has arrived: detail with the id, wid, name fields |
local-stream-ready | the stream of your microphone is ready |
remote-stream-ready | the stream of the other party is ready |
end-call | the call has ended: detail.reason and detail.cause |