TypeScript examples
fetch
const API_URL = "https://uthana.com/graphql";
const API_KEY = "YOUR_API_KEY";
async function getMotion(motionId: string) {
// Encode API key for Basic auth
const authString = btoa(`${API_KEY}:`);
const res = await fetch(API_URL, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Basic ${authString}`,
},
body: JSON.stringify({
query: `
query GetMotion($id: String!) {
motion(id: $id) {
id
name
created
}
}
`,
variables: { id: motionId },
}),
});
const json = await res.json();
return json.data.motion;
}
// Usage
getMotion("m3G3XSJrjEJH").then(console.log);
React Query + graphql-request
import { GraphQLClient, gql } from "graphql-request";
import { useQuery } from "@tanstack/react-query";
const API_URL = "https://uthana.com/graphql";
const API_KEY = "YOUR_API_KEY";
// Encode API key for Basic auth
const authString = btoa(`${API_KEY}:`);
const client = new GraphQLClient(API_URL, {
headers: {
Authorization: `Basic ${authString}`,
},
});
const GetMotion = gql`
query GetMotion($id: String!) {
motion(id: $id) {
id
name
created
}
}
`;
export function useMotion(motionId: string) {
return useQuery({
queryKey: ["motion", motionId],
queryFn: async () => {
const data = await client.request(GetMotion, { id: motionId });
return data.motion;
},
enabled: !!motionId,
});
}
// Usage in a component:
// const { data, isLoading } = useMotion('m3G3XSJrjEJH');
Apollo Client
import { ApolloClient, InMemoryCache, gql } from "@apollo/client";
// Encode API key for Basic auth
const authString = btoa(`YOUR_API_KEY:`);
const client = new ApolloClient({
uri: "https://uthana.com/graphql",
cache: new InMemoryCache(),
headers: {
Authorization: `Basic ${authString}`,
},
});
const GET_MOTION = gql`
query GetMotion($id: String!) {
motion(id: $id) {
id
name
created
}
}
`;
// Usage:
client
.query({
query: GET_MOTION,
variables: { id: "m3G3XSJrjEJH" },
})
.then((result) => {
console.log(result.data.motion);
});
Downloading motions
Download a motion with character mesh
const API_KEY = "YOUR_API_KEY";
const CHARACTER_ID = "your-character-id";
const MOTION_ID = "your-motion-id";
// Encode API key for Basic auth
const authString = btoa(`${API_KEY}:`);
async function downloadMotion(characterId: string, motionId: string, format: "fbx" | "glb") {
const url = `https://uthana.com/motion/file/motion_viewer/${characterId}/${motionId}/${format}/${characterId}-${motionId}.${format}`;
const response = await fetch(url, {
headers: {
Authorization: `Basic ${authString}`,
},
});
if (!response.ok) {
throw new Error(`Failed to download motion: ${response.statusText}`);
}
const blob = await response.blob();
return blob;
}
// Usage:
// const fbxBlob = await downloadMotion(CHARACTER_ID, MOTION_ID, 'fbx');
// const glbBlob = await downloadMotion(CHARACTER_ID, MOTION_ID, 'glb');
Download a motion-only GLB (without character mesh)
const API_KEY = "YOUR_API_KEY";
const CHARACTER_ID = "your-character-id";
const MOTION_ID = "your-motion-id";
const APP_ID = "motion_viewer"; // or 'training'
// Encode API key for Basic auth
const authString = btoa(`${API_KEY}:`);
async function downloadMotionOnlyGlb(characterId: string, motionId: string, appId: string = "motion_viewer") {
const url = `https://uthana.com/motion/animation/${appId}/${characterId}/${motionId}/glb/${characterId}-${motionId}.glb`;
const response = await fetch(url, {
headers: {
Authorization: `Basic ${authString}`,
},
});
if (!response.ok) {
throw new Error(`Failed to download motion-only GLB: ${response.statusText}`);
}
const blob = await response.blob();
return blob;
}
// Usage:
// const motionOnlyBlob = await downloadMotionOnlyGlb(CHARACTER_ID, MOTION_ID, APP_ID);
// Motion-only GLB files contain animation data without the character mesh. The character ID is required to ensure the correct skeleton is used.