curl --request GET \
--url https://apis.viggle.ai/v1/scenes/{task_id} \
--header 'Authorization: Bearer <token>'import requests
url = "https://apis.viggle.ai/v1/scenes/{task_id}"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://apis.viggle.ai/v1/scenes/{task_id}', 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/scenes/{task_id}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://apis.viggle.ai/v1/scenes/{task_id}"
req, _ := http.NewRequest("GET", url, nil)
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.get("https://apis.viggle.ai/v1/scenes/{task_id}")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://apis.viggle.ai/v1/scenes/{task_id}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"id": "<string>",
"sessionId": "<string>",
"operation": "pano",
"status": "processing",
"createdAt": 123,
"completedAt": 123,
"result": {
"operation": "pano",
"sessionId": "<string>",
"spz": {
"url": "<string>"
},
"preview": {
"url": "<string>"
},
"panorama": {
"url": "<string>"
},
"outputBatch": {
"batchId": "<string>",
"createdAt": 123,
"manifest": {
"url": "<string>"
},
"kind": "initial",
"views": [
{
"index": 1,
"url": "<string>",
"c2w": [
[
1,
0,
0,
0
],
[
0,
1,
0,
0
],
[
0,
0,
1,
0
],
[
0,
0,
0,
1
]
],
"intrinsic": [
123
]
}
]
},
"referenceViewCount": 123,
"newViewCount": 123,
"seconds": {}
},
"error": {
"code": "UNAUTHENTICATED",
"message": "<string>",
"retryable": true,
"request_id": "<string>",
"details": {},
"remediation": {
"action": "<string>",
"retry_after_ms": 1
}
}
}{
"error": {
"code": "UNAUTHENTICATED",
"message": "<string>",
"retryable": true,
"request_id": "<string>",
"details": {},
"remediation": {
"action": "<string>",
"retry_after_ms": 1
}
}
}{
"error": {
"code": "UNAUTHENTICATED",
"message": "<string>",
"retryable": true,
"request_id": "<string>",
"details": {},
"remediation": {
"action": "<string>",
"retry_after_ms": 1
}
}
}{
"error": {
"code": "UNAUTHENTICATED",
"message": "<string>",
"retryable": true,
"request_id": "<string>",
"details": {},
"remediation": {
"action": "<string>",
"retry_after_ms": 1
}
}
}Get Scene Task
Retrieve the state of a scene task, and its scene, panorama, and image downloads once ready.
curl --request GET \
--url https://apis.viggle.ai/v1/scenes/{task_id} \
--header 'Authorization: Bearer <token>'import requests
url = "https://apis.viggle.ai/v1/scenes/{task_id}"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://apis.viggle.ai/v1/scenes/{task_id}', 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/scenes/{task_id}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://apis.viggle.ai/v1/scenes/{task_id}"
req, _ := http.NewRequest("GET", url, nil)
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.get("https://apis.viggle.ai/v1/scenes/{task_id}")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://apis.viggle.ai/v1/scenes/{task_id}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"id": "<string>",
"sessionId": "<string>",
"operation": "pano",
"status": "processing",
"createdAt": 123,
"completedAt": 123,
"result": {
"operation": "pano",
"sessionId": "<string>",
"spz": {
"url": "<string>"
},
"preview": {
"url": "<string>"
},
"panorama": {
"url": "<string>"
},
"outputBatch": {
"batchId": "<string>",
"createdAt": 123,
"manifest": {
"url": "<string>"
},
"kind": "initial",
"views": [
{
"index": 1,
"url": "<string>",
"c2w": [
[
1,
0,
0,
0
],
[
0,
1,
0,
0
],
[
0,
0,
1,
0
],
[
0,
0,
0,
1
]
],
"intrinsic": [
123
]
}
]
},
"referenceViewCount": 123,
"newViewCount": 123,
"seconds": {}
},
"error": {
"code": "UNAUTHENTICATED",
"message": "<string>",
"retryable": true,
"request_id": "<string>",
"details": {},
"remediation": {
"action": "<string>",
"retry_after_ms": 1
}
}
}{
"error": {
"code": "UNAUTHENTICATED",
"message": "<string>",
"retryable": true,
"request_id": "<string>",
"details": {},
"remediation": {
"action": "<string>",
"retry_after_ms": 1
}
}
}{
"error": {
"code": "UNAUTHENTICATED",
"message": "<string>",
"retryable": true,
"request_id": "<string>",
"details": {},
"remediation": {
"action": "<string>",
"retry_after_ms": 1
}
}
}{
"error": {
"code": "UNAUTHENTICATED",
"message": "<string>",
"retryable": true,
"request_id": "<string>",
"details": {},
"remediation": {
"action": "<string>",
"retry_after_ms": 1
}
}
}GET /v1/scenes/{task_id} returns the current state of a task started by Create Scene, Create Scene from Custom Panorama, Generate Scene Views, or Reconstruct Scene — the same Scene Task object the submission answered with. Poll every 5 seconds until status is ready, failed, or cancelled, then download the files under result.
Tasks belong to your account — your organization, or your user when the key has no organization — so any API key of the same account can read them. An unknown ID, or one from another account, answers 404 INVALID_REQUEST.
Request parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
task_id | string | Yes | Full task ID returned by a submission, scn_ prefix. It has the form scn_{runId}.{sessionId}; use it exactly as returned. |
Response parameters
Returns200 OK with a Scene Task object. Field names are camelCase.
| Field | Type | Description |
|---|---|---|
id | string | Task ID, scn_ prefix. |
sessionId | string | The sessionId you submitted the task under. |
operation | string | pano, generate, or reconstruct. A custom-pano task reports pano. |
status | string | processing, ready, failed, or cancelled — see Status and errors. |
createdAt | integer | Start time, Unix milliseconds. |
completedAt | integer or null | End time, Unix milliseconds; null while processing. |
result | object or null | Set only when status is ready — see Result. |
error | object or null | Set only when status is failed. |
Result
| Field | Type | Description |
|---|---|---|
operation | string | Same as the task’s operation. |
sessionId | string | Same as the task’s sessionId. |
spz | object or null | The 3D Gaussian-splat scene, as { "url": ... }, in SPZ format. Produced by pano and reconstruct. If you sent spzOutputUrl (or outputUris.spz), the file was uploaded only to your URL and url is that URL. |
preview | object or null | A preview image, as { "url": ... }, when the operation produced one. |
panorama | object or null | The 360° panorama the scene was built from, as { "url": ... } — generated from your prompt, or the one you supplied. Produced by pano. |
outputBatch | object or null | The image batch this task added to the session — see Output batch. Produced by pano (the initial views) and generate (the new views); null for reconstruct. |
referenceViewCount | integer | Number of reference views the task read from referenceBatchIds. 0 for pano. |
newViewCount | integer | Number of new views the task produced. 0 for reconstruct. |
seconds | object | Processing time by stage, in seconds, for example {"model": 4.2}. Keys vary by operation; treat them as informational. |
url Viggle signs is valid for 3 hours. Fetch the task again for fresh ones.
Output batch
A batch is a set of posed images in one session. ItsbatchId is what you pass in referenceBatchIds to generate more views or reconstruct the scene.
| Field | Type | Description |
|---|---|---|
batchId | string | Batch ID, a lowercase UUID. |
createdAt | number | Batch creation time, Unix milliseconds. |
manifest | object | The batch’s batch.json manifest, as { "url": ... }. |
kind | string | initial for a batch made by pano, generated for one made by generate. |
views | array | Every image in the batch, in order. |
views[].index | integer | Position in the batch, from 0. |
views[].url | string | Signed download URL of the image. |
views[].c2w | number[4][4] | Camera-to-world matrix of the view. For a custom-pano scene it’s in your own world frame — see Custom panorama. |
views[].intrinsic | number[] | Camera intrinsics of the view, as recorded in the batch manifest. |
kind and views can be missing on tasks that finished before they were introduced; manifest is always there.
Ready example
Apano task. Signature query parameters shortened:
{
"id": "scn_0199f0c2-6a1e-7c3d-9b2a-4f5e6d7c8b9a.living-room-01",
"sessionId": "living-room-01",
"operation": "pano",
"status": "ready",
"createdAt": 1791856740000,
"completedAt": 1791856800000,
"result": {
"operation": "pano",
"sessionId": "living-room-01",
"spz": { "url": "https://.../scene.spz?X-Amz-Signature=..." },
"preview": null,
"panorama": { "url": "https://.../panorama.png?X-Amz-Signature=..." },
"outputBatch": {
"batchId": "3f0a6c1e-8d2b-4b7a-9e5c-1a2b3c4d5e6f",
"createdAt": 1791856800000,
"manifest": { "url": "https://.../batch.json?X-Amz-Signature=..." },
"kind": "initial",
"views": [
{
"index": 0,
"url": "https://.../0.png?X-Amz-Signature=...",
"c2w": [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]],
"intrinsic": [0.5, 0.5, 0.5, 0.5]
}
]
},
"referenceViewCount": 0,
"newViewCount": 6,
"seconds": { "model": 4.2 }
},
"error": null
}
Failed example
{
"id": "scn_0199f0c2-6a1e-7c3d-9b2a-4f5e6d7c8b9a.living-room-01",
"sessionId": "living-room-01",
"operation": "generate",
"status": "failed",
"createdAt": 1791856740000,
"completedAt": 1791856765000,
"result": null,
"error": {
"code": "PROCESSING_FAILED",
"message": "The request could not be processed.",
"retryable": true,
"request_id": "req_7d3c...",
"details": {},
"remediation": { "action": "retry", "retry_after_ms": null }
}
}
Status and errors
status | Meaning |
|---|---|
processing | Running. The session accepts no other task until this one ends. |
ready | Done; result is filled in. |
failed | Failed; see error. |
cancelled | Stopped by Viggle before it finished. Submit the task again. |
error.code on a failed task:
code | retryable | When | What to do |
|---|---|---|---|
INVALID_REQUEST | false | The scene model rejected the input — for example, a referenceBatchIds entry that isn’t a batch of this session. message says why. | Fix the input, then submit again. |
PROCESSING_FAILED | true | Any other failure: the model, storage, or a timeout. | Submit the same request again. If it keeps happening, contact us with the task id. |
| HTTP | code | Meaning |
|---|---|---|
401 | UNAUTHENTICATED | Missing or invalid API key. |
404 | INVALID_REQUEST | No such task in your account, or it is past retention. |
503 | SERVICE_BUSY | The scene model is temporarily unavailable. Retryable. |
error, wrapped as {"error": {...}}. See Errors and recovery.
Retention
- A task can be read for about 72 hours after it finishes; after that this endpoint answers
404. Download what you need, or have Viggle upload it straight to your storage withoutputUris. - Signed URLs last 3 hours each; fetch the task again for fresh ones while it is still readable.
Examples
curl https://apis.viggle.ai/v1/scenes/scn_0199f0c2-6a1e-7c3d-9b2a-4f5e6d7c8b9a.living-room-01 \
-H "Authorization: Bearer $VIGGLE_API_KEY"
import os, requests
response = requests.get(
"https://apis.viggle.ai/v1/scenes/scn_0199f0c2-6a1e-7c3d-9b2a-4f5e6d7c8b9a.living-room-01",
headers={"Authorization": f"Bearer {os.environ['VIGGLE_API_KEY']}"},
)
response.raise_for_status()
task = response.json()
const response = await fetch("https://apis.viggle.ai/v1/scenes/scn_0199f0c2-6a1e-7c3d-9b2a-4f5e6d7c8b9a.living-room-01", {
headers: { Authorization: `Bearer ${process.env.VIGGLE_API_KEY}` },
});
const task = await response.json();
Quick Start: Scene Model
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 - 128Path Parameters
Scene task ID (scn_ prefix, scn_{runId}.{sessionId}) returned by a /v1/scenes submission. It must belong to the caller's account.
1Response
Current scene task state.
A scene task (scn_ prefix), returned by every /v1/scenes
submission and by GET /v1/scenes/{task_id}. ready, failed, and
cancelled are terminal. A task stays readable for about 72 hours
after it finishes.
Task ID, scn_{runId}.{sessionId}.
A custom-pano task reports pano.
pano, generate, reconstruct processing, ready, failed, cancelled Start time, Unix milliseconds.
End time, Unix milliseconds; null while processing.
Set only when ready.
Show child attributes
Show child attributes
Set only when failed. code is INVALID_REQUEST (not
retryable — the model rejected the input, such as a batch from
another session) or PROCESSING_FAILED (retryable).
Show child attributes
Show child attributes

