Atmee.aiDocs
APIAPI referenceAvatars

Create an avatar (Avatar Import API)

POST
/v1/avatars

Three body shapes, one result.

An image. multipart/form-data with the portrait (jpg, png or webp, <= 10 MB) as the file part and the avatar name as a second field (description optional). Creates a render-only avatar: no voice, no persona, nothing to build -- the response is 201 with status: ready and the avatar can be rendered for an external agent at once. Add a voice later with PUT /v1/avatars/{avatarId}/voice to make it conversational.

A zip. avatar.json plus image/, voice/, prompt/prompt.txt, knowledge/, as the file part or a raw application/zip body. voice/ is optional; without it the result is render-only as above. With a voice the avatar is created exactly as the studio would: the row, the files under <account>/<avatar>/, and one configs.latest write; the creator-studio pipeline builds it asynchronously (202, status: building), poll GET /v1/avatars/{avatarId}. The manifest's persona block carries the character: whoPrompt (who the avatar is: the main character description), whatPrompt (what the avatar is doing with the visitor; JSON alternative to prompt/prompt.txt -- providing both is rejected), preferredAlias, spokenName, knownAliases, greeting, selfIntroduction (derived from whoPrompt when absent), guardrails, conversationalHabits. personality and scenario are older names of whoPrompt and whatPrompt and still accepted; a field given under both names is 400 invalid_manifest. JSON. The manifest as application/json with an assets block naming the image, the voice sample, prompt text and knowledge files by https URL; the service downloads them (public hosts only, same size and type rules as the zip) and continues identically.

A draft. The image and the voice are both optional on the zip and JSON bodies (and assets itself on JSON), on either engine. An avatar created without its portrait, or without its voice (other than a v1 avatar with a portrait, which is render-only), is a draft: status: draft with missingInputs naming what it lacks. Its persona and knowledge build; nothing that needs the missing input does. Give them with PUT /v1/avatars/{avatarId}/appearance and PUT /v1/avatars/{avatarId}/voice, in either order; the build continues once both are there (on v2, the input that completes it captures the first candidate). seedPreviews and seedSelection need both inputs at create: a v2 draft takes one candidate, selected automatically. Where assets takes a URL for the image, the voice sample or a knowledge file, upload:<uploadId> names a file sent with POST /v1/uploads instead (the prompt stays a URL). The upload must be this account's, of the matching kind (portrait, voice, knowledge) and uploaded; its bytes decide its type, and the same size and type rules apply. A create that succeeds consumes its uploads; one that fails leaves them usable for a retry.

The portrait (every body shape) decides whether the avatar can be animated. Use a front-facing photo of one person, head and shoulders with some margin around the head, the face at least about a third of the frame, in even light, with the lips slightly parted as if about to speak. A v2 avatar animates its first moments from the portrait itself, so a closed mouth usually makes the first second of speech fail (the lips stay still); lips slightly parted work far more often. The build refuses a clearly bad portrait at the appearance stage: stages.appearance and latestFailure carry a portrait_* reason in userFeedback (portrait_no_face, portrait_face_too_small, portrait_mouth_closed, with a message you can show verbatim). Replace it with PUT /v1/avatars/{avatarId}/appearance. Preview clips are not generated unless the manifest sets previews: true (toggle later with PATCH); stages.previews then reads skipped. Requires the avatars:write scope, plus billing:write when the manifest has a sponsor block. Behind the avatar_import_api feature flag.

engine is v1 (the default) or v2. A v2 avatar's voice is cloned from its sample; a v2 create with the portrait and the voice captures seedPreviews.count candidates (default 1, at most 10). seedSelection is auto (the default: the first completed candidate is promoted) or manual. Both are v2 only. A portrait, voice or preview message changed outside the API (Creator Studio) captures one candidate of the new inputs by itself. Captures count against the account's limit of 10 queued or running; a v2 create answers with X-RateLimit-Limit and X-RateLimit-Remaining, and with 429 rate_limited (and Retry-After) when the captures do not fit. previewMessage is the line the preview clips speak; omit it for a default sentence in the avatar's language. On v2 it is the ~6 s prime clip every candidate is captured from, so at most 60 Unicode code points (400 preview_message_too_long). knowledge.descriptions maps a knowledge file name to a short description. knowledge.facts is the avatar's knowledge as text, at most 32,000 characters (400 invalid_manifest otherwise), on either engine: it is saved as Creator Studio saves its "Facts with context" box (shown there) and as a knowledge file the knowledge base reads; change it with PATCH. knowledge.questionnaire answers Creator Studio's knowledge questionnaire (question to answer, the questions of GET /v1/avatars/{avatarId}/knowledge; each answer non-blank, at most 2,000 characters), saved as Studio saves it; change it with PATCH. Knowledge (files and facts) is used in conversations by v1 avatars; v2 conversations do not use it yet. blackoutRecovery tunes how v2 sessions recover from frames that fade to black; it is on by default, so omit it unless a setting should differ. It is ignored for v1 avatars (the setting exists only on the v2 renderer). runtimeSeed (v2) is the seed of a session's motion; omit it to keep the renderer default, 42. Ignored for v1 avatars, like blackoutRecovery. resolution (v2) is the frame size the avatar renders at, e.g. {"width": 384, "height": 672} for portrait; default 512 x 512 (see RenderResolution). Unlike blackoutRecovery it is refused for v1 avatars (400 invalid_input).

Authorization

headerX-Api-Key<token>

Secret embed API key (sk_atmee_...; keys minted before 2026-09 carry sk_live_...), held by the customer's own backend and never sent to a browser. Format: X-Api-Key: sk_atmee_....

Request Body

  1. body

avatar.json plus an assets block. Field rules match the zip manifest and are enforced by the service (400 invalid_manifest, naming the field); only the shape is checked here.

schemaVersion*1
Value in1
name*string
Length1 <= length <= 100
description?string
language?string
visibility?string
Value in"private""unlisted"
previews?boolean
previewMessage?string
engine?string
Value in"v1""v2"
seedPreviews?
seedSelection?string
Value in"auto""manual"
blackoutRecovery?

Blackout recovery of the v2 renderer. While the avatar listens, it screens each generated chunk for a fade to black (or fully black frames) and shows a healthy listening clip in place of a failed one, returning to live frames on the first healthy chunk. On by default. Send only the settings to change; an absent or null one keeps its current value (on create: its default). Ignored for v1 avatars (the setting exists only on the v2 renderer): nothing is stored and the rest of the request behaves as without it. It changes how sessions render, never the avatar's build: no candidate is captured or cancelled. A change applies from the next session.

runtimeSeed?RuntimeSeed

The v2 renderer's runtime seed: it seeds a session's noise and motion after the first chunk, so another seed gives the same avatar different movement; the serving candidate stays the same. Default 42 (the renderer default; send 42 to go back to it). Absent or null keeps the current value (on create: the default). Ignored for v1 avatars: nothing is stored and the rest of the request behaves as without it. It is no build input: nothing is captured or rebuilt, and a change applies from the next session.

Range0 <= value <= 2147483647
resolution?

A frame size in pixels for the v2 renderer: width and height are each a multiple of 32 from 256 to 1024, and width x height is at most 262,144 (512 x 512); a larger frame is 400 invalid_manifest on an avatar, 400 invalid_input on a clip. Default 512 x 512 (square). Common shapes: square 512 x 512, portrait 384 x 672, landscape 672 x 384. A deployment offers only some sizes (512 x 512 always; GET /v1/account pricing.generation.clipResolutions lists them where clips are offered): another is 400 invalid_input ("resolution WxH is not offered; offered: ..."). On an avatar it is a build input of v2 avatars only (400 invalid_input for a v1 avatar): the portrait is preprocessed at that size, so a change on PATCH builds a new version with new candidates, like a new portrait; sending the current size again builds nothing. Absent or null keeps the current size (on create: the default).

voice?
persona?
knowledge?
sponsor?
assets?

The files of a JSON create, by URL. Same limits as the zip folders (image jpg/png/webp <=10 MB, voice 10-60 s <=12 MB, knowledge <=20 files). The image is the portrait; front-facing, face at least about a third of the frame, lips slightly parted (see the operation). With an image and no voice a v1 avatar is render-only; without the image (or a v2 one without the voice) it is a draft.

Response Body

Created and ready; a render-only avatar (image without a voice) has nothing to build.

application/json
  1. response
avatarId*string
Formatuuid
kind*AvatarKind

conversational avatars have a voice and a persona and can run a full Atmanity session once built. render_only avatars have a portrait only: they are ready immediately and render video for an external agent, but readyToChat stays false until a voice is added via PUT /voice.

Value in"conversational""render_only"
status*string

ready for a render-only avatar (nothing to build), draft for one created without its portrait or voice, building otherwise.

Value in"building""ready""draft"
missingInputs?array<>

What a draft was created without; absent otherwise.

statusUrl*string
engine?AvatarEngine

Render engine. v1 is the original renderer. v2 is built from a bundle plus a promoted candidate; see /candidates.

Value in"v1""v2"
sponsor?
Example Request
curl -X POST 'https://api.atmanity.us/v1/avatars' \  -H 'Content-Type: application/json' \  -d '{  "schemaVersion": 1,  "name": "string"}'
Example Response
{  "avatarId": "ac572b6e-802b-4b9e-a602-0786d4441e67",  "kind": "conversational",  "status": "building",  "missingInputs": [    "image"  ],  "statusUrl": "string",  "engine": "v1",  "sponsor": {    "transferredMicrocredits": 0,    "replayed": true,    "error": "string"  }}
Create an avatar (Avatar Import API) — Atmee Docs