Skip to main content

End Session

End the current avatar session and clean up resources.

Endpoint

POST /v1/avatar-session/:sessionId/end

Authentication

Header: Authorization: Bearer {token}

Path Parameters

ParameterTypeRequiredDescription
sessionIdstringYesSession ID from create-session

Request Body

Empty body ({}).

Response

Success (200)

{
"success": true
}

Error Responses

  • 400 - Bad request
  • 401 - Unauthorized
  • 404 - Not found
  • 410 - Gone (already ended)
  • 500 - Server error

Examples

cURL

curl -X POST https://api.avatar.us.kaltura.ai/v1/avatar-session/session-123/end \
-H "Authorization: Bearer $TOKEN"

JavaScript (fetch)

await fetch(`https://api.avatar.us.kaltura.ai/v1/avatar-session/${sessionId}/end`, {
method: 'POST',
headers: {
Authorization: `Bearer ${token}`,
},
});

Usage Notes

What It Does

  1. Stops keep-alive
  2. Ends WebRTC streaming
  3. Releases backend resources
  4. Invalidates the session token

When to Call

  • When user is done with the avatar
  • Before navigating away from the page
  • On application shutdown
  • On error that requires restart

Cleanup

Always call end-session to prevent resource leaks:

window.addEventListener('beforeunload', async () => {
await fetch(`${baseUrl}/${sessionId}/end`, {
method: 'POST',
headers: {
Authorization: `Bearer ${token}`,
},
keepalive: true, // Important for beforeunload
});
});

Complete Example

class AvatarSession {
constructor(baseUrl) {
this.baseUrl = baseUrl;
this.sessionId = null;
this.token = null;
}

async create(ks, avatarId) {
const response = await fetch(this.baseUrl, {
method: 'POST',
headers: {
Authorization: `KS ${ks}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
visualConfig: { avatarId },
}),
});

const data = await response.json();
this.sessionId = data.sessionId;
this.token = data.token;
}

async end() {
if (!this.sessionId || !this.token) {
console.warn('No active session');
return;
}

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

if (response.ok) {
console.log('Session ended successfully');
this.sessionId = null;
this.token = null;
} else {
console.error('Failed to end session');
}
} catch (error) {
console.error('Error ending session:', error);
}
}
}

// Usage
const session = new AvatarSession('https://api.avatar.us.kaltura.ai/v1/avatar-session');

await session.create(apiKey, 'avatar-123');

// ... use the session ...

// Clean up
await session.end();

Error Handling

try {
await fetch(`${baseUrl}/${sessionId}/end`, {
method: 'POST',
headers: {
Authorization: `Bearer ${token}`,
},
});

console.log('✅ Session ended');
} catch (error) {
console.error('❌ Failed to end session:', error);
// Session may have already ended or timed out
// Clean up local state anyway
sessionId = null;
token = null;
}

Best Practices

1. Always End Sessions

// ❌ Bad - session left open
await createSession();
// ... use session ...
// navigate away without ending

// ✅ Good - always end session
await createSession();
try {
// ... use session ...
} finally {
await endSession();
}

2. Handle Page Unload

window.addEventListener('beforeunload', (event) => {
if (sessionId) {
navigator.sendBeacon(
`${baseUrl}/${sessionId}/end`,
JSON.stringify({
headers: { Authorization: `Bearer ${token}` },
})
);
}
});

3. Timeout Handling

// Set a max session duration
const MAX_SESSION_DURATION = 30 * 60 * 1000; // 30 minutes

setTimeout(async () => {
console.log('Session timeout - ending');
await endSession();
}, MAX_SESSION_DURATION);

Next Steps