Platform docs
Auth, users, webhooks & more

Events

In most cases, you should rely on the StreamVideo or CallViewModel and its events for building and updating your UI. However for some customizations you'll want to listen to the underlying events that power these objects.

Listening to events

Both the call and streamVideo object allow you to subscribe to events. You can listen to a specific event or all of them. This example shows how to listen to all events.

Task {
    for await event in streamVideo.subscribe() {
        print(event)
    }
}

You can also subscribe for a specific call.

Task {
    let call = streamVideo.call("default", "123")
    for await event in call.subscribe() {
        print(event)
    }
}
Note:

When subscribing to all events either on the client or a call, you will be receiving events of type VideoEvent. VideoEvent is the discriminator object for all websocket events, you should use this to map event payloads to their own type.

Task {
    let call = streamVideo.call("default", "123")
    for await event in call.subscribe() {
        switch event {
        case .typeBlockedUserEvent(let blockedUserEvent):
            print(blockedUserEvent)
        case .typeCallAcceptedEvent(let callAcceptedEvent):
            print(callAcceptedEvent)
        default:
            break
        }
    }
}

Or listen to a specific event

Task {
    let call = streamVideo.call("default", "123")
    for await event in call.subscribe(for: ConnectedEvent.self) {
        print(event)
    }
}

Events

The following events are triggered by the client:

Event Name Description
BlockedUserEvent This event is sent to call participants to notify when a user is blocked on a call, clients can use this event to show a notification. If the user is the current user, the client should leave the call screen as well
CallAcceptedEvent This event is sent when a user accepts a notification to join a call.
CallBroadcastingStartedEvent This event is sent when call broadcasting has started
CallBroadcastingStoppedEvent This event is sent when call broadcasting has stopped
CallCreatedEvent This event is sent when a call is created. Clients receiving this event should check if the ringing field is set to true and if so, show the call screen
CallEndedEvent This event is sent when a call is mark as ended for all its participants. Clients receiving this event should leave the call screen
CallLiveStartedEvent This event is sent when a call is started. Clients receiving this event should start the call.
CallMemberAddedEvent This event is sent when one or more members are added to a call
CallMemberRemovedEvent This event is sent when one or more members are removed from a call
CallMemberUpdatedEvent This event is sent when one or more members are updated
CallMemberUpdatedPermissionEvent This event is sent when one or more members get its role updated
CallNotificationEvent This event is sent to all call members to notify they are getting called
CallReactionEvent This event is sent when a reaction is sent in a call, clients should use this to show the reaction in the call screen
CallRecordingStartedEvent This event is sent when call recording has started
CallRecordingStoppedEvent This event is sent when call recording has stopped
CallRejectedEvent This event is sent when a user rejects a notification to join a call.
CallRingEvent This event is sent to all call members to notify they are getting called
CallSessionEndedEvent This event is sent when a call session ends
CallSessionParticipantJoinedEvent This event is sent when a participant joins a call session
CallSessionParticipantLeftEvent This event is sent when a participant leaves a call session
CallSessionStartedEvent This event is sent when a call session starts
CallUpdatedEvent This event is sent when a call is updated, clients should use this update the local state of the call. This event also contains the capabilities by role for the call, clients should update the own_capability for the current.
ConnectedEvent This event is sent when the WS connection is established and authenticated, this event contains the full user object as it is stored on the server
ConnectionErrorEvent This event is sent when the WS connection fails
CustomVideoEvent A custom event, this event is used to send custom events to other participants in the call.
HealthCheckEvent -
PermissionRequestEvent This event is sent when a user requests access to a feature on a call, clients receiving this event should display a permission request to the user
UnblockedUserEvent This event is sent when a user is unblocked on a call, this can be useful to notify the user that they can now join the call again
UpdatedCallPermissionsEvent This event is sent to notify about permission changes for a user, clients receiving this event should update their UI accordingly
CallTranscriptionStartedEvent This event is sent when call transcription has started
CallTranscriptionStoppedEvent This event is sent when call transcription has stopped
ClosedCaptionEvent This event is sent when a closed caption is available for a participant's speech
CallUserMutedEvent This event is sent when a user is muted by a moderator
ParticipantCountUpdatedEvent This event is sent when the participant count changes
VideoEvent The discriminator object for all websocket events, you should use this to map event payloads to their own type
WSCallEvent This is just a placeholder for all call events
WSClientEvent This is just a placeholder for all client events

Common Event Handling Patterns

Handling Multiple Events

Here's a more complete example of handling multiple event types:

func observeCallEvents(call: Call) {
    Task {
        for await event in call.subscribe() {
            await MainActor.run {
                switch event {
                case .typeCallSessionParticipantJoinedEvent(let e):
                    showToast("\\(e.participant.user.name ?? "Someone") joined")

                case .typeCallSessionParticipantLeftEvent(let e):
                    showToast("\\(e.participant.user.name ?? "Someone") left")

                case .typeCallRecordingStartedEvent:
                    showRecordingIndicator = true

                case .typeCallRecordingStoppedEvent:
                    showRecordingIndicator = false

                case .typeCallReactionEvent(let e):
                    showReaction(e.reaction)

                case .typeCustomVideoEvent(let e):
                    handleCustomEvent(e.custom)

                default:
                    break
                }
            }
        }
    }
}

Cleaning Up Subscriptions

When your view or view controller is deallocated, make sure to cancel any ongoing event subscriptions by storing the Task and cancelling it:

class CallObserver {
    private var eventTask: Task<Void, Never>?

    func startObserving(call: Call) {
        eventTask = Task {
            for await event in call.subscribe() {
                // Handle events
            }
        }
    }

    func stopObserving() {
        eventTask?.cancel()
        eventTask = nil
    }
}
Add Chat to my app: getstream.io/SKILL.md

The fastest way to build with Stream. Start a new project or improve an existing one. Full CLI and documentation integration out of the box.


Ask your agent:

/stream Build me a Social App with Feeds and Moderation.
/stream Any livestream calls running?
/stream Video iOS v1: <Your Question>