Skip to main content

API Examples

Complete examples showing how to use the Control API.

Basic Flow

1. Create Session → 2. Init Client → 3. Use Avatar → 4. End Session

const BASE_URL = 'https://api.avatar.us.kaltura.ai/v1/avatar-session';
const KS = process.env.AVATAR_KS;

// Step 1: Create session
const createResponse = await fetch(`${BASE_URL}/create`, {
method: 'POST',
headers: {
Authorization: `KS ${KS}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
visualConfig: { avatarId: 'avatar-123' },
voiceConfig: { id: 'voice-456' },
}),
});

const { sessionId, token } = await createResponse.json();

// Step 2: Init client
const initResponse = await fetch(`${BASE_URL}/${sessionId}/init-client`, {
method: 'POST',
headers: {
Authorization: `Bearer ${token}`,
},
});

const { whepUrl, turn } = await initResponse.json();

// Step 3: Make avatar speak
await fetch(`${BASE_URL}/${sessionId}/say-text`, {
method: 'POST',
headers: {
Authorization: `Bearer ${token}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
text: 'Hello from Kaltura Avatar!',
}),
});

// Step 4: End session
await fetch(`${BASE_URL}/${sessionId}/end`, {
method: 'POST',
headers: {
Authorization: `Bearer ${token}`,
},
});

Complete Backend Implementation

Express Server

import express from 'express';
import fetch from 'node-fetch';
import cors from 'cors';

const app = express();
app.use(cors());
app.use(express.json());

const KS = process.env.AVATAR_KS;
const BASE_URL = 'https://api.avatar.us.kaltura.ai/v1/avatar-session';

// In-memory session storage (use database in production)
const sessions = new Map();

// Create session endpoint
app.post('/api/avatar/create-session', async (req, res) => {
try {
const { avatarId, voiceId } = req.body;

const response = await fetch(`${BASE_URL}/create`, {
method: 'POST',
headers: {
Authorization: `KS ${KS}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
visualConfig: { avatarId },
voiceConfig: voiceId ? { id: voiceId } : undefined,
}),
});

if (!response.ok) {
throw new Error(`API error: ${response.status}`);
}

const data = await response.json();

// Store session
sessions.set(data.sessionId, {
token: data.token,
createdAt: new Date(),
avatarId,
voiceId,
});

res.json({
sessionId: data.sessionId,
token: data.token,
});
} catch (error) {
console.error('Create session error:', error);
res.status(500).json({ error: 'Failed to create session' });
}
});

// Say text endpoint
app.post('/api/avatar/say-text', async (req, res) => {
try {
const { sessionId, token, text } = req.body;

// Validate session exists
if (!sessions.has(sessionId)) {
return res.status(404).json({ error: 'Session not found' });
}

// Validate text
if (!text || text.length === 0) {
return res.status(400).json({ error: 'Text is required' });
}

if (text.length > 1000) {
return res.status(400).json({ error: 'Text too long' });
}

const response = await fetch(`${BASE_URL}/${sessionId}/say-text`, {
method: 'POST',
headers: {
Authorization: `Bearer ${token}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ text }),
});

if (!response.ok) {
throw new Error(`API error: ${response.status}`);
}

const data = await response.json();
res.json(data);
} catch (error) {
console.error('Say text error:', error);
res.status(500).json({ error: 'Failed to say text' });
}
});

// Interrupt endpoint
app.post('/api/avatar/interrupt', async (req, res) => {
try {
const { sessionId, token } = req.body;

if (!sessions.has(sessionId)) {
return res.status(404).json({ error: 'Session not found' });
}

const response = await fetch(`${BASE_URL}/${sessionId}/interrupt`, {
method: 'POST',
headers: {
Authorization: `Bearer ${token}`,
},
});

if (!response.ok) {
throw new Error(`API error: ${response.status}`);
}

const data = await response.json();
res.json(data);
} catch (error) {
console.error('Interrupt error:', error);
res.status(500).json({ error: 'Failed to interrupt' });
}
});

// End session endpoint
app.post('/api/avatar/end-session', async (req, res) => {
try {
const { sessionId, token } = req.body;

if (!sessions.has(sessionId)) {
return res.status(404).json({ error: 'Session not found' });
}

const response = await fetch(`${BASE_URL}/${sessionId}/end`, {
method: 'POST',
headers: {
Authorization: `Bearer ${token}`,
},
});

if (!response.ok) {
throw new Error(`API error: ${response.status}`);
}

// Remove session from storage
sessions.delete(sessionId);

const data = await response.json();
res.json(data);
} catch (error) {
console.error('End session error:', error);
res.status(500).json({ error: 'Failed to end session' });
}
});

// Keep-alive endpoint
app.post('/api/avatar/keep-alive', async (req, res) => {
try {
const { sessionId, token } = req.body;

if (!sessions.has(sessionId)) {
return res.status(404).json({ error: 'Session not found' });
}

const response = await fetch(`${BASE_URL}/${sessionId}/keep-alive`, {
method: 'POST',
headers: {
Authorization: `Bearer ${token}`,
},
});

if (!response.ok) {
throw new Error(`API error: ${response.status}`);
}

const data = await response.json();
res.json(data);
} catch (error) {
console.error('Keep-alive error:', error);
res.status(500).json({ error: 'Failed to send keep-alive' });
}
});

// Health check
app.get('/health', (req, res) => {
res.json({
status: 'ok',
sessions: sessions.size,
});
});

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});

Python Example

import os
import requests
from flask import Flask, request, jsonify

app = Flask(__name__)

API_KEY = os.environ.get('AVATAR_KS')
BASE_URL = 'https://api.avatar.us.kaltura.ai/v1/avatar-session'

# Session storage
sessions = {}

@app.route('/api/avatar/create-session', methods=['POST'])
def create_session():
try:
data = request.json
avatar_id = data.get('avatarId')
voice_id = data.get('voiceId')

response = requests.post(
f'{BASE_URL}/create',
headers={
'Authorization': f'KS {API_KEY}',
'Content-Type': 'application/json'
},
json={
'visualConfig': {'avatarId': avatar_id},
'voiceConfig': {'id': voice_id} if voice_id else None
}
)

response.raise_for_status()
result = response.json()

# Store session
sessions[result['sessionId']] = {
'token': result['token'],
'avatarId': avatar_id
}

return jsonify({
'sessionId': result['sessionId'],
'token': result['token']
})

except Exception as e:
return jsonify({'error': str(e)}), 500

@app.route('/api/avatar/say-text', methods=['POST'])
def say_text():
try:
data = request.json
session_id = data.get('sessionId')
token = data.get('token')
text = data.get('text')

if session_id not in sessions:
return jsonify({'error': 'Session not found'}), 404

response = requests.post(
f'{BASE_URL}/{session_id}/say-text',
headers={
'Authorization': f'Bearer {token}',
'Content-Type': 'application/json'
},
json={'text': text}
)

response.raise_for_status()
return jsonify(response.json())

except Exception as e:
return jsonify({'error': str(e)}), 500

@app.route('/api/avatar/end-session', methods=['POST'])
def end_session():
try:
data = request.json
session_id = data.get('sessionId')
token = data.get('token')

if session_id not in sessions:
return jsonify({'error': 'Session not found'}), 404

response = requests.post(
f'{BASE_URL}/{session_id}/end',
headers={'Authorization': f'Bearer {token}'}
)

response.raise_for_status()

# Remove session
del sessions[session_id]

return jsonify(response.json())

except Exception as e:
return jsonify({'error': str(e)}), 500

if __name__ == '__main__':
app.run(port=3000)

With Error Handling and Retries

async function createSessionWithRetry(maxRetries = 3) {
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
const response = await fetch(`${BASE_URL}/create`, {
method: 'POST',
headers: {
Authorization: `KS ${KS}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
visualConfig: { avatarId: 'avatar-123' },
}),
});

if (!response.ok) {
if (response.status >= 500 && attempt < maxRetries) {
// Retry on server errors
await new Promise((r) => setTimeout(r, 1000 * attempt));
continue;
}
throw new Error(`API error: ${response.status}`);
}

return await response.json();
} catch (error) {
if (attempt === maxRetries) {
throw error;
}
console.log(`Attempt ${attempt} failed, retrying...`);
await new Promise((r) => setTimeout(r, 1000 * attempt));
}
}
}

Next Steps