Idol 1 API: Pricing, Documentation

by Sperid Labs

Idol by Sperid Labs — turn one image of an object into a 3D Gaussian splat (.ply), including the sides the image never showed.

Get API Key
Idol API

Models Version

WELCOME BONUS

Get 10% Cashback on Your First Payment (up to $500)

Add funds and get 10% cashback on your first payment (up to $500).

Claim Your Cashback →

Idol API Documentation

Turn one image of a single object into a 3D Gaussian splat: up to about a million small colored 3D Gaussians, including the sides the image never showed, delivered as a standard 3DGS .ply file. The background is removed and the object is framed for you, so a render, a generated image or a photo all work. Asynchronous: submit returns a request_id; poll the status endpoint until the request is COMPLETED.

POST https://gateway.pixazo.ai/idol/v1/image-to-3d

Authentication

All requests require an API key passed via header.

HeaderTypeRequiredDescription
Ocp-Apim-Subscription-KeystringYesYour API subscription key

Image to 3D - Idol

Request Code

POST https://gateway.pixazo.ai/idol/v1/image-to-3d
Content-Type: application/json
Ocp-Apim-Subscription-Key: YOUR_SUBSCRIPTION_KEY

{
  "image_url": "https://pub-582b7213209642b9b995c96c95a30381.r2.dev/minimax_images/h3-image/2026/11/11/a5a743ec-24cc-424d-98df-ecd6ef235998.jpg"
}
import requests

url = "https://gateway.pixazo.ai/idol/v1/image-to-3d"
headers = {
    "Content-Type": "application/json",
    "Ocp-Apim-Subscription-Key": "YOUR_SUBSCRIPTION_KEY"
}
data = {
  "image_url": "https://pub-582b7213209642b9b995c96c95a30381.r2.dev/minimax_images/h3-image/2026/11/11/a5a743ec-24cc-424d-98df-ecd6ef235998.jpg"
}

resp = requests.post(url, json=data, headers=headers)
print(resp.json())
const res = await fetch("https://gateway.pixazo.ai/idol/v1/image-to-3d", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Ocp-Apim-Subscription-Key": "YOUR_SUBSCRIPTION_KEY"
  },
  body: JSON.stringify({
  "image_url": "https://pub-582b7213209642b9b995c96c95a30381.r2.dev/minimax_images/h3-image/2026/11/11/a5a743ec-24cc-424d-98df-ecd6ef235998.jpg"
})
});
console.log(await res.json());
curl -X POST 'https://gateway.pixazo.ai/idol/v1/image-to-3d' \
  -H 'Content-Type: application/json' \
  -H 'Ocp-Apim-Subscription-Key: YOUR_SUBSCRIPTION_KEY' \
  --data-raw '{"image_url": "https://pub-582b7213209642b9b995c96c95a30381.r2.dev/minimax_images/h3-image/2026/11/11/a5a743ec-24cc-424d-98df-ecd6ef235998.jpg"}'

Output

{
  "request_id": "idol_019dxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "status": "QUEUED",
  "polling_url": "https://gateway.pixazo.ai/v2/requests/status/idol_019dxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}

Webhook (Optional)

Instead of polling, you can receive a Webhook callback when the request reaches a terminal state. Provide a Webhook URL via header on the submit request.

HeaderRequiredDescription
X-Webhook-URLTo enableHTTPS URL to receive the Webhook callback.
X-Webhook-ModeNoterminal (default, one callback on COMPLETED/ERROR) or sync (per-poll callbacks).

Callback Payload (success)

{
  "request_id": "idol_019dxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "status": "COMPLETED",
  "model_id": "idol",
  "error": null,
  "output": {
    "media_url": [
      "https://pub-582b7213209642b9b995c96c95a30381.r2.dev/v1/idol_019dxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/output.ply"
    ],
    "media_type": "model/ply"
  },
  "created_at": "2026-11-11T12:56:10.571Z",
  "updated_at": "2026-11-11 12:56:38",
  "completed_at": "2026-11-11 12:56:37"
}

Failure callback shape

{
  "request_id": "idol_019dxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "status": "ERROR",
  "model_id": "idol",
  "error": "Generation failed: the request was rejected (image_url: Failed to load the image. Please ensure the image file is not corrupted and is in a supported format).",
  "output": null,
  "created_at": "2026-11-11T12:58:51.848Z",
  "updated_at": "2026-11-11 12:59:00",
  "completed_at": "2026-11-11 12:59:00"
}

Callbacks are idempotent on request_id — de-duplicate on it. Respond 200 within a few seconds; the Webhook endpoint must be HTTPS.

Request Parameters

ParameterRequiredTypeDefaultAllowed values / rangeDescription
image_urlYesstring—A public http(s) URL of the imageThe image of ONE object. Renders, generated images and photos all work; the background is removed and the object is framed for you.
image_typeNostringsyntheticsynthetic, realsynthetic for renders and generated images (the object is framed tightly); real for photographs (looser framing).
num_inference_stepsNointeger501 to 50Sampling steps. Fewer are faster but lose some detail.
guidance_scaleNonumber30 to 10How strictly the object follows the image.
num_gaussiansNointeger26214432,768 to 1,048,576How many Gaussians the splat has, rounded down to a multiple of 32. More gives finer detail and a bigger file (see The output file).
seedNointegerrandom0 to 2,147,483,647Fix it to get the same object again.
enable_safety_checkerNobooleantruetrueThe input image is checked for unsafe content. It cannot be turned off.

How usage is measured

Billed per 3D object: one per request, at the same rate whatever num_inference_steps or num_gaussians. The rate is in the pricing panel on this page. Nothing is charged for a request that fails.

Parameters not supported

Rejected with 400

Checked when you submit: the request is rejected before it is queued.

ParameterWhyUse instead
stepsThat is the Idol SDK's name for it.num_inference_steps
cfg_strengthThat is the Idol SDK's name for it.guidance_scale
modeThat is the Idol SDK's name for it.image_type
image_urls, images, imageIdol builds one object from one image.image_url
prompt, negative_promptIdol works from the image alone; there is no text prompt.—
num_images, number_of_images, batch_size, n, countOne 3D object per request.One request per image
output_formatThe splat is always a .ply file.—
modelThis endpoint always runs Idol.—
input, parametersNot accepted by this endpoint.Send the parameters at the top level of the JSON body
webhook_url, callback_urlWebhooks are set by header.X-Webhook-URL header
sync_mode set to trueResults are delivered through the status endpoint or a Webhook.—
enable_safety_checker set to falseThe safety check cannot be turned off.—
image_url that cannot be downloadedThe image is fetched when you submit; if the URL answers an error (for example 404), the 400 says so under failures.A public URL that serves the image

Accepted, then the request fails

These pass the submit check, so the submit returns 202, but the request then fails with status: "ERROR". Nothing is charged.

ParameterWhen the request fails
image_urlThe file downloads but is not a readable image, for example a web page or a text file.
image_urlThe image is blocked by the content safety check.

Accepted but ignored

Any other parameter is dropped and has no effect.

The output file

output.media_url is one .ply file (model/ply): a standard 3D Gaussian splatting (3DGS) PLY, binary_little_endian 1.0, with one vertex per Gaussian and 17 properties each: x, y, z, nx, ny, nz, f_dc_0, f_dc_1, f_dc_2, opacity, scale_0, scale_1, scale_2, rot_0, rot_1, rot_2, rot_3.

num_gaussiansFile size (measured at launch)
262,144 (default)17.8 MB
1,048,576 (maximum)71.3 MB

Open it in any Gaussian splat viewer or editor, for example SuperSplat, or load it with the splat loaders for three.js and Babylon.js. A splat is not a mesh: it renders photoreal in splat viewers, but it has no polygons, so tools that need a mesh (3D printing, CAD, most game-engine imports) need a conversion step first. The object is centered, and the side the image did not show is generated.

Input tips

ItemGuidance
SubjectOne object, whole in frame. Several objects or a full scene give a poor result.
BackgroundAny; it is removed for you. A plain background gives the cleanest cut-out.
Kind of imagesynthetic (default) for renders and generated images, real for photographs.
DetailRaise num_gaussians for finer detail; lower it for a smaller file.

Timing

A splat at the defaults took about 30 seconds from submit to result at launch, and one at the maximum num_gaussians about 45 seconds. Polling the status endpoint every 3 to 5 seconds is enough, or use a Webhook.

Example Request

{
  "image_url": "https://pub-582b7213209642b9b995c96c95a30381.r2.dev/minimax_images/h3-image/2026/11/11/a5a743ec-24cc-424d-98df-ecd6ef235998.jpg"
}

Example Response

{
  "request_id": "idol_019dxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "status": "QUEUED",
  "polling_url": "https://gateway.pixazo.ai/v2/requests/status/idol_019dxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}

Example: a photo at the maximum detail

Request

{
  "image_url": "https://pub-582b7213209642b9b995c96c95a30381.r2.dev/minimax_images/h3-image/2026/11/11/30eaadbd-7b48-4252-92d0-9b3513520e1f.jpg",
  "image_type": "real",
  "num_gaussians": 1048576,
  "seed": 42
}

Completed response

{
  "request_id": "idol_019dxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "status": "COMPLETED",
  "model_id": "idol",
  "error": null,
  "output": {
    "media_url": [
      "https://pub-582b7213209642b9b995c96c95a30381.r2.dev/v1/idol_019dxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/output.ply"
    ],
    "media_type": "model/ply"
  },
  "created_at": "2026-11-11T12:56:11.162Z",
  "updated_at": "2026-11-11 12:56:59",
  "completed_at": "2026-11-11 12:56:58"
}

Request Headers

HeaderRequiredDescription
Content-TypeYesapplication/json
Ocp-Apim-Subscription-KeyYesYour API subscription key.
X-Webhook-URLNoEnable Webhook callbacks (see Webhook section).

Response Handling

Status CodeMeaning
202Accepted — request queued; returns request_id and polling_url.
400Bad request — the body failed the submit check (see Request Parameters) and was not queued.
401Unauthorized — missing or invalid subscription key.
402Insufficient balance.
403Forbidden.
429Too many requests.
500Internal server error.

Error Responses

A 400 names every rejected parameter in violations. This one was sent {"image_type": "photo", "steps": 10} with an image:

{
  "error": "Invalid request parameters",
  "message": "'image_type' must be one of: \"synthetic\", \"real\" (got \"photo\"); 'steps' is not a parameter here: use 'num_inference_steps' (1 to 50).",
  "violations": [
    "'image_type' must be one of: \"synthetic\", \"real\" (got \"photo\")",
    "'steps' is not a parameter here: use 'num_inference_steps' (1 to 50)."
  ]
}

An image_url that cannot be downloaded is also a 400, with the reason under failures:

{
  "request_id": "idol_019dxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "error": "Asset proxy failed",
  "message": "Failed to proxy asset https://raw.githubusercontent.com/speridlabs/idol-sdk/main/no-such-image.png: 404 Not Found",
  "failures": [
    {
      "url": "https://raw.githubusercontent.com/speridlabs/idol-sdk/main/no-such-image.png",
      "error": "404 Not Found"
    }
  ]
}

Retrieving Results

Poll the status endpoint with the request_id until status is COMPLETED or ERROR, then download the splat from output.media_url.

curl 'https://gateway.pixazo.ai/v2/requests/status/idol_019dxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' \
  -H 'Ocp-Apim-Subscription-Key: YOUR_SUBSCRIPTION_KEY'

Completed response

Captured from a real Idol request at launch; the request id is masked.

{
  "request_id": "idol_019dxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "status": "COMPLETED",
  "model_id": "idol",
  "error": null,
  "output": {
    "media_url": [
      "https://pub-582b7213209642b9b995c96c95a30381.r2.dev/v1/idol_019dxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/output.ply"
    ],
    "media_type": "model/ply"
  },
  "created_at": "2026-11-11T12:56:10.571Z",
  "updated_at": "2026-11-11 12:56:38",
  "completed_at": "2026-11-11 12:56:37"
}

Response Fields

FieldTypeDescription
request_idstringUnique request identifier.
statusstringQUEUED, PROCESSING, COMPLETED or ERROR.
model_idstringThe model that handled the request.
errorstring or nullError message when status is ERROR; otherwise null.
output.media_urlarray of stringsURL of the .ply splat (one per request). Download it and keep your own copy.
output.media_typestringmodel/ply.
created_atstringRequest creation timestamp.
updated_atstringLast status change timestamp.
completed_atstringCompletion timestamp.
polling_urlstringStatus URL for this request (in the submit response).

Status Values & Flow

QUEUED → PROCESSING → COMPLETED (success) or ERROR (failure). Treat any status other than QUEUED, PROCESSING or COMPLETED as a failure.

Idol API Pricing

ResolutionPrice (USD)
Per 3D object (any settings)$0.105 per generation

⚡ Performance

Live usage measured on Pixazo's gateway, split by model version. Generation time is how long a generation takes end-to-end (lower is better). Success rate is the percent of generations that complete (higher is better).

Show data for the last
Generations
600last 30d
~20 per day
Success rate
66.7%
of completed generations
Generation time
36.6savg
p95 26.4s
Requests
Oct 14max 600Nov 12
IdolAvg 20/day
Generation Time
Oct 14max 36.6sNov 12
IdolAvg 36.6s
Error Rate
Oct 14max 33.3%Nov 12
IdolAvg 33.3%

〰 Uptime

Percent of generations that succeeded over the selected period, per model version.

Avg. Success Rate (30d)
66.67%
across all generations of this model family
Uptime
Oct 14max 100%Nov 12
SuccessfulAvg 66.67%