Docs index: /llms.txt · every page as Markdown: add .md

‹ API reference

Gestures API

Generate gestures (wave, nod, laugh) for an Essence 1 avatar, and trigger them.

Overview

Gestures are conversational animations (wave, nod, laugh, idle motions) for an Essence 1 avatar; the API paths use the word dynamics. Generate them asynchronously, then toggle them on to make the gesture model the active one for live sessions. During conversation, gestures fire automatically on keyword mapping — or you can trigger an exact gesture from your code. Dynamics generation costs 250 credits.

Trigger a specific gesture from your code — in either mode. Self-hosted: runtime.push(VideoControl(action="…")). Managed cloud: send a trigger_dynamics RPC to the avatar participant (avatar.avatar_identity). Both are deterministic — no keyword, no randomness. See Trigger gestures from code.

Generate dynamics

POST /v1/dynamics/generate generateDynamics

Generate movements for an agent. Returns immediately with processing; use the GET endpoint to check completion.

ParameterTypeRequiredDefaultDescription
agent_idstringyes—Agent ID to generate dynamics for.
image_urlstringnofrom agentSource image URL. Defaults to the agent’s primary image.
durationnumberno5Duration of each motion in seconds.

Duration guidance: 1–3 s for quick gestures (waves, nods), 3–5 s for standard motions (default), 5–10 s for extended animations.

curl

curl -X POST https://api.bithuman.ai/v1/dynamics/generate \
  -H "Content-Type: application/json" -H "api-secret: $BITHUMAN_API_SECRET" \
  -d '{"agent_id": "A80HVD8577", "duration": 5}'

Python

import os, requests

resp = requests.post(
    "https://api.bithuman.ai/v1/dynamics/generate",
    headers={"api-secret": os.environ["BITHUMAN_API_SECRET"]},
    json={"agent_id": "A80HVD8577", "duration": 5},
)
print(resp.json())

Node

const resp = await fetch("https://api.bithuman.ai/v1/dynamics/generate", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "api-secret": process.env.BITHUMAN_API_SECRET,
  },
  body: JSON.stringify({ agent_id: "A80HVD8577", duration: 5 }),
});
console.log(await resp.json());
{
  "success": true,
  "message": "Dynamics generation started",
  "agent_id": "A80HVD8577",
  "status": "processing"
}

Get dynamics

GET /v1/dynamics/{agent_id} getDynamics

List the current dynamics configuration and available gestures for an agent.

The gesture names are the keys of data.gestures.

FieldTypeDescription
urlstring | nullURL to the dynamics model file, or null if not yet generated.
statusstringgenerating while in progress, ready when complete. Also returned as ready (with url: null and empty gestures) for agents whose dynamics were never generated — treat url != null, not status, as the has-dynamics signal.
agent_idstringThe agent ID.
gesturesobjectMap of gesture action name → video URL.

Before generation completes, url is null and gestures is an empty object.

curl

curl https://api.bithuman.ai/v1/dynamics/A80HVD8577 -H "api-secret: $BITHUMAN_API_SECRET"

Python

import os, requests

resp = requests.get(
    "https://api.bithuman.ai/v1/dynamics/A80HVD8577",
    headers={"api-secret": os.environ["BITHUMAN_API_SECRET"]},
)
print(resp.json())

Node

const resp = await fetch("https://api.bithuman.ai/v1/dynamics/A80HVD8577", {
  headers: { "api-secret": process.env.BITHUMAN_API_SECRET },
});
console.log(await resp.json());
{
  "success": true,
  "data": {
    "url": "https://assets.bithuman.ai/A80HVD8577/my_agent_20260115_103500_000003.imx",
    "status": "ready",
    "agent_id": "A80HVD8577",
    "gestures": {
      "mini_wave_hello": "https://assets.bithuman.ai/A80HVD8577/mini_wave_hello_20260115_104000_000004.mp4",
      "talk_head_nod_subtle": "https://assets.bithuman.ai/A80HVD8577/talk_head_nod_subtle_20260115_104100_000005.mp4",
      "blow_kiss_heart": "https://assets.bithuman.ai/A80HVD8577/blow_kiss_heart_20260115_104200_000006.mp4"
    }
  }
}

Update dynamics

PUT /v1/dynamics/{agent_id} updateDynamics

Update the gestures configuration. After a successful update, the avatar’s idle motion is regenerated automatically.

ParameterTypeRequiredDescription
dynamicsobjectyesConfiguration to merge with existing data.
dynamics.enabledbooleannoEnable or disable dynamics for this agent.
toggle_enabledbooleannotrue turns gestures on for live sessions; false turns them off.

If regeneration fails to start, regeneration_status is failed and a regeneration_error message is included.

curl

curl -X PUT https://api.bithuman.ai/v1/dynamics/A80HVD8577 -H "api-secret: $BITHUMAN_API_SECRET" \
  -H "Content-Type: application/json" -d '{"dynamics": {"enabled": true}, "toggle_enabled": true}'

Python

import os, requests

resp = requests.put(
    "https://api.bithuman.ai/v1/dynamics/A80HVD8577",
    headers={"api-secret": os.environ["BITHUMAN_API_SECRET"]},
    json={"dynamics": {"enabled": True}, "toggle_enabled": True},
)
print(resp.json())

Node

const resp = await fetch("https://api.bithuman.ai/v1/dynamics/A80HVD8577", {
  method: "PUT",
  headers: {
    "api-secret": process.env.BITHUMAN_API_SECRET,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ dynamics: { enabled: true }, toggle_enabled: true }),
});
console.log(await resp.json());
{
  "success": true,
  "message": "Dynamics updated successfully and movements regeneration started",
  "agent_id": "A80HVD8577",
  "regeneration_status": "started"
}

Gesture names

Generated gestures use descriptive action identifiers. The exact set depends on what was generated — call GET /v1/dynamics/{agent_id} to discover them.

Gesture actionCategoryTypical use
mini_wave_hellowaveGreeting
talk_head_nod_subtlenodAgreement, acknowledgment
blow_kiss_heartexpressionPlayful reaction
laugh_reactexpressionHumor response
idle_subtleidleBackground movement

These action names are what you pass to VideoControl(action=...) or the trigger_dynamics RPC in a live session.

Error codes

HTTPMeaning
400Invalid parameters.
401Unauthorized.
402Insufficient credits.
404Agent not found. (An agent without dynamics is not a 404 — GET /v1/dynamics/{agent_id} returns 200 with url: null.)
500Internal server error.

See the full error reference and the interactive API reference.