Skip to content

Realtime events reference

The hub frame keeps one realtime connection to Nexafon for the page and passes events to your code as they happen: a ringing call shows in the embed within about 150 ms of Nexafon learning of it, and reaches your listeners at the same moment.

const stop = Nexafon.on('call.ringing', (call) => {
showBanner(`Call from ${call.callerName || call.callerNumber}`)
})
// stop() removes the listener; Nexafon.off(name, listener) does the same.

The wrappers expose the same events: useNexafonEvent in React and Vue, NexafonService.events(name) in Angular.

Event When Payload
ready A frame finished loading { kind }: 'hub', 'app', 'inbox', 'softphone', 'call-button' or 'call'
session.ready The session started (or was renewed with a new user token) { userId, stores: [{ workspaceId, name }] }
session.error The session could not start, such as an invalid token or no free seat { code, message }: code is the API’s error code
call.ringing A call to this user started ringing Call details
call.answered A call was answered Call details
call.ended A call ended Call details and reason
message.received A customer’s message arrived in a conversation the user can see { workspaceId, conversationId, messageId }
store.changed The user switched store in the store switcher { workspaceId }

Call details are:

Field
workspaceId The workspace (store) of the call
callId The call’s id, as in the API and in webhooks
kind whatsapp_inbound, whatsapp_outbound, internal_direct, internal_group or meeting
callerName The caller’s name, when known
callerNumber The caller’s number (E.164) for WhatsApp calls

Events in the page are for the user in front of it: show a banner, open the order of the caller, update a badge. They only arrive while the page is open and only for what that user may see. For anything your systems must not miss (CRM sync, order processing, reports) use webhooks: they are signed, retried for three days and cover the whole workspace.

Events travel over a versioned, origin-checked postMessage bridge between Nexafon’s frames and the loader; your code only ever sees the payloads above. The realtime WebSocket behind it is internal to the SDK and not part of the public v1 API.