> ## Documentation Index
> Fetch the complete documentation index at: https://developer.suki.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Session Events & Delegates

> Learn how to use the session events and delegates to handle the session lifecycle in the mobile SDK

<div className="quick-summary-wrapper">
  <div className="quick-summary-header">
    <span className="quick-summary-icon" aria-hidden="true" />

    <span className="quick-summary-title">Quick summary</span>
  </div>

  <div className="quick-summary-content">
    The SDK uses a delegate pattern to broadcast important events during a session's lifecycle. By conforming to the `SukiAmbientSessionDelegate` protocol and implementing `sukiAmbient(sessionEvent:for:)`, you receive real-time updates about session state changes.

    <br />

    <br />

    Use a switch statement to handle specific events like `.started`, `.paused`, `.suggestionsGenerated`, or `.convertedToOfflineSession` to update your UI or handle errors accordingly.
  </div>

  <div className="quick-summary-footer">
    <span className="quick-summary-footer-icon" aria-hidden="true" />

    <span className="quick-summary-footer-text">Last updated:</span>
    <span className="quick-summary-footer-date">June 2026</span>
  </div>
</div>

The SDK uses a delegate pattern to broadcast important events that occur during a session's lifecycle. By conforming to the `SukiAmbientSessionDelegate` protocol, you can receive real-time updates and respond to state changes in your application, such as updating your UI or handling errors.

**What will you learn?**

In this guide, you will learn how to:

* Use the `SukiAmbientSessionDelegate` protocol.
* Implement the `sukiAmbient(sessionEvent:for:)` method.
* Handle the events that are relevant to your application using a switch statement.

## How to implement the session delegate

#### 1. Conform to the protocol

First, declare that your class conforms to the `SukiAmbientSessionDelegate` protocol. You must also pass an **instance** of this delegate class when you initialize the SDK.

#### 2. Implement the delegate method

Next, implement the `sukiAmbient(sessionEvent:for:)` method. The SDK calls this method every time a new session event occurs, providing the event type and the associated `recordingId`.

Use a **switch statement** within this method to handle the events that are relevant to your application.

<CodeGroup>
  ```swift Swift theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}}
  extension YourViewController: SukiAmbientSessionDelegate {
      func sukiAmbient(sessionEvent event: SukiAmbientCore.SessionEvent, for recordingId: SukiAmbientCore.RecordingId) {
          // This method receives all session events for a given recording ID.
          print("Received event: \(event) for recording ID: \(recordingId)")

          // Use a switch statement to handle specific events.
          switch event {
          case .started:
              // Update your UI to show that recording has started.
              break
          case .suggestionsGenerated:
              // Notify the user that their note is ready.
              break
          case .convertedToOfflineSession:
              // Inform the user about the network issue.
              break
          // Handle other cases as needed for your app's logic.
          default:
              break
          }
      }
  }
  ```
</CodeGroup>

## Available session events

The `SessionEvent` enum provides the following cases, which are grouped by category for clarity.

#### Recording lifecycle

<ResponseField name="SessionEvent" type="enum">
  Recording lifecycle events for ambient sessions.

  <Expandable title="cases">
    <ResponseField name="started" type="case">
      Triggered when the recording starts.
    </ResponseField>

    <ResponseField name="resumed" type="case">
      Triggered when the recording resumes after being paused.
    </ResponseField>

    <ResponseField name="paused" type="case">
      Triggered when the recording is paused.
    </ResponseField>

    <ResponseField name="ended" type="case">
      Triggered when the recording ends.
    </ResponseField>

    <ResponseField name="cancelled" type="case">
      Triggered when the recording is cancelled.
    </ResponseField>
  </Expandable>
</ResponseField>

#### Content generation

<ResponseField name="SessionEvent" type="enum">
  Content generation events for note suggestions.

  <Expandable title="cases">
    <ResponseField name="suggestionGenerationInProgress" type="case">
      Triggered when suggestion generation begins.
    </ResponseField>

    <ResponseField name="suggestionsGenerated" type="case">
      Triggered when suggestions are successfully generated.
    </ResponseField>

    <ResponseField name="suggestionsGenerationFailed" type="case">
      Triggered when suggestion generation fails.
    </ResponseField>
  </Expandable>
</ResponseField>

#### Offline mode & uploading

<ResponseField name="SessionEvent" type="enum">
  Offline mode and audio upload events.

  <Expandable title="cases">
    <ResponseField name="convertedToOfflineSession" type="case">
      Triggered when session is converted to offline mode.
    </ResponseField>

    <ResponseField name="pendingOfflineUpload" type="case">
      Triggered when offline audio is pending upload.
    </ResponseField>

    <ResponseField name="preparingOfflineUpload" type="case">
      Triggered when preparing offline audio for upload.
    </ResponseField>

    <ResponseField name="uploadingAudio" type="case">
      Triggered when audio upload is in progress.
    </ResponseField>

    <ResponseField name="audioUploaded" type="case">
      Triggered when audio is successfully uploaded.
    </ResponseField>

    <ResponseField name="audioUploadFailed" type="case">
      Triggered when audio upload fails.
    </ResponseField>

    <ResponseField name="audioUploadAllRetryFailed" type="case">
      Triggered when all audio upload retry attempts fail.
    </ResponseField>

    <ResponseField name="processingUpload" type="case">
      Triggered when uploaded audio is being processed.
    </ResponseField>

    <ResponseField name="processingUploadFailed" type="case">
      Triggered when upload processing fails.
    </ResponseField>
  </Expandable>
</ResponseField>

#### Audio interruptions

<ResponseField name="SessionEvent" type="enum">
  Audio interruption events during recording.

  <Expandable title="cases">
    <ResponseField name="audioInterruptionStarted" type="case">
      Triggered when audio interruption begins (e.g., phone call).
    </ResponseField>

    <ResponseField name="audioInterruptionEnded" type="case">
      Triggered when audio interruption ends.
    </ResponseField>
  </Expandable>
</ResponseField>

#### All available session events cases

Below is the complete list of all available session events cases:

<CodeGroup>
  ```swift Swift theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}}
  public enum SessionEvent {
      case started
      case resumed
      case paused
      case ended
      case cancelled
      case suggestionGenerationInProgress
      case suggestionsGenerated
      case suggestionsGenerationFailed
      case audioInterruptionStarted
      case audioInterruptionEnded
      case convertedToOfflineSession
      case pendingOfflineUpload
      case preparingOfflineUpload
      case uploadingAudio
      case audioUploadFailed
      case audioUploadAllRetryFailed
      case audioUploaded
      case processingUpload
      case processingUploadFailed
      case clearingBufferredAudio
      case clearedBufferredAudio
      case audioBufferFilled(withPercentage: Double) // [!code ++] New in v2.4.0
  }
  ```
</CodeGroup>

## FAQs

<AccordionGroup>
  <Accordion title="Do I have any other events to listen to?">
    Yes, you can listen to the following events:

    * `sessionEvent`
    * `recordingId`
  </Accordion>

  <Accordion title="Can I create a new case inside the `SessionEvent` enum?">
    No, you cannot create a new case inside the `SessionEvent` enum. You must use the existing cases.
  </Accordion>

  <Accordion title="Why do we need so many cases for the `SessionEvent` enum?">
    We have so many cases because we want to be able to handle all the possible events that can occur during a session.
  </Accordion>
</AccordionGroup>
