Embed widget
Drop a talking avatar onto any website with a single iframe — zero backend — and mint short-lived embed tokens for per-visitor session tracking.
Drop-in iframe
Embed an agent as an iframe — no SDK install, drop it on any page. The avatar runs in bitHuman’s cloud; your page just hosts the frame:
<iframe
src="https://bithuman.ai/embed/A78WKV4515"
allow="microphone *; camera *; autoplay *"
style="width: 400px; height: 700px; border: none; border-radius: 12px;"
></iframe>
Replace A78WKV4515 with your agent code — find it in the Library or the Deploy & Share dialog. URL parameters customize the widget.
Note The
allowattribute must grantmicrophone(andcamera, if you use vision) to the embed origin. If the parent page sets a restrictivePermissions-Policy, allowlistagent.viewer.bithuman.aior the mic prompt won’t appear in some browsers.
Production: mint short-lived embed tokens
For per-visitor session tracking and rate limiting, mint a short-lived embed token from your backend and pass it to the iframe. Your api-secret never reaches the browser. (The mint endpoint authenticates your api-secret upstream and is covered by a per-IP request limit rather than your plan tiers.)
// SERVER — mint a token (api-secret stays server-side)
const res = await fetch("https://api.bithuman.ai/v1/embed-tokens/request", {
method: "POST",
headers: {
"api-secret": process.env.BITHUMAN_API_SECRET,
"content-type": "application/json",
},
body: JSON.stringify({
agent_id: "A78WKV4515",
fingerprint: visitorFingerprint, // stable per-device hex — required
}),
});
const { data: { token } } = await res.json();
<!-- BROWSER — pass the token in the iframe URL -->
<iframe
src="https://bithuman.ai/embed/A78WKV4515?token=YOUR_TOKEN"
allow="microphone *; camera *; autoplay *"
style="width: 400px; height: 700px; border: none;"
></iframe>
The token is a 1-hour JWT (HS256-signed). Mint one per visitor session. Both agent_id and fingerprint are required; the response also returns a sid session identifier for tracking the embed instance. See POST /v1/embed-tokens/request for the full request shape.
Pin a serving tier
By default the platform routes each session down the model’s serving chain
(GPU → Apple Neural Engine → CPU), overflowing on capacity
(details). For
benchmarking or placement testing, append ?model= with a force-tier slug
(essence-2-gpu/-ane/-cpu, expression-2-gpu/-cpu/-ane) to the embed (or
viewer) URL to pin the session to that tier — a forced tier never overflows:
<iframe
src="https://bithuman.ai/embed/A66GYD8664?token=YOUR_TOKEN&model=expression-2-cpu"
allow="microphone *; camera *; autoplay *"
style="width: 400px; height: 700px; border: none;"
></iframe>
The tier slugs per model are listed in each model guide —
Expression 2,
Essence 2,
Essence 2 Max (single tier). An
unrecognized value falls back to the agent’s default routing. For production,
omit ?model= and let the platform choose — direct elastic tiers scale from
zero and can cold-start on first connect
(what to expect).
Prefer validating the choice when you mint the token: pass model in the
POST /v1/embed-tokens/request body
and the API checks it up front — an unknown value returns 400, and a model
family the agent can’t be launched as (a per-identity artifact that hasn’t
been generated, or essence-2-max on an agent with no stored identity
video — generated internally by Essence creations)
returns 409 MODEL_NOT_GENERATED rather than a
session that fails to start. The mint response’s supported_models array
tells you which model families the agent can launch as right now — send those
values straight back as model, mapping the two internal tier spellings first
(essence-2-light → essence-2, essence-2-quality → essence-2-max; the
former is rejected with 400 by
POST /v1/video/generate).
Webhooks
bitHuman POSTs to your endpoint when session events occur. Return 200 immediately and offload work to a queue — long handlers risk the timeout.
room.join — fired once when a user connects:
{ "agent_code": "A80HVD8577", "event_type": "room.join",
"data": { "room_name": "support", "participant_count": 1,
"session_id": "session_xyz" }, "timestamp": 1705312200.0 }
chat.push — fired per message (user and agent):
{ "agent_code": "A80HVD8577", "event_type": "chat.push",
"data": { "role": "user", "message": "help with order #12345",
"session_id": "session_xyz" }, "timestamp": 1705312285.0 }
Endpoint setup, signature verification, and retry policy are in the API reference.
Where to go next
- Essence 2 & Expression 2 — the second-generation models, with per-model guides: Expression 2, Essence 2, Essence 2 Max.
- Session behavior & troubleshooting — connect latency, idle behavior, and common embed errors.
- Deploy via LiveKit — full agent-worker integration.
- Browser rendering — render client-side to cut server video egress.
- API reference — embed tokens, agents, and webhooks.
- Pricing — what an embedded session costs.