Skip to content
Documentation
Esc
↑↓navigate↵open⌘Jpreview
On this page

Web SDK quickstart

Drive the whole avatar session from the browser with @avtr/web-sdk — session lifecycle, token handling, and error semantics in one client.

The browser SDK packages the canonical /v1/ flow — create, connect, refresh, status, end — behind one client, so your frontend never hand-rolls REST calls or token logic. The SDK is bound to the same generated contract as this site: it never invents endpoints, fields, or error codes.

Install and construct

npm install @avtr/web-sdk
import { AvtrWebSdk } from "@avtr/web-sdk";

const sdk = new AvtrWebSdk({
  apiBaseUrl: "https://<orvyn-public-api-host>", // REST base (no trailing slash needed)
  wsBaseUrl: "wss://<orvyn-public-api-host>", // optional; derived from apiBaseUrl when omitted
  videoElement: document.querySelector("video"),
  apiKey: "<server-minted-key>", // only needed for SDK-initiated REST calls
  sessionConfig: {
    /* CreateSessionRequest body when the SDK creates the session */
  },
  diagnostic: (message) => console.log(message),
});
Option Purpose
apiBaseUrl REST base URL for the /v1/ control plane
wsBaseUrl Media WebSocket base; derived from apiBaseUrl when omitted
videoElement <video> element the bundled MSE player renders into
apiKey API key — only needed when the SDK itself makes REST calls
sessionConfig CreateSessionRequest body used when the SDK creates the session
diagnostic Diagnostic log callback

Session lifecycle methods

Method Contract Semantics
createSession(apiBaseUrl, auth, body) POST /v1/sessions Returns the bare SessionResponse — client_token is delivered here exactly once
sdk.connect(sessionId, clientToken?) Media WebSocket /v1/sessions/{session_id}/ws?token= Refreshes an expired token before connecting; on a pre-open failure with 401 semantics it performs exactly one refresh + one retry. Mic capture starts automatically
sdk.refreshNow() POST /v1/sessions/{session_id}/client-token Explicit refresh; returns the bare ClientTokenResponse (5-minute TTL). Single-flight — concurrent callers share one request
sdk.status() GET /v1/sessions/{session_id} Returns the bare SessionStatusResponse. Never contains a client_token
sdk.endSession({ force? }) POST /v1/sessions/{session_id}/end Returns the bare EndSessionResponse; force: true appends ?force=true to skip the graceful handshake
sdk.disconnect() — Local teardown only; no REST call

Token lifecycle

The client_token is a short-lived bearer credential with a 5-minute TTL (expires_at is epoch milliseconds). The SDK tracks the newest token and handles four refresh triggers:

  1. Creation — createSession() returns the first token in the SessionResponse.
  2. Expiry-triggered — before opening the socket, a cached token whose expires_at has passed is refreshed via the client-token endpoint (single-flight, lazy — no timers).
  3. 401-triggered — the media WebSocket answers an expired or invalid ?token= with HTTP 401. A pre-open connect failure while a token is known triggers exactly one refresh and one retry; a second failure propagates the original error.
  4. Manual — await sdk.refreshNow() for reconnects, delayed connections, and browser sleep recovery.

Refreshing does not revoke previously issued tokens — outstanding tokens simply age out at their own expiry (5-minute TTL).

End semantics — the 409 resolution

POST /end returns 409 when the session is not active:

  • AVTR_SESSION_ENDED — status was ended / ended_with_warnings.
  • AVTR_SESSION_CONFLICT — status was created / ending / failed.

Both mean the end intent can no longer change the outcome, so the SDK resolves them to { sessionId, status: "ended", endedAt: 0 } instead of throwing (endedAt: 0 marks “already ended; server timestamp not re-issued”). All other errors — 401, 403, 404, 429, 503 — throw AvtrApiError. See the lifecycle guide for the full matrix.

Error handling

REST failures throw AvtrApiError, which carries the flat contract error fields:

Property Meaning
code The AVTR_* error code from the flat error shape
status HTTP status code
requestId The request_id correlation UUID
retryAfter retry_after in seconds — present on retryable codes only
docUrl The doc_url documentation link
try {
  await sdk.endSession({ force: true });
} catch (err) {
  console.error(err.code, err.status, err.requestId, err.retryAfter);
}

Match on code (and status), never on message — see errors, limits & security for the full catalog and the retry rules.

Media playback

The SDK bundles an MSE player (MediaSource + SourceBuffer, bounded segment queue with backpressure handling) that renders fMP4 segments into your videoElement. For the underlying media protocol — segments, microphone PCM frames, and the message catalog — see the WebSocket & fMP4 guide, including its MSE playback section.

Was this page helpful?