---
title: "Getting Started"
canonical_url: "https://apidocs.sportradar.com/resources/virtual-stadium/docs/sdk/gettingStarted"
markdown_url: "https://apidocs.sportradar.com/resources/virtual-stadium/docs/sdk/gettingStarted.md"
last_updated: "2026-04-16T10:19:11Z"
---

# Getting Started

This guide will help you integrate the Virtual Stadium Data SDK into your application and get up and running quickly.

## Overview

To integrate the Virtual Stadium Data SDK:

1. Install and initialize the SDK
2. Authenticate with a JWT token using `LoginManager`
3. Initialize chat channels with `ChatManager`
4. Subscribe to state flows for real-time updates
5. Handle user interactions (send messages, reactions, etc.)

This guide walks you through each step with complete code examples.

***

## Prerequisites

**SDK Version Requirements**

- **Android**: Minimum SDK 23 (Android 6.0)
- **iOS**: Minimum iOS 11.0

**Authentication**

- Valid JWT token for user authentication — see the [JWT Authentication](https://apidocs.sportradar.com/resources/virtual-stadium/docs/gettingStarted/authentication.md) guide for setup instructions
- API key from Virtual Stadium (if applicable)

***

## Step 1: SDK Initialization

The SDK uses Koin for dependency injection and is automatically initialized when you start using any services.

Complete the [Installation & Setup](https://apidocs.sportradar.com/resources/virtual-stadium/docs/sdk/dependencies.md) guide before proceeding.

***

## Step 2: Authentication

Before using any chat functionality, you must authenticate with a JWT token using `LoginManager`.

Monitor the `loginState` flow to track authentication status and handle different login states (LOGGED\_IN, ERROR, LOADING, LOGGED\_OUT).

> **Warning**
>
> All SDK features require successful authentication. Ensure login completes before initializing chat channels.

**Android**

```kotlin
class MainViewModel : ViewModel(), KoinComponent {
    private val loginManager: LoginManager by inject()
    
    fun initialize() {
        // Monitor login state
        loginManager.loginState.collect { loginState ->
            when (loginState.loginStatus) {
                LoginStatus.LOGGED_IN -> {
                    // SDK is ready to use
                    initializeChat()
                }
                LoginStatus.ERROR -> {
                    // Handle login error
                    handleLoginError(loginState.loginError)
                }
                // Handle other states...
            }
        }
        
        // Perform login
        loginManager.login("YOUR_JWT_TOKEN")
    }
}
```

**iOS**

```swift
class MainViewModel: ObservableObject {
    private let loginManager = KoinHelper().getLoginManager()
    @Published var isLoggedIn = false
    
    init() {
        subscribeToLoginState()
    }
    
    private func subscribeToLoginState() {
        loginManager.loginState.subscribe { [weak self] loginState in
            switch loginState?.loginStatus {
            case .loggedIn:
                self?.isLoggedIn = true
                self?.initializeChat()
            case .error:
                self?.handleLoginError(loginState?.loginError)
            default:
                break
            }
        }
    }
    
    func login() {
        loginManager.login(jwtToken: "YOUR_JWT_TOKEN")
    }
}
```

***

## Step 3: Initialize Chat Channel

Once authenticated, create and manage chat channels using `ChatManager`.

Use `getOrAddChannel()` to get an existing channel or create a new one. The method returns a `ChatChannel` instance for message operations.

Subscribe to various state flows:

- **MessagesState** - Chat messages and pagination
- **UserState** - User status (bans, timeouts)
- **ChatSettings** - Channel configuration

**Android**

```kotlin
class ChatViewModel : ViewModel(), KoinComponent {
    private val chatManager: ChatManager
        get() = get()

    val userProvider: UserProvider
        get() = get()

    private val settingsProvider: SettingsProvider
        get() = get()

    private val channel: ChatChannel? = null
    
    val settings: StateFlow<ChatSettings> = settingsProvider.settings

    fun initializeChannel(channelId: String) {
        //Initializing channel and states!"
        channel = chatManager.getOrAddChannel(channelId = channelId, getChannelStats = true)
    }

    fun loadPreviousPage() {
        channel?.loadPreviousPage()
    }

    fun sendMessage(message: String) {
        channel?.sendMessage(message)
    }

    fun replyToMessage(messageId: String, message: String) {
        channel?.replyToMessage(message, messageId)
    }

    fun toggleReactionOnMessage(reaction: ReactionType, message: Message) {
        channel?.toggleReactionOnMessage(message, reaction)
    }

    fun addReaction(reaction: ReactionType, message: Message) {
        channel?.reactToMessage(message, reaction)
    }

    fun reportMessage(messageId: String, reportedSuccessfully: (Boolean) -> Unit) {
        channel?.reportMessage(
            messageId = messageId,
            onSuccess = { reportedSuccessfully(true) },
            onFailure = { reportedSuccessfully(false) },
        )
    }

    fun shareNewBet(
        betPayload: BetPayload,
        showStake: Boolean,
        comment: String,
    ) {
        channel.value?.shareBet(
            betPayload = betPayload,
            comment = comment,
            showStake = showStake,
            onSuccess = {
                //Successfully shared a bet
            },
            onFailure = {
                //Failed to share bet
            },
        )
    }

    fun getAllBetShares() {
        channel?.getAllBetShares()
    }

    fun loadMoreBetShares() {
        channel?.loadMoreMyBetShares()
    }

    fun getMyBetShares() {
        channel?.getMyBetShares()
    }

    fun loadMoreMyBetShares() {
        channel?.loadMoreMyBetShares()
    }

    fun copySharedBet(messageId: String) {
        channel?.copySharedBet(messageId)
    }

    fun filterTags(query: String) {
        channel?.filterTags(query)
    }
    
    fun stopChannel(channelId: String) {
        // Clear channel and states
        chatManager.removeChannel(channelId)
        channel = null
    }

    fun restartChannel() {
        channel?.restart()
    }
}
```

**iOS**

```swift
class ChatViewModel: ObservableObject {
    private let chatManager = KoinHelper().getChatManager()
    private let userProvider = KoinHelper().getUserProvider()
    private let settingsProvider = KoinHelper().getSettingsProvider()
    
    @Published var messagesState: MessagesState?
    @Published var userState: UserState?
    @Published var chatSettings: ChatSettings?
    
    private var channel: ChatChannel?
    
    func initializeChannel(channelId: String) {
        channel = chatManager.getOrAddChannel(
            channelId: channelId, 
            getChannelStats: true
        )
        
        subscribeToStates()
    }
    
    private func subscribeToStates() {
        // Messages state
        channel?.state.subscribe(onCollect: { messagesState in
            self?.messagesState = messagesState
        })
        
        // User state
        userProvider.userState.subscribe(onCollect: { userState in
            self?.userState = userState
        })
        
        // Settings state
        settingsProvider.settings.subscribe(onCollect: { chatSettings in
            self?.chatSettings = chatSettings
        })
    }
}
```

***

## Step 4: Basic Chat Operations

Now you can perform basic chat operations using the `ChatChannel` instance.

Common operations include:

- **Send messages** - Post new messages to the channel
- **React to messages** - Add emoji reactions
- **Load history** - Paginate through previous messages

**Android**

```kotlin
// Send a message
fun sendMessage(text: String) {
    channel?.sendMessage(
        message = text,
        onFailure = {
            // Handle send failure
        }
    )
}

// React to a message
fun reactToMessage(message: Message, reactionType: ReactionType) {
    channel?.toggleReactionOnMessage(message, reactionType)
}

// Load previous messages
fun loadPreviousPage() {
    channel?.loadPreviousPage()
}
```

**iOS**

```swift
// Send a message
func sendMessage(text: String) {
    channel?.sendMessage(
        message: text,
        onFailure: {
            // Handle send failure
        }
    )
}

// React to a message
func reactToMessage(message: Message, reactionType: ReactionType) {
    channel?.toggleReactionOnMessage(message: message, reactionType: reactionType)
}

// Load previous messages
func loadPreviousPage() {
    channel?.loadPreviousPage()
}
```

***

## Integration Flow

Here's the recommended integration flow:

1. **Initialize SDK** → SDK auto-initializes with Koin dependency injection
2. **Login** → Authenticate with JWT token using `LoginManager`
3. **Monitor Login State** → Wait for successful authentication (LOGGED\_IN status)
4. **Initialize Chat Channel** → Create/get channel with `ChatManager.getOrAddChannel()`
5. **Subscribe to States** → Observe messages, user status, and settings flows
6. **Handle User Interactions** → Send messages, reactions, share bets, etc.
7. **Manage Lifecycle** → Stop/resume channels based on app lifecycle
8. **Cleanup** → Destroy channels and logout when done

***

## Next Steps

### SDK Services

Review all available services and their purposes.

[View Services](https://apidocs.sportradar.com/resources/virtual-stadium/docs/sdk/intro.md)

### Authentication

Learn about login and user state management.

[View Auth Docs](https://apidocs.sportradar.com/resources/virtual-stadium/docs/sdk/userAuthentication.md)

### Chat Features

Explore messaging, reactions, and bet sharing.

[View Chat Docs](https://apidocs.sportradar.com/resources/virtual-stadium/docs/sdk/chatChannel.md)
