AISARAISAR

Realtime events over WebSocket

Which WebSocket channels and events are available when connecting to AISAR Reverb directly, and how they relate to webhooks.

In addition to webhooks (see the Webhooks guide), AISAR broadcasts a subset of events in real time over a Pusher-compatible WebSocket server (Reverb). This is useful for custom frontends that need an instant reaction to changes (typing indicators, counters, conversation updates) without polling the REST API.

Webhooks and WebSocket are complementary, not interchangeable. Webhooks are the authoritative, signed, retried delivery channel for server-side integration. WebSocket is a fast but best-effort channel for UI: events missed during a disconnect are not replayed — re-fetch state via REST after reconnecting.

Channels

ChannelFormatPurpose
Companyprivate-company.{companyId}Conversation/message/contact/deal events for the whole team
Userprivate-user.{userId}Personal events: counters, notifications
Channelprivate-channel.{channelId}Channel status, contact/group sync
Conversationprivate-conversation.{conversationId}Typing indicators and contact presence

Active events

Messages (channel: company)

Broadcast: message.created, message.updated, message.deleted, message.read, message.status.updated, message.reaction.updated. Event payload:

json
{
  "conversation_id": 750,
  "thread_id": 750,
  "message": { "...MessageResource..." }
}

Conversations (channel: company)

Broadcast: conversation.created, conversation.updated, conversation.closed, conversation.reopened, conversation.assigned, conversation.unassigned.

Base payload
{ "conversation_id": 750 }
For assigned / unassigned — additionally
{
  "conversation_id": 750,
  "action": "added",
  "participant": { "id": 1, "member_type": "user", "member_id": 5, "role": "agent" }
}

Counters (channel: user)

chat.counters.updated refreshes the conversation filter badges. Fires on any counter-affecting event (message.created/deleted/read, conversation.created/updated/closed/reopened/assigned/unassigned) — recomputed personally for every user in the company.

json
{
  "counters": {
    "all": 42,
    "awaiting": 5,
    "unread": 8,
    "assigned": 15,
    "unassigned": 2,
    "archived": 18
  }
}

Notifications (channel: user)

notification.created — a new personal notification for the user.

Messaging channels (channel: channel)

channel.realtime.update — a single event routed by payload.type: channel_status (channel status change), contacts_synced/contacts_updated, groups_synced/group_updated/group_participants_updated, history_sync_progress.

Deals and AI agents (channel: company)

deal.updated — a deal changed. ai-pending-action.updated — the status of an AI agent action awaiting operator confirmation changed (action: "created" | "approved" | "rejected"), payload { event_id, conversation_id, action }.

Broadcast-only events (not delivered as a webhook)

Some events are broadcast over WebSocket only, without a corresponding outbound HTTP webhook: contact.outbound_eligibility_updated (a contact's eligibility for outbound/WhatsApp calls, payload {contact_id, channel_id} or a variant with contact_account_id + call{...}) and nudges.updated (an in-app nudge banner, payload {company_id}). If your integration needs these specific signals, subscribe to them over WebSocket — no webhook fires for them.

Reliability

  • Broadcast events raised inside a database transaction are only sent after it commits — you will never see an event for an entity that was then rolled back.
  • Delivery is synchronous (not queued) — latency is minimal, but events aren't buffered for the duration of a disconnect.
  • The unread counter calculation depends on the company's shared_read_receipts setting: when true it uses the maximum last_read_at across all users, when false each user's individual last_read_at.

AISAR connects to Reverb over a Pusher-compatible protocol (wsHost: api.aisar.app, TLS port 443, authEndpoint: https://api.aisar.app/broadcasting/auth). Subscribing to private channels (private-*) requires token authorization at /broadcasting/auth and goes through a per-channel ACL — a user from one company cannot subscribe to another company's channel. Contact AISAR support for the connection credentials (app key, etc.).