Catalog hydrate — resolve an avatar by handle
Instead of hardcoding avatar_id values like avt_441ad4d95906438490a85b79 in your app, resolve avatars by their human handle — (owner, avatarname) — via GET /v1/avatars/{owner}/{name}. The gateway returns the record (resolved avatar_id, display name, idle video, optional greeting), and your code stays free of opaque ids.
Shipped 2026-10-06 on the gateway + Flutter SDK. iOS native in preview. Web SDK integration in flight.
When to use it
Section titled “When to use it”- Your UI shows multiple avatars and you want human-readable ids in your config.
- You want to let users (or your product’s own logic) pick an avatar by name.
- You’re building a reseller / embed where customers pick which avatar runs in their deployment.
If you only ever use one hardcoded avatar, this is an optional convenience — nothing breaks without it.
Request
Section titled “Request”GET /v1/avatars/{owner}/{name}Authorization: Bearer sk_...owner + name are the human handles — e.g. alman/dr-alman for Dr. Alman. The gateway resolves either:
- Public avatars — anyone with a valid
sk_can see them. Owned by a studio creator who’s listed the avatar publicly. - Private avatars — only visible to the developer whose
sk_was issued through the Developer Portal, and only when the avatar’s creator has flipped the Studio-sideapi_exposed_attoggle on. See Avatar Studio API exposure for the opt-in.
Not found: 404 no_such_avatar. (Uniform-404 regardless of whether the avatar doesn’t exist or exists but isn’t visible to your tenant — the response can’t be used to probe for private avatar existence.)
Response
Section titled “Response”{ "avatar": { "owner": "alman", "name": "dr-alman", "display_name": "Dr. Alman", "avatar_id": "avt_4586c4366d51bfa70c0df7cd", "listed": true, "idle_url": "https://cdn.example.com/alman/idle.mp4", "poster_url": "https://cdn.example.com/alman/poster.jpg", "greeting": { "id": "grt_123", "video_url": "https://cdn.example.com/alman/intro.mp4", "text": "Hi, I'm Dr. Alman.", "kind": "intro", "consumption_key": null } }, "view_token": null}Fields:
avatar_id— the resolvedavt_...id. Pass this toPOST /v1/sessions.display_name— human name for your UI.idle_url— background idle video to show before/during warm-up.poster_url— static image before the idle video loads.greeting(optional) — intro video + text the avatar should say on first connect.kind: "intro"plays once per user;kind: "return"plays on repeat visits withconsumption_keyfor server-side idempotency.view_token— reserved for future auth modes;nullon T0.
SDK code
Section titled “SDK code”final result = await restClient.getAvatar('alman', 'dr-alman');print(result.avatar.displayName); // "Dr. Alman"print(result.avatar.avatarId); // "avt_4586c4366d51bfa70c0df7cd"
// Use the resolved id to mint a session.final session = await restClient.createLiveKitSession( TwaiApiLiveKitSessionRequest(avatarId: result.avatar.avatarId),);Full SDK docs: Flutter SDK.
let result = try await api.getAvatar(owner: "alman", name: "dr-alman")print(result.avatar.displayName!)print(result.avatar.avatarId)Full SDK docs: iOS native SDK.
As of 2026-10, the Web SDK’s client.avatars.get(owner, name) is in flight. Until it ships, call via your mint proxy:
// in your mint proxyapp.get('/avatars/:owner/:name', async (req, res) => { const r = await fetch( `https://api.2wai.ai/v1/avatars/${req.params.owner}/${req.params.name}`, { headers: { Authorization: `Bearer ${process.env.TWAI_SECRET_KEY}` } } ); res.status(r.status).json(await r.json());});Then client-side:
const { avatar } = await (await fetch(`/api/avatars/${owner}/${name}`)).json();curl https://api.2wai.ai/v1/avatars/alman/dr-alman \ -H "Authorization: Bearer sk_..."Errors
Section titled “Errors”| Status | code | What it means |
|---|---|---|
| 200 | — | Avatar resolved. |
| 401 | invalid_key | sk_ wrong or revoked. |
| 404 | no_such_avatar | Avatar doesn’t exist publicly, OR exists privately but isn’t visible to your sk_’s tenant. Uniform 404 — can’t distinguish. |
| 503 | catalog_hydrate_not_configured | Gateway not fully configured for catalog hydrate. Shouldn’t appear in prod post 2026-10-08. |
See Errors for the full ladder.