Quickstart
This guide takes you from zero to a running realtime avatar session. Budget about 10 minutes.
Prerequisites
Section titled “Prerequisites”- A Protoface account and an API key (
sk_live_...). Create one in the dashboard — new accounts get free credits applied automatically (see Limits & quotas). - A LiveKit project. Protoface is BYO transport: you own the room and mint
the worker token with your own LiveKit API key/secret. A free
LiveKit Cloud project works. You’ll need:
LIVEKIT_URL(e.g.wss://your-project.livekit.cloud)LIVEKIT_API_KEYLIVEKIT_API_SECRET
1. Get your API key
Section titled “1. Get your API key”Sign up at app.protoface.com, create a key under API keys, and copy it. The full key is shown once at creation — store it somewhere safe.
export PROTOFACE_API_KEY="sk_live_..."2. List available avatars
Section titled “2. List available avatars”Confirm your key works and find an avatar to use. v0 returns platform demo
avatars such as av_demo.
curl https://api.protoface.com/v1/avatars \ -H "Authorization: Bearer $PROTOFACE_API_KEY"import { ProtofaceClient } from "@protoface/sdk";
const client = new ProtofaceClient({ apiKey: process.env.PROTOFACE_API_KEY! });
const avatars = await client.avatars.list();console.log(avatars.data.map((a) => `${a.id} (${a.status})`));3. Mint a LiveKit worker token
Section titled “3. Mint a LiveKit worker token”Protoface joins a room you own. You mint a token authorizing our worker to join, using your LiveKit API key and secret. The Protoface SDK never touches your LiveKit credentials.
import { AccessToken } from "livekit-server-sdk";
const ROOM_NAME = "protoface-demo";
const at = new AccessToken( process.env.LIVEKIT_API_KEY!, process.env.LIVEKIT_API_SECRET!, { identity: "protoface-worker" },);at.addGrant({ roomJoin: true, room: ROOM_NAME });
const workerToken = await at.toJwt();from livekit import api as lk_api
ROOM_NAME = "protoface-demo"
worker_token = ( lk_api.AccessToken(LIVEKIT_API_KEY, LIVEKIT_API_SECRET) .with_identity("protoface-worker") .with_grants(lk_api.VideoGrants(room_join=True, room=ROOM_NAME)) .to_jwt())4. Create a session
Section titled “4. Create a session”Point Protoface at your room and pass the worker token you just minted.
curl https://api.protoface.com/v1/sessions \ -H "Authorization: Bearer $PROTOFACE_API_KEY" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: $(uuidgen)" \ -d '{ "avatar_id": "av_demo", "transport": { "type": "livekit", "url": "wss://your-project.livekit.cloud", "room_name": "protoface-demo", "worker_token": "<WORKER_TOKEN_FROM_STEP_3>" }, "quality": "mock", "metadata": { "demo": "quickstart" } }'import { ProtofaceClient } from "@protoface/sdk";
const client = new ProtofaceClient({ apiKey: process.env.PROTOFACE_API_KEY! });
// `createLivekit` is a convenience wrapper around `sessions.create`.const session = await client.sessions.createLivekit({ avatarId: "av_demo", url: process.env.LIVEKIT_URL!, roomName: "protoface-demo", workerToken, // from step 3});
console.log(session.id, session.status); // sess_..., "created"The call returns immediately (under 300 ms p95) with
status: "created". The session is queued — a worker claims it asynchronously.
5. Watch the avatar speak
Section titled “5. Watch the avatar speak”Join the same LiveKit room as a participant from your app or the LiveKit Meet sandbox. Once the worker joins, it publishes a video track and the avatar starts rendering. Push audio into the room and the avatar speaks it back in realtime.
First frame typically lands within a few seconds of create (see the realtime targets).
6. Poll status and end the session
Section titled “6. Poll status and end the session”# Pollcurl https://api.protoface.com/v1/sessions/sess_... \ -H "Authorization: Bearer $PROTOFACE_API_KEY"
# End (idempotent)curl -X POST https://api.protoface.com/v1/sessions/sess_.../end \ -H "Authorization: Bearer $PROTOFACE_API_KEY"const current = await client.sessions.get(session.id);console.log(current.status, current.first_frame_at);
// End when you're done. Idempotent.await client.sessions.end(session.id);A session ends on its own when it hits max_duration_seconds, when audio stops
for idle_timeout_seconds, or when you call end. See
Limits & quotas for the defaults.
Install the SDK
Section titled “Install the SDK”The TypeScript examples above use the official SDK:
npm install @protoface/sdkIt works in Node 18+, browsers (server-side only — never ship your key to a
browser), and edge runtimes. The SDK retries 429/503 automatically and
throws typed errors you can switch on by error.code — see
Error reference.