cURL examples
Uthana provides a powerful GraphQL API for all programmatic access to animation, character, and motion data. There is no REST API—all features are available via GraphQL.
This guide shows how to use curl
to interact with the GraphQL API, including authentication, queries, mutations, and file uploads.
Endpoint
https://uthana.com/graphql
Authentication
Use the -u
flag to authenticate with your API key:
curl -s "https://uthana.com/graphql" \
-u YOUR_API_KEY: \
-H 'Accept: application/json' \
-H 'Content-Type: application/json' \
--data-raw '{<your-query-or-mutation>}'
or include your API key in the basic Authorization
header, base64-encoded with a colon:
AUTH_STRING=$(echo -n "<your-api-key>:" | base64)
curl -H "Authorization: Basic $AUTH_STRING" \
https://uthana.com/graphql
or as a query parameter:
curl 'https://uthana.com/graphql?api_key=<your-api-key>'
Making GraphQL queries with cURL
Send a POST request with your query or mutation in the JSON body:
Get motion details
curl -X POST https://uthana.com/graphql \
-u <your-api-key>: \
-H "Content-Type: application/json" \
-d '{
"query": "query GetMotion($id: String!) { motion(id: $id) { id name created } }",
"variables": { "id": "m3G3XSJrjEJH" }
}'
Download a motion
To download a motion file (fbx
or glb
), use the following endpoint:
https://uthana.com/motion/file/motion_viewer/{character_id}/{motion_id}/{type}/{character_id}-{motion_id}.{type}
- app_id: The application context (always use
motion_viewer
) - character_id: The character's ID
- motion_id: The motion's ID
- type: The file type/format (
fbx
,glb
)
Download a motion as FBX
curl -L "https://uthana.com/motion/file/motion_viewer/<character-id>/<motion-id>/fbx/<character-id>-<motion-id>.fbx" \
-u <your-api-key>: \
-o motion.fbx
- Replace
<character-id>
and<motion-id>
with your actual IDs. - The
-L
flag follows redirects (if any). - The
-o
flag saves the file asmotion.fbx
.
Generate motion from text (text-to-motion)
curl -X POST https://uthana.com/graphql \
-u <your-api-key>: \
-H "Content-Type: application/json" \
-d '{
"query": "mutation CreateTextToMotion($character_id: String!, $prompt: String!) { create_text_to_motion(character_id: $character_id, prompt: $prompt) { ok job_id motion { id name } } }",
"variables": { "character_id": "<your-character-id>", "prompt": "walk casually" }
}'
Upload files (multipart/form-data)
To upload files (e.g., for create_character
or create_video_to_motion
), use the GraphQL multipart request spec:
Upload a character
curl -X POST https://uthana.com/graphql \
-u <your-api-key>: \
-F 'operations={
"query": "mutation ($file: Upload!, $name: String!) { create_character(file: $file, name: $name) { ok character_id } }",
"variables": { "file": null, "name": "My Character" }
}' \
-F 'map={ "0": ["variables.file"] }' \
-F '0=@/path/to/character.fbx'
Complete examples
Create a text-to-motion job and download the motion as FBX and GLB
#!/bin/bash
set -eo pipefail
# Set your API key and character ID for easy reuse
UTHANA_APIKEY=<your-api-key>
HOST="uthana.com"
CHARACTER_ID=<your-character-id>
# Create a text-to-motion job
RES="$(curl -s "https://$HOST/graphql" \
-u $UTHANA_APIKEY: \
-H 'Accept: application/json' \
-H 'Content-Type: application/json' \
--data-raw $'{"query":"mutation CreateTextToMotion($character_id: String!, $model: String!, $prompt: String!) {create_text_to_motion(character_id: $character_id, model: $model, prompt: $prompt) {motion{id name}}}","variables":{"character_id":"'"$CHARACTER_ID"'","model":"text-to-motion","prompt":"a person runs in a circle"},"operationName":"CreateTextToMotion"}'
)"
echo $RES
MOTION_ID="$(echo $RES | jq -r .data.create_text_to_motion.motion.id)"
echo "motion_id: $MOTION_ID"
# Download the motion as FBX
curl -s --remote-name "https://$HOST/motion/file/motion_viewer/$CHARACTER_ID/$MOTION_ID/fbx/$CHARACTER_ID-$MOTION_ID.fbx" \
-u $UTHANA_APIKEY:
# Download the motion as GLB
curl -s --remote-name "https://$HOST/motion/file/motion_viewer/$CHARACTER_ID/$MOTION_ID/glb/$CHARACTER_ID-$MOTION_ID.glb" \
-u $UTHANA_APIKEY:
# View the motion in the Uthana Web UI
echo "https://$HOST/app/play/$CHARACTER_ID/$MOTION_ID"
Upload a character
#!/bin/bash
set -eo pipefail
# Set your API key and character ID for easy reuse
UTHANA_APIKEY=<your-api-key>
HOST="uthana.com"
CHARACTER_NAME="My Character"
# Your existing fbx or glb file – ensure it has a rigged skeleton
FILE="$1"
if [ ! -e "$FILE" ]; then
echo "$FILE is missing?"
fi
# Upload & create character
# In this request we auto-retarget to our internal skeleton, so the first time
# we see a skeleton this might be slow, but if you use the same skeleton again,
# it should be faster. Please contact us if you have issues during this process.
# You can also include a motion prompt to generate a motion from text in the same
# request, or omit `prompt` to just create the character.
RES="$(curl -s -X POST "https://$HOST/graphql" \
-u $UTHANA_APIKEY: \
-H 'Accept: application/json' \
--form $'operations={"query":"mutation CreateCharacter($file: Upload!, $name: String!) {\\n create_character(file: $file, name: $name) {character_id motion_id}\\n}","variables":{"file":null,"name":"'"$CHARACTER_NAME"'","prompt":"a person runs in a circle"},"operationName":"CreateCharacter"}' \
--form 'map={ "nFile": ["variables.file"] }' \
--form nFile=@$FILE
)"
echo $RES
CHARACTER_ID="$(echo $RES | jq -r .data.create_character.character_id)"
MOTION_ID="$(echo $RES | jq -r .data.create_character.motion_id)"
# List existing characters
curl -s "https://$HOST/graphql" \
-u $UTHANA_APIKEY: \
-H 'Accept: application/json' \
-H 'Content-Type: application/json' \
--data-raw $'{"query":"{ characters { id name created } }"}'
# View the character in the Uthana Web UI
echo "https://$HOST/app/play/$CHARACTER_ID/$MOTION_ID"
Error handling
Errors are returned in the errors
array of the GraphQL response:
{
"errors": [
{
"message": "Rate limit exceeded",
"extensions": {
"code": "RATE_LIMIT_EXCEEDED",
"resetAt": "2025-01-01T00:00:00Z"
}
}
]
}
Rate limits
Rate limits are enforced on a per-organization basis. Contact the Uthana team to discuss your needs.