Events & Real-Time
All broadcast events, channels, payloads, and how to listen for them
Chatify dispatches broadcast events for every real-time interaction. All events implement ShouldBroadcastNow (dispatched synchronously, no queue needed).
Channels
Events are sent on two types of private channels:
| Channel | Format | Scope |
|---|---|---|
| Conversation | private-chatify.conversation.{conversationId} | Events for all participants of a conversation |
| User | private-chatify.user.{userId} | Events targeted at a specific user |
Event reference
MessageSent
Dispatched when a new message is sent.
| Property | Value |
|---|---|
| Channel | chatify.conversation.{conversationId} |
| Event name | MessageSent |
| Payload | Full MessageResource (id, conversation_id, body, attachment, sender, reply_to, forwarded_from, created_at) |
MessageUpdated
Dispatched when a message is edited.
| Property | Value |
|---|---|
| Channel | chatify.conversation.{conversationId} |
| Event name | MessageUpdated |
| Payload | Full MessageResource with updated body and edited_at |
MessageDeleted
Dispatched when a message is deleted.
| Property | Value |
|---|---|
| Channel | chatify.conversation.{conversationId} |
| Event name | MessageDeleted |
| Payload | { id, conversation_id } |
ConversationRead
Dispatched when a user marks a conversation as read.
| Property | Value |
|---|---|
| Channel | chatify.conversation.{conversationId} |
| Event name | ConversationRead |
| Payload | { conversation_id, user_id, read_at } |
ConversationInboxUpdated
Dispatched to update a user's inbox (new message arrived, conversation updated, etc.).
| Property | Value |
|---|---|
| Channel | chatify.user.{userId} |
| Event name | InboxUpdated |
| Payload | Full ConversationResource with last message and unread count |
UserTyping
Dispatched when a user starts or stops typing.
| Property | Value |
|---|---|
| Channel | chatify.conversation.{conversationId} |
| Event name | UserTyping |
| Payload | { conversation_id, user_id, is_typing } |
UserPresenceChanged
Dispatched when a user comes online or goes offline. Sent to each user who shares a conversation with them.
| Property | Value |
|---|---|
| Channel | chatify.user.{audienceUserId} |
| Event name | UserPresenceChanged |
| Payload | { user_id, is_online } |
UserBlockChanged
Dispatched when a user blocks or unblocks another user. Sent to both parties.
| Property | Value |
|---|---|
| Channel | chatify.user.{audienceUserId} |
| Event name | UserBlockChanged |
| Payload | { blocker_id, blocked_user_id, blocked, messaging_blocked_user_ids } |
GroupParticipantsChanged
Dispatched when participants are added, removed, or their roles change in a group.
| Property | Value |
|---|---|
| Channel | chatify.conversation.{conversationId} |
| Event name | GroupParticipantsChanged |
| Payload | { conversation_id, change_type, actor_user_id, target_user_ids, participant_count, participants_preview } |
GroupMembershipRevoked
Dispatched to a user who has been removed from a group. Sent only to the removed user.
| Property | Value |
|---|---|
| Channel | chatify.user.{userId} |
| Event name | GroupMembershipRevoked |
| Payload | { conversation_id, user_id, reason } |
Listening on the frontend
The bundled UI handles all events automatically. If you are building a custom frontend, subscribe to channels using Laravel Echo:
import Echo from 'laravel-echo';
import Pusher from 'pusher-js';
const echo = new Echo({
broadcaster: 'pusher',
key: 'your-pusher-key',
cluster: 'mt1',
forceTLS: true,
authEndpoint: '/api/chatify/v1/broadcasting/auth',
});
// Listen for new messages in a conversation
echo.private(`chatify.conversation.${conversationId}`)
.listen('.MessageSent', (data) => {
console.log('New message:', data);
})
.listen('.UserTyping', (data) => {
console.log('Typing:', data);
})
.listen('.ConversationRead', (data) => {
console.log('Read receipt:', data);
});
// Listen for user-specific events
echo.private(`chatify.user.${userId}`)
.listen('.InboxUpdated', (data) => {
console.log('Inbox updated:', data);
})
.listen('.UserPresenceChanged', (data) => {
console.log('Presence:', data);
});Note the . prefix before event names -- this tells Echo to use the broadcastAs name rather than the fully-qualified class name.
Presence heartbeat
The frontend sends periodic heartbeat requests to track online status:
POST /api/chatify/v1/presence/heartbeatWhen a user closes the tab or navigates away, an offline signal is sent:
POST /api/chatify/v1/presence/offlineThe server then dispatches UserPresenceChanged events to all users who share conversations with the user.
Event summary
| Event | Channel type | Event name | When dispatched |
|---|---|---|---|
MessageSent | Conversation | MessageSent | New message sent |
MessageUpdated | Conversation | MessageUpdated | Message edited |
MessageDeleted | Conversation | MessageDeleted | Message deleted |
ConversationRead | Conversation | ConversationRead | Conversation marked as read |
UserTyping | Conversation | UserTyping | User starts/stops typing |
GroupParticipantsChanged | Conversation | GroupParticipantsChanged | Group members added/removed/role changed |
ConversationInboxUpdated | User | InboxUpdated | Inbox entry needs refresh |
UserPresenceChanged | User | UserPresenceChanged | User comes online/goes offline |
UserBlockChanged | User | UserBlockChanged | User blocked/unblocked |
GroupMembershipRevoked | User | GroupMembershipRevoked | User removed from group |