Atmee.aiDocs

Create an avatar

Two ways to create an avatar with the API: send a JSON manifest that points at your files, or upload everything in one zip. Either builds Atmee V2 or Atmee V1.

Everything you can do in Studio's Create flow is also an API call. An avatar made through the API shows up in Studio and starts sessions with POST /v1/sessions like any other.

There are two ways to create one. Both build either model and end the same way.

With JSONWith a zip
Your filesPublic https links, or uploads you send firstInside the zip, next to the manifest
One request isA JSON manifestA zip, as a multipart file or a raw application/zip
Best forApps and agents, files already online, Atmee V2Files on disk, many avatars at once

Before you start

  • A key with avatars:write, account-wide: an avatar-scoped key can't create avatars. Add generation:write to generate a portrait or a voice. See API keys.
  • A portrait: jpg, png or webp, up to 10 MB. See Avatar 101: Negative examples for the photos that animate badly.
  • A voice sample: 10 to 60 seconds of one person speaking clearly, up to 12 MB: mp3, wav, m4a, aac, ogg, flac, opus or webm. An Atmee V2 avatar's voice is cloned from it.
  • Permission: if the portrait or the voice is a real person other than you, have that person's permission first.
  • The model: set engine to v2 or v1 on every create. Without it the API builds Atmee V1. Atmee V2 is invite only for now (403 v2_access_required without access).

Create with JSON

Send a manifest that points at your files. Atmee downloads them, checks them and starts the build.

Get your files to Atmee

If the portrait and the voice sample are at public https links, skip to the next step.

Otherwise, upload each one first. Start an upload, PUT the file to the uploadUrl it returns, with its uploadHeaders:

curl -X POST https://api.atmanity.us/v1/uploads \
  -H "X-Api-Key: $ATMEE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "kind": "portrait" }'

curl -X PUT "<uploadUrl>" -H "Content-Type: image/jpeg" --data-binary @portrait.jpg

kind is portrait, voice or knowledge. Poll GET /v1/uploads/{uploadId} until status is uploaded, then use upload:<uploadId> wherever the manifest takes a link. An upload works once and expires an hour after you start it; a create that fails leaves it usable for a retry.

Send the manifest

curl -X POST https://api.atmanity.us/v1/avatars \
  -H "X-Api-Key: $ATMEE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "schemaVersion": 1,
    "name": "Val",
    "engine": "v2",
    "language": "en",
    "visibility": "private",
    "previewMessage": "Hi! I am Val. What can I help you find today?",
    "assets": {
      "image": { "url": "https://cdn.example.com/val/portrait.jpg" },
      "voice": { "url": "upload:6f1c2d34-8b7a-4e19-9c5d-0a2b3c4d5e6f" }
    }
  }'
{
  "avatarId": "56cc8fdd-ba78-4d48-a210-16cf80c3f5f5",
  "status": "building",
  "statusUrl": "/v1/avatars/56cc8fdd-ba78-4d48-a210-16cf80c3f5f5"
}

A 202 means the build has started. Keep the avatarId. Every field is in Manifest fields.

Wait for the build

Poll the avatar every few seconds until it settles:

curl https://api.atmanity.us/v1/avatars/56cc8fdd-ba78-4d48-a210-16cf80c3f5f5 \
  -H "X-Api-Key: $ATMEE_API_KEY"

An Atmee V1 build usually finishes in under a minute; an Atmee V2 build takes a few minutes, longer when the renderer is starting cold. What each status means is in Build status.

Pick a take (Atmee V2)

An Atmee V2 avatar is captured as one or more takes: short talking clips of it saying the preview message. By default the first take to finish goes live. To compare, list them and watch each previewUrl:

curl https://api.atmanity.us/v1/avatars/56cc8fdd-ba78-4d48-a210-16cf80c3f5f5/candidates \
  -H "X-Api-Key: $ATMEE_API_KEY"

Capture more, or pick another, at any time. See Takes and versions.

Start a conversation

Once readyToChat is true, start a session with the avatarId, as in the Quickstart.

Create with a zip

Put the manifest and the files in one zip, and send it in one request.

Lay out the zip

my-avatar.zip
├── avatar.json          # the manifest (required)
├── image/portrait.jpg   # exactly one image
├── voice/sample.wav     # exactly one sample; leave out for a render-only avatar
├── prompt/prompt.txt    # optional: what the avatar does with the visitor, as text
└── knowledge/           # optional: up to 20 files (pdf, docx, doc, txt, md, html, csv), 50 MB each

Write avatar.json

The manifest takes the same fields as the JSON create, without assets, plus knowledge.descriptions for the files in knowledge/:

{
  "schemaVersion": 1,
  "name": "Grand Valley Concierge",
  "engine": "v1",
  "language": "en",
  "visibility": "private",
  "persona": {
    "preferredAlias": "Val",
    "whoPrompt": "A warm, endlessly patient concierge who knows the resort inside out.",
    "greeting": "Hi, I'm Val. How can I help?",
    "guardrails": ["Never quote prices that aren't in the knowledge base"]
  },
  "knowledge": { "descriptions": { "pricing.pdf": "2026 rate card" } }
}

prompt/prompt.txt and persona.whatPrompt say the same thing, so give only one of them.

Upload it

curl -X POST https://api.atmanity.us/v1/avatars \
  -H "X-Api-Key: $ATMEE_API_KEY" \
  -F "file=@my-avatar.zip"

Or send the zip itself as the body, with Content-Type: application/zip. A 202 with status: building and the avatarId means the build has started.

Wait for the build

Poll GET /v1/avatars/{avatarId} as in the JSON path until it settles. See Build status. For an Atmee V2 avatar, pick a take the same way.

Render-only avatars. A zip without a voice, or a multipart request with only an image (file) and a name, makes a render-only avatar: 201, ready at once, for use with your own voice agent in Avatar mode. Add a voice later with PUT /v1/avatars/{avatarId}/voice to make it talk on its own.

Manifest fields

FieldNotes
schemaVersionRequired. 1.
nameRequired. 1 to 100 characters, the name in Studio.
enginev2 or v1. Without it the API builds v1, so always send it.
languageThe avatar's language: en, zh-TW, zh-CN, ja, ko, fr, vi, es, de, ru, or hi (accepted, spoken in English for now).
visibilityprivate (default) or unlisted. Make it public with PATCH once it is ready.
assets.image.url, assets.voice.urlJSON only. The portrait and the voice sample: a public https link or upload:<uploadId>.
assets.prompt.url, assets.knowledgeJSON only. The prompt text, and the knowledge files as a list of { "url", "description" }.
previewMessageThe line the previews speak. On Atmee V2 every take speaks it, up to 60 characters (400 preview_message_too_long). Leave it out for a default sentence in the avatar's language.
seedPreviews.countAtmee V2. How many takes to capture now, 1 to 10. Default 1.
seedSelectionAtmee V2. auto (default): the first finished take goes live. manual: the avatar waits as awaiting_selection until you pick one.
resolutionAtmee V2. The frame size, square 512 × 512 by default; portrait or landscape where your account offers it.
persona.whoPromptWho the avatar is. Up to 10,000 characters.
persona.whatPromptWhat it does with the visitor. Up to 10,000 characters. In a zip, this or prompt/prompt.txt.
persona.greetingIts opening line, up to 500 characters.
persona.selfIntroductionHow it introduces itself, 51 to 2,000 characters. Written from whoPrompt when left out.
persona.guardrailsUp to 20 rules, 500 characters each, used word for word.
persona.preferredAlias, spokenName, knownAliasesThe name it goes by, how to say it, and other names people use.
persona.conversationalHabitsStudio's style sliders, each CONVERSATIONAL_HABIT_SCALE_LOW, _MEDIUM or _HIGH.
knowledge.factsWhat it knows, as text, up to 32,000 characters. Used by Atmee V1 avatars; Atmee V2 conversations don't use knowledge yet.
knowledge.descriptionsZip only. A short description for each file in knowledge/.
previewstrue to also render idle and talking preview clips, off by default.

personality and scenario still work as older names of whoPrompt and whatPrompt; a field given under both names is 400 invalid_manifest.

Start with only a name. The portrait and the voice are optional on both paths. An avatar created without them is a draft (status: draft, with missingInputs naming what it lacks). Add them with PUT /appearance and PUT /voice, in either order, and the build carries on. An Atmee V2 draft captures one take, picked automatically.

Build status

statusMeans
buildingStill working. Keep polling.
readyStart a session once readyToChat is true.
awaiting_selectionAtmee V2 with seedSelection: manual: pick a take.
draftCreated without its portrait or voice; missingInputs says which.
failedlatestFailure.userFeedback says why, in words you can show your user.
moderation_holdHeld for review. Visitors can't open it, but your account can still talk to it while readyToChat is true. Don't retry.
stalledNo progress for a long time; stall.reason says what to replace. Waiting longer won't help.

The answer also has stages: appearance, voice, persona, knowledge and previews, each moving through waiting, pending, processing and completed, skipped when it doesn't apply (such as previews when you didn't ask for them), or failed with a userFeedback message. A clearly bad portrait fails appearance with a portrait_* reason (portrait_no_face, portrait_face_too_small, portrait_mouth_closed); replace the portrait to fix it.

If a create fails on the network, list your avatars before you send it again: a repeated create makes a second avatar.

Takes and versions

Atmee V2 only. Lip sync and motion vary from take to take, and the inputs don't tell you which will be best, so watch them.

A version is one set of capture inputs: the portrait, the voice sample and the preview message. Changing any of them starts a new version with new takes, and the old take serves until a new one goes live. Picking a take of an older version goes back to that version's inputs, with nothing captured again. DELETE /v1/avatars/{avatarId}/versions/{versionId} removes an older version; the current one, or one holding the serving take, can't be deleted (version_in_use).

Update it afterwards

No portrait or voice yet?

Generate them. Each call needs a key with generation:write and avatars:write, and an Idempotency-Key header with a new UUID, so a retry never charges twice.

CallSendGet back
POST /v1/generation/portraitsA description of an invented characterUp to four portraits
POST /v1/generation/enhancementsYour photo as image, and an optional prompt to restyle itUp to four portraits that keep the person
POST /v1/generation/voicesA voiceDescription, and optionally language, avatarName and sampleTextVoice previews, each with the text it speaks

Each output comes back as upload:<uploadId>: pass it straight to assets.image.url, assets.voice.url, or a /appearance or /voice replace. You're charged only when at least one output comes back. Never generate a real person's likeness from a description; for a real person, enhance their own photo, with their permission.

Errors

A create that can't start answers 400 with an error and a message naming the problem:

errorMeans
invalid_zip, invalid_manifestThe zip or the manifest is malformed.
invalid_urlA link is not https, carries credentials, or points at a private host.
fetch_failedA link couldn't be downloaded.
upload_not_found, upload_kind_mismatch, invalid_uploadAn upload: value is unknown, of the wrong kind, or not uploaded yet.
preview_message_too_longAn Atmee V2 previewMessage over 60 characters.
public_visibility_not_allowed_on_createCreate it private or unlisted, then make it public.

The full list is in the API reference.

Next steps

Create an avatar — Atmee Docs