---
title: API Reference
url: https://docs.kaltura.com/docs/conversational-agents/agentic-avatars-sdk/client-sdk-api-reference
---

## API Reference

Complete reference for all Kaltura Avatar Client SDK methods, properties, and events.

### Constructor

#### `new KalturaAvatarSession(config?)`

Creates a new avatar session instance.

**Signature:**

```typescript
new KalturaAvatarSession(config?: AvatarConfig)
// Legacy (deprecated): new KalturaAvatarSession(apiKey?: string, config?: AvatarConfig)
```

**Configuration Options:**

```typescript
interface AvatarConfig {
  apiKey?: string; // Your Kaltura Session (KS). Required for FE-only flow; omit for BE/FE split.
  baseUrl?: string; // Avatar API root URL (e.g., https://api.avatar.us.kaltura.ai/). Defaults to https://api.avatar.us.kaltura.ai/.
  catalogUrl?: string; // Base URL for Catalog Service. Defaults to baseUrl if not provided.
  retryConfig?: RetryConfig; // Retry configuration
  logLevel?: 'debug' | 'info' | 'warn' | 'error'; // Default: 'info'
}

interface RetryConfig {
  maxAttempts: number; // Max retry attempts
  initialDelayMs: number; // Initial delay in ms
  maxDelayMs: number; // Max delay in ms
  backoffMultiplier: number; // Exponential backoff multiplier
}
```

> **Recommended Usage**
>
> Pass configuration as a single object for cleaner API:

```typescript
const session = new KalturaAvatarSession({
  apiKey: 'your-kaltura-session', // optional, for FE-only flow
  baseUrl: 'https://api.avatar.us.kaltura.ai/',
  logLevel: 'debug',
});
```

> **Deprecation Notice**
>
> Passing `apiKey` as the first parameter is deprecated:

```typescript
// Deprecated (still works, but shows warning)
const session = new KalturaAvatarSession('your-api-key', { baseUrl: '...' });

// Recommended
const session = new KalturaAvatarSession({ apiKey: 'your-api-key', baseUrl: '...' });
```

**Examples:**

```typescript
// FE-Only: SDK creates the session (with apiKey in config)
const session = new KalturaAvatarSession({
  apiKey: 'your-kaltura-session',
  baseUrl: 'https://api.avatar.us.kaltura.ai/',
  logLevel: 'info',
  retryConfig: {
    maxAttempts: 3,
    initialDelayMs: 500,
    maxDelayMs: 5000,
    backoffMultiplier: 2,
  },
});

// Backend-Created: Backend creates session, FE displays (no apiKey)
const session = new KalturaAvatarSession({
  baseUrl: 'https://api.avatar.us.kaltura.ai/',
  logLevel: 'info',
});
// Then use initSession() with backend-provided credentials
```

### Session Methods

#### `createSession(options)`

Create a new avatar session and establish WebRTC connection.

**Parameters:**

```typescript
interface CreateSessionOptions {
  visualId?: string; // ID of the visual to use
  voiceId?: string; // Optional - ID of the voice for TTS
  language?: TTSLanguage; // Optional - TTS language code (e.g., 'en', 'es', 'ja')
  videoContainerId?: string; // Optional - ID of div to auto-attach video
  /** @deprecated Use `visualId` instead. Will be removed in a future major version. */
  avatarId?: string;
}
```

| Parameter | Type | Required | Description |
|---|---|---|---|
| `visualId` | string | Yes | ID of the visual to use |
| `voiceId` | string | No | Voice ID for TTS |
| `language` | TTSLanguage | No | TTS language code (e.g., `'en'`, `'es'`) |
| `videoContainerId` | string | No | DOM element ID for auto-attaching video |

> **Deprecation Notice**
>
> `avatarId` is deprecated in favor of `visualId`. It still works but will log a console warning. It will be removed in a future major version.

**Returns:** `Promise<void>`

**Example:**

```typescript
// With auto-attach
await session.createSession({
  visualId: 'visual-123',
  voiceId: 'voice-456',
  language: 'en',
  videoContainerId: 'avatar-container',
});

// Without auto-attach
await session.createSession({
  visualId: 'visual-123',
  voiceId: 'voice-456',
});
```

**What it does:**

1. Initializes the backend client
2. Retrieves WHEP URL and TURN server configuration
3. Establishes WebRTC connection
4. Starts automatic keep-alive (every 10 seconds)
5. Attaches video if `videoContainerId` is provided

---

#### `initSession(session, options?)`

Initialize a pre-created session from your backend. Use this when your backend creates the session (recommended for production).

**Parameters:**

```typescript
interface InitSessionParams {
  sessionId: string; // Required - from backend's create response
  token: string; // Required - JWT token from backend
}

interface InitSessionOptions {
  videoContainerId?: string; // Optional - ID of div to auto-attach video
}
```

**Returns:** `Promise<void>`

**Example:**

```typescript
// Get session credentials from your backend
const { sessionId, token } = await fetch('/api/create-avatar-session').then(
  (r) => r.json()
);

// Create SDK instance WITHOUT apiKey (backend already created session)
const session = new KalturaAvatarSession({
  baseUrl: 'https://api.avatar.us.kaltura.ai/',
});

// Initialize with backend-provided credentials
await session.initSession(
  { sessionId, token },
  { videoContainerId: 'avatar-container' }
);

// SDK is now ready to use
await session.sayText('Hello from backend-created session!');
```

**When to use:**

- Your backend creates the session and provides `sessionId` and `token`
- For production applications (keeps Kaltura Session secure on server)
- When you need server-side control and validation

**What it does:**

1. Injects the JWT token from backend
2. Retrieves WHEP URL and TURN server configuration
3. Establishes WebRTC connection
4. Starts automatic keep-alive (every 10 seconds)
5. Attaches video if `videoContainerId` is provided

**Comparison with `createSession()`:**

| Aspect | createSession | initSession |
|---|---|---|
| **Who creates session** | SDK (using apiKey) | Backend server |
| **apiKey needed** | Yes | No |
| **Use case** | Demos, prototypes | Production apps |
| **Security** | KS in client | KS on server |

---

#### `attachAvatar(containerId)`

Attach avatar video to a container div by creating a video element inside it.

**Parameters:**

| Parameter | Type | Required | Description |
|---|---|---|---|
| `containerId` | `string` | Yes | ID of the div element |

**Returns:** `void`

**Example:**

```typescript
session.attachAvatar('avatar-container');
```

**HTML:**

```html
<div id="avatar-container" style="width: 512px; height: 512px;"></div>
```

**Generated video element:**

- `autoplay` and `playsinline` attributes
- Width and height set to 100%
- Appropriate styling for fullscreen display

---

#### `sayText(text, turnId?, isFinal?)`

Send text for the avatar to speak using text-to-speech.

**Parameters:**

| Parameter | Type | Required | Description |
|---|---|---|---|
| `text` | `string` | Yes | Text for the avatar to speak |
| `turnId` | `string` | Optional | Unique identifier for this speech turn. Auto-generated if not provided. |
| `isFinal` | `boolean` | Optional | Whether this is the final chunk (default: true). Use false for LLM streaming. |

**Returns:** `Promise<void>`

**Examples:**

```typescript
// Simple usage (auto-generates turnId)
await session.sayText('Hello, how are you doing today?');

// With explicit turn tracking
const turnId = `turn-${Date.now()}`;
await session.sayText('Hello!', turnId, true);

// LLM streaming support (streaming chunks from LLM)
const streamTurnId = `turn-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
await session.sayText('Hello, ', streamTurnId, false); // More chunks coming
await session.sayText('how are you?', streamTurnId, true); // Final chunk
```

**Parameters explained:**

- **`turnId`**: Unique identifier to track which speech turn this text belongs to. Useful for correlating avatar speech with your application state. Use the same `turnId` for all chunks of a single turn.
- **`isFinal`**: For simple use cases, always use `true`. For LLM streaming where text arrives in chunks, use `false` for intermediate chunks and `true` for the final one.

---

#### `sayAudio(audioFile, turnId, duration)`

Send an audio file for the avatar to speak.

**Parameters:**

| Parameter | Type | Required | Description |
|---|---|---|---|
| `audioFile` | `File \| Blob` | Yes | MP3 file at 44.1 kHz |
| `turnId` | `string` | Yes | Unique identifier for this speech turn |
| `duration` | `number` | Yes | Duration of the audio in seconds |

**Returns:** `Promise<void>`

**Example:**

```typescript
// Get duration via WebAudio API
async function getAudioDuration(file: File): Promise<number> {
  const arrayBuffer = await file.arrayBuffer();
  const audioCtx = new AudioContext();
  const decoded = await audioCtx.decodeAudioData(arrayBuffer);
  await audioCtx.close();
  return decoded.duration;
}

const audioFile = new File([audioBlob], 'speech.mp3', { type: 'audio/mpeg' });
const duration = await getAudioDuration(audioFile);
const turnId = `turn-${Date.now()}`;
await session.sayAudio(audioFile, turnId, duration);
```

---

#### `interrupt()`

Interrupt the avatar's current speech.

**Parameters:** None

**Returns:** `Promise<void>`

**Example:**

```typescript
await session.interrupt();
```

---

#### `endSession()`

End the session and cleanup resources.

**Parameters:** None

**Returns:** `Promise<void>`

**Example:**

```typescript
await session.endSession();
```

**What it does:**

- Stops the automatic keep-alive interval
- Disconnects the WebRTC connection
- Ends the session on the backend
- Cleans up all resources

---

### State Methods

#### `getSessionId()`

Get the current session ID.

**Returns:** `string | null`

**Example:**

```typescript
const sessionId = session.getSessionId();
console.log('Session ID:', sessionId);
```

---

#### `getSessionState()`

Get current session state.

**Returns:** `SessionState`

**Possible values:**

- `'IDLE'` - Not yet created
- `'CREATING'` - Session being created
- `'READY'` - Session ready for use
- `'ENDED'` - Session ended
- `'ERROR'` - Error occurred

**Example:**

```typescript
const state = session.getSessionState();
console.log('Session state:', state);
```

---

#### `getConnectionState()`

Get current WebRTC connection state.

**Returns:** `ConnectionState`

**Possible values:**

- `'DISCONNECTED'` - Not connected
- `'CONNECTING'` - Connection in progress
- `'CONNECTED'` - Connected and streaming
- `'FAILED'` - Connection failed
- `'CLOSED'` - Connection closed

**Example:**

```typescript
const connState = session.getConnectionState();
console.log('Connection state:', connState);
```

---

### Event Methods

#### `on(event, callback)`

Register event handlers.

**Parameters:**

| Parameter | Type | Required | Description |
|---|---|---|---|
| `event` | `SessionEvent` | Yes | Event name |
| `callback` | `Function` | Yes | Event handler function |

**Returns:** `void`

**Available Events:**

- `'stateChange'` - Session state changed
- `'connectionChange'` - WebRTC connection state changed
- `'error'` - Error occurred
- `'speakingStart'` - Avatar started speaking
- `'speakingEnd'` - Avatar stopped speaking

##### `'stateChange'`

Fired when session state changes.

```typescript
session.on('stateChange', (state: SessionState) => {
  console.log('Session state:', state);
});
```

##### `'connectionChange'`

Fired when WebRTC connection state changes.

```typescript
session.on('connectionChange', (state: ConnectionState) => {
  console.log('Connection state:', state);
});
```

##### `'error'`

Fired when an error occurs.

```typescript
session.on('error', (error: AvatarError) => {
  console.error('Error:', error.message, error.code);
});
```

##### `'speakingStart'`

Fired when the avatar starts speaking.

```typescript
session.on('speakingStart', () => {
  console.log('Avatar started speaking');
  // Update UI to show speaking state
});
```

##### `'speakingEnd'`

Fired when the avatar stops speaking.

```typescript
session.on('speakingEnd', () => {
  console.log('Avatar stopped speaking');
  // Update UI to show idle state
});
```

---

### TypeScript Types

#### TTS Languages

```typescript
import { TTSLanguages, TTSLanguage } from '@unisphere/models-sdk-js';

// TTSLanguages is a constant object with all supported language codes:
// ENGLISH: 'en', JAPANESE: 'ja', CHINESE: 'zh', GERMAN: 'de', HINDI: 'hi',
// FRENCH: 'fr', KOREAN: 'ko', PORTUGUESE: 'pt', ITALIAN: 'it', SPANISH: 'es',
// INDONESIAN: 'id', DUTCH: 'nl', TURKISH: 'tr', FILIPINO: 'fil', POLISH: 'pl',
// SWEDISH: 'sv', BULGARIAN: 'bg', ROMANIAN: 'ro', ARABIC: 'ar', CZECH: 'cs',
// GREEK: 'el', FINNISH: 'fi', CROATIAN: 'hr', MALAY: 'ms', SLOVAK: 'sk',
// DANISH: 'da', TAMIL: 'ta', UKRAINIAN: 'uk', RUSSIAN: 'ru', HUNGARIAN: 'hu',
// NORWEGIAN: 'no', VIETNAMESE: 'vi'

// TTSLanguage is the union type of all language code values
type TTSLanguage = 'en' | 'ja' | 'zh' | 'de' | ... ; // all 33 codes
```

#### Enums

```typescript
enum SessionState {
  IDLE = 'IDLE',
  CREATING = 'CREATING',
  READY = 'READY',
  ENDED = 'ENDED',
  ERROR = 'ERROR',
}

enum ConnectionState {
  DISCONNECTED = 'DISCONNECTED',
  CONNECTING = 'CONNECTING',
  CONNECTED = 'CONNECTED',
  FAILED = 'FAILED',
  CLOSED = 'CLOSED',
}

enum AvatarErrorCode {
  INVALID_STATE = 'INVALID_STATE',
  API_REQUEST_FAILED = 'API_REQUEST_FAILED',
  RTC_CONNECTION_FAILED = 'RTC_CONNECTION_FAILED',
  INVALID_CONFIGURATION = 'INVALID_CONFIGURATION',
  SESSION_NOT_FOUND = 'SESSION_NOT_FOUND',
  UNAUTHORIZED = 'UNAUTHORIZED',
}
```

#### Error Interface

```typescript
class AvatarError extends Error {
  code: AvatarErrorCode;
  message: string;
  details?: any;
}
```

---

### Complete Examples

#### Pattern 1: FE-Only (SDK Creates Session)

```typescript
import { KalturaAvatarSession, SessionState, ConnectionState, AvatarError, AvatarErrorCode } from '@unisphere/models-sdk-js';

async function runAvatarFEOnly() {
  // Create instance with apiKey in config
  const session = new KalturaAvatarSession({
    apiKey: 'your-kaltura-session',
    baseUrl: 'https://api.avatar.us.kaltura.ai/',
    logLevel: 'info',
  });

  // Event listeners
  session.on('stateChange', (state: SessionState) => {
    console.log('State:', state);
  });

  session.on('error', (error: AvatarError) => {
    console.error('Error:', error.code, error.message);
  });

  try {
    // Create session (SDK creates it using apiKey)
    await session.createSession({
      visualId: 'visual-123',
      voiceId: 'voice-456',
      language: 'en',
      videoContainerId: 'avatar-container',
    });

    console.log('Session ID:', session.getSessionId());

    // Say text
    await session.sayText('Hello from Kaltura Avatar!');

    // Wait...
    await new Promise((r) => setTimeout(r, 5000));

    // End session
    await session.endSession();
  } catch (error) {
    console.error('Failed:', error);
  }
}
```

#### Pattern 2: Backend-Created (Recommended for Production)

```typescript
import { KalturaAvatarSession, SessionState, AvatarError } from '@unisphere/models-sdk-js';

async function runAvatarBECreated() {
  // Get session from your backend
  const { sessionId, token } = await fetch('/api/create-avatar-session').then(
    (r) => r.json()
  );

  // Create instance WITHOUT apiKey (no need, backend created session)
  const session = new KalturaAvatarSession({
    baseUrl: 'https://api.avatar.us.kaltura.ai/',
    logLevel: 'info',
  });

  // Event listeners
  session.on('stateChange', (state: SessionState) => {
    console.log('State:', state);
  });

  session.on('error', (error: AvatarError) => {
    console.error('Error:', error.code, error.message);
  });

  try {
    // Initialize with backend-provided credentials
    await session.initSession(
      { sessionId, token },
      { videoContainerId: 'avatar-container' }
    );

    console.log('Session ID:', session.getSessionId());

    // Say text
    const turnId = `turn-${Date.now()}`;
    await session.sayText('Hello from backend-created session!', turnId, true);

    // Wait...
    await new Promise((r) => setTimeout(r, 5000));

    // End session
    await session.endSession();
  } catch (error) {
    console.error('Failed:', error);
  }
}
```

### Next Steps

- **[Catalog Service](./client-sdk-catalog)** - Browse available visuals and voices
- **[State Management](./client-sdk-state-management)** - Learn about states and events
- **[Error Handling](./client-sdk-error-handling)** - Handle errors gracefully
- **[Advanced Usage](./client-sdk-advanced)** - Custom ICE servers and more
