curl --request POST \
--url https://apis.viggle.ai/v1/motions/import \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"template_id": "<string>",
"template_uuid": "<string>",
"name": "<string>",
"model": "V3_Preview"
}
'import requests
url = "https://apis.viggle.ai/v1/motions/import"
payload = {
"template_id": "<string>",
"template_uuid": "<string>",
"name": "<string>",
"model": "V3_Preview"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
template_id: '<string>',
template_uuid: '<string>',
name: '<string>',
model: 'V3_Preview'
})
};
fetch('https://apis.viggle.ai/v1/motions/import', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://apis.viggle.ai/v1/motions/import",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'template_id' => '<string>',
'template_uuid' => '<string>',
'name' => '<string>',
'model' => 'V3_Preview'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://apis.viggle.ai/v1/motions/import"
payload := strings.NewReader("{\n \"template_id\": \"<string>\",\n \"template_uuid\": \"<string>\",\n \"name\": \"<string>\",\n \"model\": \"V3_Preview\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://apis.viggle.ai/v1/motions/import")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"template_id\": \"<string>\",\n \"template_uuid\": \"<string>\",\n \"name\": \"<string>\",\n \"model\": \"V3_Preview\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://apis.viggle.ai/v1/motions/import")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"template_id\": \"<string>\",\n \"template_uuid\": \"<string>\",\n \"name\": \"<string>\",\n \"model\": \"V3_Preview\"\n}"
response = http.request(request)
puts response.read_body{
"id": "<string>",
"status": "queued",
"name": "<string>",
"progress": 50,
"capabilities": [
"<string>"
],
"created_at": "<string>",
"completed_at": "<string>",
"error": {
"code": "<string>",
"message": "<string>",
"request_id": "<string>"
},
"type": "render",
"vsplat": {
"status": "queued",
"error": {
"code": "<string>",
"message": "<string>",
"request_id": "<string>"
}
},
"glb": {
"status": "queued",
"skeletons": [
"mixamo"
],
"error": {
"code": "<string>",
"message": "<string>",
"request_id": "<string>"
}
}
}{
"error": {
"code": "authentication_required",
"message": "<string>",
"request_id": "<string>"
}
}{
"error": {
"code": "authentication_required",
"message": "<string>",
"request_id": "<string>"
}
}{
"error": {
"code": "authentication_required",
"message": "<string>",
"request_id": "<string>"
}
}{
"error": {
"code": "authentication_required",
"message": "<string>",
"request_id": "<string>"
}
}{
"error": {
"code": "authentication_required",
"message": "<string>",
"request_id": "<string>"
}
}{
"error": {
"code": "authentication_required",
"message": "<string>",
"request_id": "<string>"
}
}Import Motion
Create a reusable Motion from an official Viggle motion template.
curl --request POST \
--url https://apis.viggle.ai/v1/motions/import \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"template_id": "<string>",
"template_uuid": "<string>",
"name": "<string>",
"model": "V3_Preview"
}
'import requests
url = "https://apis.viggle.ai/v1/motions/import"
payload = {
"template_id": "<string>",
"template_uuid": "<string>",
"name": "<string>",
"model": "V3_Preview"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
template_id: '<string>',
template_uuid: '<string>',
name: '<string>',
model: 'V3_Preview'
})
};
fetch('https://apis.viggle.ai/v1/motions/import', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://apis.viggle.ai/v1/motions/import",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'template_id' => '<string>',
'template_uuid' => '<string>',
'name' => '<string>',
'model' => 'V3_Preview'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://apis.viggle.ai/v1/motions/import"
payload := strings.NewReader("{\n \"template_id\": \"<string>\",\n \"template_uuid\": \"<string>\",\n \"name\": \"<string>\",\n \"model\": \"V3_Preview\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://apis.viggle.ai/v1/motions/import")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"template_id\": \"<string>\",\n \"template_uuid\": \"<string>\",\n \"name\": \"<string>\",\n \"model\": \"V3_Preview\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://apis.viggle.ai/v1/motions/import")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"template_id\": \"<string>\",\n \"template_uuid\": \"<string>\",\n \"name\": \"<string>\",\n \"model\": \"V3_Preview\"\n}"
response = http.request(request)
puts response.read_body{
"id": "<string>",
"status": "queued",
"name": "<string>",
"progress": 50,
"capabilities": [
"<string>"
],
"created_at": "<string>",
"completed_at": "<string>",
"error": {
"code": "<string>",
"message": "<string>",
"request_id": "<string>"
},
"type": "render",
"vsplat": {
"status": "queued",
"error": {
"code": "<string>",
"message": "<string>",
"request_id": "<string>"
}
},
"glb": {
"status": "queued",
"skeletons": [
"mixamo"
],
"error": {
"code": "<string>",
"message": "<string>",
"request_id": "<string>"
}
}
}{
"error": {
"code": "authentication_required",
"message": "<string>",
"request_id": "<string>"
}
}{
"error": {
"code": "authentication_required",
"message": "<string>",
"request_id": "<string>"
}
}{
"error": {
"code": "authentication_required",
"message": "<string>",
"request_id": "<string>"
}
}{
"error": {
"code": "authentication_required",
"message": "<string>",
"request_id": "<string>"
}
}{
"error": {
"code": "authentication_required",
"message": "<string>",
"request_id": "<string>"
}
}{
"error": {
"code": "authentication_required",
"message": "<string>",
"request_id": "<string>"
}
}template_id into a Motion asset owned by the calling principal.
Request parameters
Send a JSON body.| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
template_id | string | One of | — | ID of the official Viggle motion template to copy into the caller’s assets. Preferred for new integrations; supply either this field or template_uuid. |
template_uuid | string | One of | — | Backward-compatible alias for template_id. Supply one template identifier rather than sending both fields. |
name | string | No | Imported: + first 8 characters of the template ID | Optional display label for the imported Motion. When omitted, the service derives the default from the selected template ID. |
model | string | No | V3_Preview | Render model associated with the imported motion: V3_Preview or V4_BaseSG; V4_Preview is accepted as a backward-compatible alias for V4_BaseSG. |
template_id in new integrations; unknown properties are ignored.
Response parameters
Returns200 OK. Only id and status carry information here; name and created_at are populated from Get Motion. See Create Motion for the field-by-field definition of the full Motion object.
{"id":"mot_550e8400-e29b-41d4-a716-446655440000","status":"queued","name":"","progress":0,"capabilities":[],"created_at":null,"completed_at":null,"error":null,"type":"render","vsplat":null,"glb":null}
Examples
payload := strings.NewReader(`{"template_id":"YOUR_TEMPLATE_ID","name":"Campaign dance"}`)
req, _ := http.NewRequest("POST", "https://apis.viggle.ai/v1/motions/import", payload)
req.Header.Set("Authorization", "Bearer "+os.Getenv("VIGGLE_API_KEY")); req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req); if err != nil { panic(err) }; defer resp.Body.Close()
const response = await fetch("https://apis.viggle.ai/v1/motions/import", {method:"POST", headers:{Authorization:`Bearer ${process.env.VIGGLE_API_KEY}`,"Content-Type":"application/json"}, body:JSON.stringify({template_id:"YOUR_TEMPLATE_ID",name:"Campaign dance"})});
const motion = await response.json();
import os, requests
response = requests.post("https://apis.viggle.ai/v1/motions/import", headers={"Authorization":f"Bearer {os.environ['VIGGLE_API_KEY']}"}, json={"template_id":"YOUR_TEMPLATE_ID","name":"Campaign dance"})
response.raise_for_status(); motion = response.json()
curl -X POST "https://apis.viggle.ai/v1/motions/import" -H "Authorization: Bearer $VIGGLE_API_KEY" -H "Content-Type: application/json" -d '{"template_id":"YOUR_TEMPLATE_ID","name":"Campaign dance"}'
Authorizations
Server-side SDK clients use a project API key. Remote MCP clients use an OAuth access token. Never expose a project API key in browser code.
Headers
Optional caller-supplied correlation ID, up to 128 characters. The service returns the effective value in the response header for tracing and support.
1 - 128Optional source-channel label, up to 128 characters, used to attribute traffic to an SDK, integration, product surface, or internal workflow.
1 - 128Body
- Option 1
- Option 2
template_uuid is an accepted alias for template_id; supply one of
them. Unknown properties are ignored. Costs 1 credit per second of
the source template's duration, with a minimum of 1 credit.
ID of the official Viggle motion template to copy into the caller's assets. Supply either this field or template_uuid.
1Backward-compatible alias for template_id. Supply one identifier field, not both.
1Optional display name for the imported Motion. When omitted, it defaults to Imported: followed by the first eight characters of the template ID.
Render model associated with the imported motion. Choose V3_Preview or V4_BaseSG; V4_Preview is accepted as a backward-compatible alias for V4_BaseSG. Defaults to V3_Preview.
V3_Preview, V4_BaseSG, V4_Preview Response
Motion queued. Only id and status carry information here;
name and created_at are populated from
GET /v1/motions/{motion_id}.
A character or motion asset. Both resources share one wire shape.
progress is null in list responses. error is always null, including
on a failed asset: read status to detect failure.
type reflects what was requested at creation. For characters it is
render, vsplat, or all; for motions it is render, glb,
or all. Assets created before type existed report render.
vsplat and glb carry that extraction's own status — never
download URLs, which come from GET /v1/characters/{character_id}/export
or GET /v1/motions/{motion_id}/export instead — and are null unless
type requested that extraction. On an all asset, the top-level
status only reaches ready once both the 2D render and the 3D
extraction have; if either fails, the top-level status is failed
while the sub-object's own status still shows which one it was.
Public asset identifier. Character IDs normally begin with char_; Motion IDs normally begin with mot_.
1Overall lifecycle of the asset. Use an asset for rendering or export only after the required capability becomes ready.
queued, processing, ready, failed, cancelled Display name supplied at creation or derived during import; it may be empty when a workflow does not accept a name.
Best-effort processing percentage from 0 through 100 on detail responses; null in list responses or when unavailable.
0 <= x <= 100What the asset can be used for. video_render appears once the
asset is ready.
ISO 8601 timestamp with a UTC offset, for example 2026-07-31T09:15:22+00:00.
ISO 8601 timestamp with a UTC offset when all requested processing reached a terminal state; null while work is active.
Reserved top-level failure detail. It is currently always null; detect failure from status and inspect extraction sub-objects when applicable.
Show child attributes
Show child attributes
Work requested when the asset was created. render produces the 2D render-ready asset, vsplat/glb requests 3D output, and all requests both supported outputs.
render, vsplat, glb, all Character vsplat extraction status. Null for motions, and for
characters whose type is render. The request parameters
(model_precision, etc.) submitted at creation are not echoed
back here — this is status only.
Show child attributes
Show child attributes
Motion 3D animation extraction/generation status. Null for
characters, and for motions whose type is render.
Show child attributes
Show child attributes

