Auto-rig / add a character
Upload a 3D character model in FBX or GLB format to use with generated motions.
Step 1: Prepare your character file
- Supported formats:
.fbx,.glb,.gltf - File size must be less than 20MB (100MB for some organizations)
- Keep the file size reasonable to speed up auto-rigging
Step 2: Upload via GraphQL
Use a multipart GraphQL request with the create_character mutation.
- Shell
- Python
- TypeScript
- C#
API_KEY="{{apiKey}}"
CHARACTER_FILE="/path/to/character.fbx"
CHARACTER_NAME="My Character"
curl -X POST https://uthana.com/graphql \
-u $API_KEY: \
-F 'operations={
"query": "mutation ($file: Upload!, $name: String!, $auto_rig: Boolean, $auto_rig_front_facing: Boolean) { create_character(file: $file, name: $name, auto_rig: $auto_rig, auto_rig_front_facing: $auto_rig_front_facing) { character { id name } } }",
"variables": { "file": null, "name": "'"$CHARACTER_NAME"'", "auto_rig": true, "auto_rig_front_facing": true }
}' \
-F 'map={ "0": ["variables.file"] }' \
-F '0=@'"$CHARACTER_FILE"
import json
import requests
API_URL = "https://uthana.com/graphql"
API_KEY = "{{apiKey}}"
CHARACTER_FILE = "/path/to/character.fbx"
CHARACTER_NAME = "My Character"
operations = {
"query": """
mutation ($file: Upload!, $name: String!, $auto_rig: Boolean, $auto_rig_front_facing: Boolean) {
create_character(file: $file, name: $name, auto_rig: $auto_rig, auto_rig_front_facing: $auto_rig_front_facing) {
character { id name }
}
}
""",
"variables": {"file": None, "name": CHARACTER_NAME, "auto_rig": True, "auto_rig_front_facing": True}
}
files = {
"operations": (None, json.dumps(operations)),
"map": (None, json.dumps({"0": ["variables.file"]})),
"0": open(CHARACTER_FILE, "rb"),
}
response = requests.post(API_URL, auth=(API_KEY, ""), files=files)
print(response.json())
const API_URL = "https://uthana.com/graphql";
const API_KEY = "{{apiKey}}";
const CHARACTER_NAME = "My Character";
// Example markup: <input type="file" id="characterFile" accept=".fbx,.glb,.gltf" />
const characterInput = document.querySelector<HTMLInputElement>("#characterFile");
const characterFile = characterInput?.files?.[0];
if (!characterFile) {
throw new Error("Select a character file before uploading.");
}
const formData = new FormData();
formData.append(
"operations",
JSON.stringify({
query: `
mutation ($file: Upload!, $name: String!, $auto_rig: Boolean, $auto_rig_front_facing: Boolean) {
create_character(file: $file, name: $name, auto_rig: $auto_rig, auto_rig_front_facing: $auto_rig_front_facing) {
character { id name }
}
}
`,
variables: { file: null, name: CHARACTER_NAME, auto_rig: true, auto_rig_front_facing: true },
}),
);
formData.append("map", JSON.stringify({ 0: ["variables.file"] }));
formData.append("0", characterFile, characterFile.name);
const authString = btoa(`${API_KEY}:`);
const response = await fetch(API_URL, {
method: "POST",
headers: {
Authorization: `Basic ${authString}`,
},
body: formData,
});
console.log(await response.json());
var operations = new
{
query = @"
mutation ($file: Upload!, $name: String!, $auto_rig: Boolean, $auto_rig_front_facing: Boolean) {
create_character(file: $file, name: $name, auto_rig: $auto_rig, auto_rig_front_facing: $auto_rig_front_facing) {
character { id name }
}
}",
variables = new { file = (object)null, name = "My Character", auto_rig = true, auto_rig_front_facing = true }
};
var map = new { ["0"] = new[] { "variables.file" } };
using var content = new MultipartFormDataContent();
content.Add(new StringContent(JsonSerializer.Serialize(operations), Encoding.UTF8, "application/json"), "operations");
content.Add(new StringContent(JsonSerializer.Serialize(map), Encoding.UTF8, "application/json"), "map");
content.Add(new StreamContent(File.OpenRead("/path/to/character.fbx")), "0", "character.fbx");
var authValue = Convert.ToBase64String(Encoding.UTF8.GetBytes($"{_apiKey}:"));
_httpClient.DefaultRequestHeaders.Authorization =
new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", authValue);
var response = await _httpClient.PostAsync("https://uthana.com/graphql", content);
response.EnsureSuccessStatusCode();
Step 3: Save the character ID
The response includes the character id. Keep it for generating motions and downloads.
Auto-rigging
By default, Uthana automatically attempts to rig characters that don't have a skeleton. Auto-rigging allows you to use characters that weren't originally rigged for animation.
Default behavior
auto_rig:true(default) - Automatically rig the character if no skeleton is foundauto_rig_front_facing:true(default) - Make the auto-rigged character face forward
Timing
- Auto-rigging typically takes 30-60 seconds to complete
- The upload job has a timeout of 5 minutes (300 seconds)
- If your character already has a skeleton, no auto-rigging occurs and the upload is faster
Disabling auto-rigging
If your character already has a skeleton rig, you can disable auto-rigging to speed up the upload:
- Shell
- Python
- TypeScript
- C#
curl -X POST https://uthana.com/graphql \
-u $API_KEY: \
-F 'operations={
"query": "mutation ($file: Upload!, $name: String!, $auto_rig: Boolean) { create_character(file: $file, name: $name, auto_rig: $auto_rig) { character { id name } } }",
"variables": { "file": null, "name": "'"$CHARACTER_NAME"'", "auto_rig": false }
}' \
-F 'map={ "0": ["variables.file"] }' \
-F '0=@'"$CHARACTER_FILE"
operations = {
"query": """
mutation ($file: Upload!, $name: String!, $auto_rig: Boolean) {
create_character(file: $file, name: $name, auto_rig: $auto_rig) {
character { id name }
}
}
""",
"variables": {"file": None, "name": CHARACTER_NAME, "auto_rig": False}
}
variables: { file: null, name: CHARACTER_NAME, auto_rig: false, auto_rig_front_facing: true },
variables = new { file = (object)null, name = "My Character", auto_rig = false, auto_rig_front_facing = true }
Character requirements
Your character must have essential joints for retargeting to work:
- Pelvis
- Left and right hips
- Left and right shoulders
If these joints are missing, the upload will fail with an error.
Known errors
Common errors you may encounter:
- "Only FBX and GLB files are supported" - Your file format is not supported. Use
.fbxor.glbfiles only. - "The provided file is too large, it must be less than [size]MiB" - File size exceeds the limit (default 20MB, 100MB for some organizations). The error message will include the actual size limit.
- "Maximum number of characters reached" - Your organization has reached its character limit. Upgrade your plan or delete unused characters.
- "Essential joints missing. Please ensure your character has a basic bone structure (pelvis, shoulders, hips)." - Your character model lacks required skeleton joints.
- "Auto-rigging failed: [error]" - Auto-rigging encountered an error. The character may not be suitable for automatic rigging (e.g., non-humanoid structure, extreme proportions, or other compatibility issues). The error message will include specific details about what went wrong.
- "Auto-rigging job not done after [timeout] seconds" - Auto-rigging exceeded the timeout. Try uploading a smaller or simpler character model. The error message will include the actual timeout value.
- "No rig found in scene. Please upload a rigged character." - No skeleton was found and auto-rigging was disabled or failed.
Related docs
- Asset management for full character and motion workflows