curl --request POST \
--url https://apis.viggle.ai/v1/characters \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: multipart/form-data' \
--form image=@example-file \
--form 'image_url=<string>' \
--form 'ref_url=<string>' \
--form name= \
--form type=render \
--form variant=optimized \
--form enhance=true \
--form joint_set=body \
--form model_precision=0.5 \
--form quality=0.7 \
--form filter_low_quality=true \
--form prune_preset=balanced \
--form prune_budget=1 \
--form use_sparse_W=false \
--form 'scale_parts=<string>' \
--form render_thumbnail=false \
--form 'task_id=<string>'import requests
url = "https://apis.viggle.ai/v1/characters"
files = { "image": ("example-file", open("example-file", "rb")) }
payload = {
"image_url": "<string>",
"ref_url": "<string>",
"name": "",
"type": "render",
"variant": "optimized",
"enhance": "true",
"joint_set": "body",
"model_precision": "0.5",
"quality": "0.7",
"filter_low_quality": "true",
"prune_preset": "balanced",
"prune_budget": "1",
"use_sparse_W": "false",
"scale_parts": "<string>",
"render_thumbnail": "false",
"task_id": "<string>"
}
headers = {"Authorization": "Bearer <token>"}
response = requests.post(url, data=payload, files=files, headers=headers)
print(response.text)const form = new FormData();
form.append('image', '<string>');
form.append('image_url', '<string>');
form.append('ref_url', '<string>');
form.append('name', '');
form.append('type', 'render');
form.append('variant', 'optimized');
form.append('enhance', 'true');
form.append('joint_set', 'body');
form.append('model_precision', '0.5');
form.append('quality', '0.7');
form.append('filter_low_quality', 'true');
form.append('prune_preset', 'balanced');
form.append('prune_budget', '1');
form.append('use_sparse_W', 'false');
form.append('scale_parts', '<string>');
form.append('render_thumbnail', 'false');
form.append('task_id', '<string>');
const options = {method: 'POST', headers: {Authorization: 'Bearer <token>'}};
options.body = form;
fetch('https://apis.viggle.ai/v1/characters', 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/characters",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"image_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"ref_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"name\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"type\"\r\n\r\nrender\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"variant\"\r\n\r\noptimized\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"enhance\"\r\n\r\ntrue\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"joint_set\"\r\n\r\nbody\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"model_precision\"\r\n\r\n0.5\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"quality\"\r\n\r\n0.7\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"filter_low_quality\"\r\n\r\ntrue\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"prune_preset\"\r\n\r\nbalanced\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"prune_budget\"\r\n\r\n1\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"use_sparse_W\"\r\n\r\nfalse\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"scale_parts\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"render_thumbnail\"\r\n\r\nfalse\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"task_id\"\r\n\r\n<string>\r\n-----011000010111000001101001--",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: multipart/form-data"
],
]);
$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/characters"
payload := strings.NewReader("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"image_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"ref_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"name\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"type\"\r\n\r\nrender\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"variant\"\r\n\r\noptimized\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"enhance\"\r\n\r\ntrue\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"joint_set\"\r\n\r\nbody\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"model_precision\"\r\n\r\n0.5\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"quality\"\r\n\r\n0.7\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"filter_low_quality\"\r\n\r\ntrue\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"prune_preset\"\r\n\r\nbalanced\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"prune_budget\"\r\n\r\n1\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"use_sparse_W\"\r\n\r\nfalse\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"scale_parts\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"render_thumbnail\"\r\n\r\nfalse\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"task_id\"\r\n\r\n<string>\r\n-----011000010111000001101001--")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
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/characters")
.header("Authorization", "Bearer <token>")
.body("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"image_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"ref_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"name\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"type\"\r\n\r\nrender\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"variant\"\r\n\r\noptimized\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"enhance\"\r\n\r\ntrue\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"joint_set\"\r\n\r\nbody\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"model_precision\"\r\n\r\n0.5\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"quality\"\r\n\r\n0.7\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"filter_low_quality\"\r\n\r\ntrue\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"prune_preset\"\r\n\r\nbalanced\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"prune_budget\"\r\n\r\n1\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"use_sparse_W\"\r\n\r\nfalse\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"scale_parts\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"render_thumbnail\"\r\n\r\nfalse\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"task_id\"\r\n\r\n<string>\r\n-----011000010111000001101001--")
.asString();require 'uri'
require 'net/http'
url = URI("https://apis.viggle.ai/v1/characters")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request.body = "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"image_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"ref_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"name\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"type\"\r\n\r\nrender\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"variant\"\r\n\r\noptimized\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"enhance\"\r\n\r\ntrue\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"joint_set\"\r\n\r\nbody\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"model_precision\"\r\n\r\n0.5\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"quality\"\r\n\r\n0.7\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"filter_low_quality\"\r\n\r\ntrue\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"prune_preset\"\r\n\r\nbalanced\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"prune_budget\"\r\n\r\n1\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"use_sparse_W\"\r\n\r\nfalse\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"scale_parts\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"render_thumbnail\"\r\n\r\nfalse\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"task_id\"\r\n\r\n<string>\r\n-----011000010111000001101001--"
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>"
}
}{
"error": {
"code": "authentication_required",
"message": "<string>",
"request_id": "<string>"
}
}{
"error": {
"code": "authentication_required",
"message": "<string>",
"request_id": "<string>"
}
}Create Character (from Image)
Create a reusable Character from an image, optionally extracting a 3D vsplat.
curl --request POST \
--url https://apis.viggle.ai/v1/characters \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: multipart/form-data' \
--form image=@example-file \
--form 'image_url=<string>' \
--form 'ref_url=<string>' \
--form name= \
--form type=render \
--form variant=optimized \
--form enhance=true \
--form joint_set=body \
--form model_precision=0.5 \
--form quality=0.7 \
--form filter_low_quality=true \
--form prune_preset=balanced \
--form prune_budget=1 \
--form use_sparse_W=false \
--form 'scale_parts=<string>' \
--form render_thumbnail=false \
--form 'task_id=<string>'import requests
url = "https://apis.viggle.ai/v1/characters"
files = { "image": ("example-file", open("example-file", "rb")) }
payload = {
"image_url": "<string>",
"ref_url": "<string>",
"name": "",
"type": "render",
"variant": "optimized",
"enhance": "true",
"joint_set": "body",
"model_precision": "0.5",
"quality": "0.7",
"filter_low_quality": "true",
"prune_preset": "balanced",
"prune_budget": "1",
"use_sparse_W": "false",
"scale_parts": "<string>",
"render_thumbnail": "false",
"task_id": "<string>"
}
headers = {"Authorization": "Bearer <token>"}
response = requests.post(url, data=payload, files=files, headers=headers)
print(response.text)const form = new FormData();
form.append('image', '<string>');
form.append('image_url', '<string>');
form.append('ref_url', '<string>');
form.append('name', '');
form.append('type', 'render');
form.append('variant', 'optimized');
form.append('enhance', 'true');
form.append('joint_set', 'body');
form.append('model_precision', '0.5');
form.append('quality', '0.7');
form.append('filter_low_quality', 'true');
form.append('prune_preset', 'balanced');
form.append('prune_budget', '1');
form.append('use_sparse_W', 'false');
form.append('scale_parts', '<string>');
form.append('render_thumbnail', 'false');
form.append('task_id', '<string>');
const options = {method: 'POST', headers: {Authorization: 'Bearer <token>'}};
options.body = form;
fetch('https://apis.viggle.ai/v1/characters', 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/characters",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"image_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"ref_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"name\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"type\"\r\n\r\nrender\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"variant\"\r\n\r\noptimized\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"enhance\"\r\n\r\ntrue\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"joint_set\"\r\n\r\nbody\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"model_precision\"\r\n\r\n0.5\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"quality\"\r\n\r\n0.7\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"filter_low_quality\"\r\n\r\ntrue\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"prune_preset\"\r\n\r\nbalanced\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"prune_budget\"\r\n\r\n1\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"use_sparse_W\"\r\n\r\nfalse\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"scale_parts\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"render_thumbnail\"\r\n\r\nfalse\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"task_id\"\r\n\r\n<string>\r\n-----011000010111000001101001--",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: multipart/form-data"
],
]);
$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/characters"
payload := strings.NewReader("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"image_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"ref_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"name\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"type\"\r\n\r\nrender\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"variant\"\r\n\r\noptimized\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"enhance\"\r\n\r\ntrue\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"joint_set\"\r\n\r\nbody\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"model_precision\"\r\n\r\n0.5\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"quality\"\r\n\r\n0.7\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"filter_low_quality\"\r\n\r\ntrue\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"prune_preset\"\r\n\r\nbalanced\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"prune_budget\"\r\n\r\n1\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"use_sparse_W\"\r\n\r\nfalse\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"scale_parts\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"render_thumbnail\"\r\n\r\nfalse\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"task_id\"\r\n\r\n<string>\r\n-----011000010111000001101001--")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
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/characters")
.header("Authorization", "Bearer <token>")
.body("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"image_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"ref_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"name\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"type\"\r\n\r\nrender\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"variant\"\r\n\r\noptimized\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"enhance\"\r\n\r\ntrue\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"joint_set\"\r\n\r\nbody\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"model_precision\"\r\n\r\n0.5\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"quality\"\r\n\r\n0.7\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"filter_low_quality\"\r\n\r\ntrue\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"prune_preset\"\r\n\r\nbalanced\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"prune_budget\"\r\n\r\n1\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"use_sparse_W\"\r\n\r\nfalse\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"scale_parts\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"render_thumbnail\"\r\n\r\nfalse\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"task_id\"\r\n\r\n<string>\r\n-----011000010111000001101001--")
.asString();require 'uri'
require 'net/http'
url = URI("https://apis.viggle.ai/v1/characters")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request.body = "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"image_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"ref_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"name\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"type\"\r\n\r\nrender\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"variant\"\r\n\r\noptimized\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"enhance\"\r\n\r\ntrue\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"joint_set\"\r\n\r\nbody\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"model_precision\"\r\n\r\n0.5\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"quality\"\r\n\r\n0.7\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"filter_low_quality\"\r\n\r\ntrue\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"prune_preset\"\r\n\r\nbalanced\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"prune_budget\"\r\n\r\n1\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"use_sparse_W\"\r\n\r\nfalse\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"scale_parts\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"render_thumbnail\"\r\n\r\nfalse\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"task_id\"\r\n\r\n<string>\r\n-----011000010111000001101001--"
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>"
}
}{
"error": {
"code": "authentication_required",
"message": "<string>",
"request_id": "<string>"
}
}{
"error": {
"code": "authentication_required",
"message": "<string>",
"request_id": "<string>"
}
}status is ready before using its ID in a Render.
type selects what gets produced from the source image: render (default) creates only the render-ready 2D Character, vsplat creates only the 3D Gaussian splat, and all produces both and is billed for both. Once the vsplat extraction is ready, fetch its download URL from Export 3D Character (for 3D/game engines).
type=render costs 1 credit flat. type=vsplat costs 30 credits flat by default, or 25 credits flat with enhance=false — enhance only affects the vsplat extraction and replaces the 25-credit price rather than adding to it. type=all is billed for both: 31 credits, or 26 credits with enhance=false. See Pricing and retention.Request parameters
Sendmultipart/form-data.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
image | file | One of | — | Character source image uploaded directly. PNG, JPEG, and WebP are accepted; supply exactly one source field. |
image_url | string | One of | — | Publicly reachable HTTP(S) URL of the character source image. Supply this instead of image and keep it accessible while ingestion starts. |
ref_url | string | One of | — | Backward-compatible alias for image_url. Do not send both URL fields. |
name | string | No | "" | Optional display label returned by detail and list operations. It helps identify the Character but does not affect generation. |
model | string | No | Service default | 2D preprocessing model used by type=render or all: V3, v3, V3_Preview, V4, v4, V4_Preview, or V4_BaseSG. It does not select the 3D extraction model. |
type | string | No | render | Outputs to create: render produces the reusable 2D Character (1 credit), vsplat produces only the 3D Gaussian-splat asset (30 credits, or 25 with enhance=false), and all produces both and is billed for both (31 or 26 credits). |
enhance | boolean | No | true | Whether to run the higher-fidelity vsplat extraction pass. Only takes effect when type is vsplat or all — it has no effect and isn’t billed when type=render. Enabled by default at 30 credits flat; set to false for the cheaper standard extraction at 25 credits. |
image, image_url, or ref_url. Prefer image_url in new integrations.
The following fields apply only when type is vsplat or all.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
variant | string | No | optimized | VSPLAT encoding variant: optimized or original. quality applies only to optimized. |
model_precision | number | No | — | Optional model-level extraction precision in (0, 1]. Applies upstream, at the pkl extraction stage, before encoding. |
quality | number | No | 0.70 | Target fraction of Gaussian splats retained after pruning, in (0, 1]. |
filter_low_quality | boolean | No | true | Master switch for importance-ranked Gaussian pruning. prune_preset and prune_budget are used only when enabled. |
prune_preset | string | No | balanced | Gaussian-splat pruning strategy: geometric, draft, balanced, quality, compact, or compact_hq. |
prune_budget | number | No | — | Optional maximum Gaussian count used as an extract-time pruning budget; must be greater than 0. |
joint_set | string | No | body | Rig the vsplat is skinned to: full, expression, or body. Doesn’t affect price. |
use_sparse_W | boolean | No | false | Store skinning weights as a sparse matrix in the extracted asset. |
scale_parts | JSON string | No | — | JSON object of body-part or bone scale factors, for example {"legs":1.1}. Requires joint_set=full. |
render_thumbnail | boolean | No | false | Whether to generate the standard Character preview thumbnail with the vsplat extraction. The service selects the render source and pose internally. |
task_id | string | No | — | Caller-generated idempotency ID for type=vsplat. Use a unique, stable value when retrying the same work; for type=all, the service keys the companion extraction with the created Character ID. |
joint_set rigs. full keeps all 441 joints, including the complete facial rig, so the Character can play back facial-expression animation. expression keeps a 119-joint body-plus-facial-expression rig. body keeps the 86-joint body-only rig, dropping every facial joint — the Character can’t animate its face at all. Reducing the joint set only changes the joint list and the columns of the skinning matrix W — the splat count itself is untouched, so a body character still has a full-detail face, it just can’t animate it. If you omit joint_set, the V1 API resolves it to body (the extraction service’s own internal default is full, but V1 always fills in body first). This parameter belongs only to Character extraction; Motion creation has no joint_set field.Motion export is a separate choice: metahuman_url carries the 441-joint rig and metahuman_body_url the 86-joint body rig. The API does not currently return a dedicated 119-joint Motion export for expression. mixamo_url is a generic 50-joint rig intended for retargeting onto another character mesh. See Export 3D Motion.Response parameters
Returns200 OK with a Character object.
| Field | Type | Always present | Description |
|---|---|---|---|
id | string | Yes | Public Character ID, for example char_550e8400-e29b-41d4-a716-446655440000. Store it exactly as returned. |
status | string | Yes | Initial status is normally queued. Terminal values are ready and failed. On an all Character, status only reaches ready once both the 2D render and the vsplat extraction have; if either fails, status is failed while vsplat.status shows which one it was. |
name | string | Yes | The supplied label, or an empty string. |
progress | integer or null | Yes | Progress from 0 to 100 when available. |
capabilities | string[] | Yes | Empty until ready; ready Characters include video_render. |
created_at | string or null | Yes | ISO 8601 timestamp with a UTC offset, for example 2026-07-31T09:15:22+00:00. |
completed_at | string or null | Yes | ISO 8601 completion timestamp; null before completion. |
error | object or null | Yes | Structured error when status is failed; otherwise null. |
type | string | Yes | Echoes the requested type: render, vsplat, or all. |
vsplat | object or null | Yes | null for a render-only Character. Otherwise {status, error} — the vsplat extraction’s own status. Never carries a download URL; use Export 3D Character (for 3D/game engines) for that. |
glb | null | Yes | Always null for a Character. |
{
"id": "char_550e8400-e29b-41d4-a716-446655440000",
"status": "queued",
"name": "Presenter",
"progress": 0,
"capabilities": [],
"created_at": "2026-07-31T09:15:22+00:00",
"completed_at": null,
"error": null,
"type": "render",
"vsplat": null,
"glb": null
}
Examples
body := &bytes.Buffer{}
writer := multipart.NewWriter(body)
part, _ := writer.CreateFormFile("image", "character.png")
file, _ := os.Open("character.png")
defer file.Close()
io.Copy(part, file)
writer.WriteField("name", "Presenter")
writer.Close()
req, _ := http.NewRequest("POST", "https://apis.viggle.ai/v1/characters", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("VIGGLE_API_KEY"))
req.Header.Set("Content-Type", writer.FormDataContentType())
resp, err := http.DefaultClient.Do(req)
if err != nil { panic(err) }
defer resp.Body.Close()
const form = new FormData();
form.append("image", imageFile);
form.append("name", "Presenter");
const response = await fetch("https://apis.viggle.ai/v1/characters", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.VIGGLE_API_KEY}` },
body: form,
});
const character = await response.json();
import os
import requests
with open("character.png", "rb") as image:
response = requests.post(
"https://apis.viggle.ai/v1/characters",
headers={"Authorization": f"Bearer {os.environ['VIGGLE_API_KEY']}"},
files={"image": image},
data={"name": "Presenter"},
)
response.raise_for_status()
character = response.json()
curl -X POST "https://apis.viggle.ai/v1/characters" \
-H "Authorization: Bearer $VIGGLE_API_KEY" \
-F "[email protected]" \
-F "name=Presenter"
-F "type=vsplat" (or all to keep the render too):
curl -X POST "https://apis.viggle.ai/v1/characters" \
-H "Authorization: Bearer $VIGGLE_API_KEY" \
-F "[email protected]" \
-F "type=all" \
-F "model_precision=0.8" \
-F "prune_preset=quality" \
-F "render_thumbnail=true"
enhance pass by default (30 credits flat). To use the cheaper standard extraction instead, add -F "enhance=false" alongside type=vsplat or type=all (25 credits flat):
curl -X POST "https://apis.viggle.ai/v1/characters" \
-H "Authorization: Bearer $VIGGLE_API_KEY" \
-F "[email protected]" \
-F "type=vsplat" \
-F "enhance=false"
joint_set is body. To keep facial-expression joints (or the full 441-joint rig), add -F "joint_set=expression" (or full):
curl -X POST "https://apis.viggle.ai/v1/characters" \
-H "Authorization: Bearer $VIGGLE_API_KEY" \
-F "[email protected]" \
-F "type=vsplat" \
-F "joint_set=expression"
Next step
Use Get Character to poll the returned ID until it is ready, then Export 3D Character (for 3D/game engines) to download the vsplat if requested.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
Supply the source image as exactly one of image, image_url, or
the backward-compatible ref_url alias.
type selects what gets produced from it — see createCharacter.
The fields below type apply only when it is vsplat or all.
This is the complete public contract; workflow paths, output URIs,
multiview details, thumbnail cameras and pose, render source, and
rest mode are service-managed.
Character source image uploaded directly. Supply exactly one of image or image_url; supported formats are validated by the service.
Publicly reachable URL of the character source image. Supply this instead of image, and keep it accessible while the request is processed.
Backward-compatible alias for image_url. Do not send both fields.
Optional display name for the Character. An omitted value defaults to an empty string.
Optional 2D preprocessing model used by type=render or all. It does not select the 3D extraction model. Omit to use the service default.
V3, v3, V3_Preview, V4, v4, V4_Preview, V4_BaseSG Outputs to produce: render for the reusable 2D Character (1 credit), vsplat for only the 3D extraction (30 credits by default, 25 with enhance=false), or all for both (billed for both — 31 or 26 credits).
render, vsplat, all VSPLAT encoding variant. quality applies only to optimized.
optimized, original Whether to run the higher-fidelity vsplat extraction pass.
Enabled by default, at a flat 30 credits; set to false for the
cheaper standard extraction at 25 credits. Only takes effect when
type is vsplat or all — it has no effect and is not billed
when type=render.
Rig the vsplat is skinned to. full keeps all 441 joints;
expression keeps the 119-joint body-plus-facial-expression rig;
body keeps the 86-joint body-only rig, dropping every facial
joint. Reducing the joint set changes only joints and the
columns of the skinning matrix W — the splat count itself is
untouched, so a body character still has a full-detail face,
it just can't animate it. Applies only when type is vsplat
or all, and does not affect price. Omit to get body, the
V1 default (the extraction service's own internal default is
full, but the V1 facade always resolves an omitted value to
body before the request reaches it). This field configures
Character extraction only; Motion extraction does not accept
joint_set.
expression, body, full Optional model-level precision parameter for vsplat extraction, greater than 0 and at most 1. Applies only to type=vsplat or all.
0 < x <= 1Target fraction of Gaussian splats retained after pruning. Applies only to type=vsplat or all.
0 < x <= 1Master switch for importance-ranked Gaussian pruning. prune_preset and prune_budget are used only when this is true.
Gaussian-splat pruning strategy; used only when filter_low_quality=true.
geometric, draft, balanced, quality, compact, compact_hq Optional maximum Gaussian count budget for extract-time pruning. Applies only to type=vsplat or all.
x > 0Store skinning weights as a sparse matrix in the extracted asset.
JSON object of body-part or bone scale factors, for example {"legs":1.1}. Requires joint_set=full.
Whether to generate the standard Character thumbnail. The service chooses the render source and pose internally.
Client-supplied idempotency key for type=vsplat. For type=all,
the service keys the companion extraction with the Character ID.
Use a unique, stable non-empty value when retrying the same
creation request; reusing it for separate work causes a conflict.
1Response
Character queued.
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

