# Kasamila API / Web SDK 2.1.0 developer handbook

> Kasamila developer documentation · [Canonical page](https://www.kasamila.com/portal/docs/complete?lang=en)

[English](kasamila_api_and_sdk_guide.en.md) | [简体中文](kasamila_api_and_sdk_guide.md)

> SDK 2.1: encrypted GLSL/ONNX with temporary Runtime licensing; no caller-side key setup. See [AILIVE upgrade and protection notes](sdk_2_1_protected_runtime.en.md). Pinned 2.0.0 remains supported.

# Kasamila API / Web SDK 2.1.0 developer handbook

> SDK 2.1.0 released: read the [new Runtime release contract](sdk_2_runtime_release_contract.en.md) before integration. SDK 1 and mutable entry URLs are retired. This guide's fixed version checks apply only to explicitly pinned examples, not to a server-global latest version. Forward the Session response's sdk object from your backend and load it with the bootstrap. HLS is bundled. Production supports this release; use the one-time migration checklist.


This is the main entry point for integrators. Geometry is the supported template build/runtime mode. Person-specific MouthUNet fine-tuning and V7+v29 hybrid rendering are retired and must not be used for new integrations.

[Runtime and Agent API](api_v1_runtime_integration_guide.en.md) · [Geometry/HLS reference](api_v1_geometry_runtime_guide.en.md) · [Migration checklist](sdk_1_11_0_third_party_migration.en.md) · [Runnable example](../examples/geometry-runtime-web/README.en.md)

## 1. Current production contract

| Item | Contract |
| --- | --- |
| Template mode | `geometry` only |
| SDK | `https://www.kasamila.com/sdk/releases/2.1.0/kasamila.js` |
| Media delivery | Caller-hosted HLS for short and long templates |
| Model data | Kasamila-authorized Runtime Manifest; V7 + 468-point tracking + chunked geometry |
| Default profile | C |
| Explicit comparisons | G/H/I; I is not automatically enabled |
| Teeth and oral surfaces | Generated by the full SDK V7 chain, not baked into caller HLS |
| Transparent media | Matching packed-matte HLS, not ordinary color HLS |
| Browser credential | Short-lived `ks_rt_` Token only |
| Backend credential | Permanent `ks_live_` / `ks_test_` API Key |

Portal's authenticated built-in previews are free and login-bound; their Tokens cannot be reused by third parties. Ordinary API/SDK Sessions are metered from creation using server elapsed time. A lease reserves seconds up front; early termination returns unused seconds idempotently, while an unended lease consumes its full duration.
New users receive one API/SDK hour, valid for 30 days after registration. Packs have separate expiry dates and are consumed earliest-expiry first. Silence and hidden canvases still count.

SDK `destroy()` ends the Runtime lifecycle. Backend-managed flows can use the authorized `POST /api/v1/runtime/sessions/end` operation. `stop()` only stops audio.

SDK 2.1.0 adds client negotiation and the sdk release descriptor; mouth/media fields retain their semantics. Its stable-material closed-lip contact layer aims to reduce source-teeth/highlight artifacts; assess actual template quality rather than assuming every artifact is eliminated. Existing media descriptors and calibration do not require migration or geometry retraining for this SDK revision.

## 2. Integration flow

1. Query runnable ready geometry templates on your backend with your API Key.
2. Create a Session bound to the template, exact browser Origin, input modes and output mode.
3. Return the short-lived client Token and your trusted HLS descriptor matching the actual output mode.
4. Load the official SDK and call `Kasamila.create()`.
5. The SDK obtains signed geometry, oral materials and official rendering assets, accepts audio and renders in the browser.
6. End the player/Session on component teardown or when idle suspension is intended.

## 3. Backend example

The authentication and descriptor-store helpers below belong to your application:

```javascript
const request = authorizeEndUserAndTemplate(currentUser, selectedTemplate);
const response = await fetch('https://www.kasamila.com/api/v1/runtime/sessions', {
  method: 'POST', signal: AbortSignal.timeout(15000),
  headers: {
    Authorization: `Bearer ${process.env.KASAMILA_API_KEY}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    avatar_id: request.avatarId, template_code: request.templateCode,
    origin: 'https://app.example.com',
    input_modes: ['file', 'audio_url', 'pcm_stream', 'tts_stream'],
    output_mode: 'original', max_duration_seconds: 600
  })
});
const payload = await response.json();
if (!response.ok) throw new Error(payload.error?.code || 'runtime_failed');
return {
  sdk: payload.data.sdk, sessionToken: payload.data.client_token,
  expiresAt: payload.data.expires_at,
  mediaDelivery: payload.data.media_delivery,
  templateMedia: loadTrustedMediaDescriptor(
    payload.data.output_mode, `${request.avatarId}-${request.templateCode}`)
};
```

Keep Keys in backend configuration/Secret Manager. Never let the browser submit arbitrary descriptor URLs. Protect token issuance with your own authentication, template authorization and rate limits. Clean up a created Session if subsequent bootstrap fails.

## 4. Browser initialization

```html
<div id="avatar" style="width:540px;height:960px"></div>
<script type="module">
  import { loadKasamila } from "https://www.kasamila.com/sdk/bootstrap/1/loader.mjs";
  const response = await fetch("/api/runtime-token", {
    method: "POST", credentials: "same-origin"
  });
  const bootstrap = await response.json();
  if (!response.ok) throw new Error("Runtime bootstrap failed");
  const Kasamila = await loadKasamila(bootstrap.sdk, "https://www.kasamila.com");
  const player = await Kasamila.create({
    element: document.querySelector("#avatar"),
    sessionToken: bootstrap.sessionToken,
    templateMedia: bootstrap.templateMedia
  });
  window.addEventListener("pagehide", () => player.destroy(), { once: true });
</script>
```

Use native HLS when available; otherwise the SDK uses its bundled hls.js. The SDK starts at frame 0 only once initial geometry, textures and mouth runtime are ready. It prefetches media and two-second geometry chunks; gzip/JSON decoding runs in a Blob Worker.

Decoded frame PTS is the template clock, always at `1.0` playback rate. Never adjust internal video time/rate yourself. Idle loops the template; speech continues from the current idle position.

## 5. Audio inputs

```javascript
await player.setAudioFile(file);                       // file
await player.setAudioUrl(corsEnabledTemporaryUrl);    // audio_url
await player.setPcmStream(readable, { sampleRate: 16000 });
await player.setPcmStream(ttsReadable, {
  mode: 'tts_stream', sampleRate: 16000
});
await player.setMicrophone();                          // microphone
await player.setMediaStreamTrack(remoteRtcTrack);      // rtc
```

Grant only required `input_modes`. Unlock audio via a user gesture. Use decodable TTS files or mono Int16/Float32 PCM with the real sample rate. Browser speechSynthesis cannot export standard PCM and is only an approximate demo.

## 6. Mouth and teeth

Use Manifest defaults. `setProfile('I')` should be an explicit geometry candidate test, not an implicit default. Browser profile/parameter changes do not save template defaults.

Do not overlay old MouthUNet/v29 masks, mouth/teeth layers or CSS clipping onto the SDK Canvas. Do not set `teeth_scale` to zero unless intentionally disabling teeth. The SDK loads its official renderer and teeth texture; no separate teeth endpoint is needed.

If teeth are missing, check:

1. Actual `Kasamila.version === '2.1.0'`; clear stale JS/Service Worker/CDN caching.
2. `/web/common/teeth_cavity_texture.png` returns HTTP 200 and is not blocked by CSP/CORS/proxies.
3. `player.getMouthConfiguration().parameters.teeth_scale > 0`.
4. No old mouth layer obscures the Canvas.
5. `Geometry v7 oral material is incomplete` means template assets need repair; never fall back to an old renderer.

Use only the stable `Kasamila.create()` interface, not internal WebGL classes.

## 7. HLS, transparency, CORS and CSP

A full `templateMedia` descriptor is required for every geometry template, including ten-second and five-minute-plus videos. It includes timeline, fps, frame count, logical dimensions, layout, two-second segment duration and canonical-media digest.
Packed-matte output needs a separate matching descriptor and matte layout. Confirm actual output with `player.getOutput()`; requesting transparent does not prove the Canvas is transparent.

Media responses must allow the page Origin on every playlist, initialization segment and media segment:

```http
Access-Control-Allow-Origin: https://app.example.com
Access-Control-Allow-Methods: GET, HEAD, OPTIONS
Access-Control-Expose-Headers: Content-Length, Content-Range, Accept-Ranges, ETag
```

```text
script-src 'self' https://www.kasamila.com;
connect-src 'self' https://www.kasamila.com https://media.example.com;
media-src 'self' https://www.kasamila.com https://media.example.com blob:;
worker-src 'self' blob:;
img-src 'self' https://www.kasamila.com data: blob:;
```

Texture access needs `img-src`; mouth/geometry decoding requires Blob Workers and `connect-src`. Supply media MIME types and signed-URL lifetimes appropriate for the full Session.

## 8. Acceptance and ongoing updates

Test original and packed-matte output, short/long playback, segment crossings, seek/loop, file/TTS/PCM inputs, lip/teeth occlusion, explicit profiles, network recovery and media/Token expiry. Confirm fixed-speed playback and no periodic two-second stalls.

Verify teardown without duplicate Canvas, audio nodes or heartbeats, and long-run memory/audio recovery on actual desktop and mobile devices.
Use the [upgrade guide](sdk_1_11_0_third_party_migration.en.md) as your release checklist. Public [Kasamila developer resources](https://github.com/kasamila/kasamila-dev) provide updated documents, examples and [release notes](https://github.com/kasamila/kasamila-dev/blob/main/CHANGELOG.md).
