Base path for all endpoints: /v1/3d. Auth: Authorization: Bearer <key> (or X-API-Key: <key>); /v1/3d/health and /metrics are public. All responses use the envelope {"code","message","data"}. Generation is asynchronous: submit → task_id → poll GET /task/query until a terminal state (running / success / failed / canceled).
| Method | Endpoint | Request Body | Description |
|---|---|---|---|
| POST | /v1/3d/task/generate |
{"prompt":string, "negative_prompt?":string, "reference_image_url?":string, "provider?":string, "model?":string, "options?":object, "webhook_url?":string, "extra?":object} |
Submit generation task; image-to-3D when reference_image_url present |
| POST | /v1/3d/task/batch-generate |
{"requests":[...]} |
Batch ≤100, each item same as /task/generate |
| GET | /v1/3d/task/query?task_id= |
— | Query status, progress, model & preview URLs |
| POST | /v1/3d/task/cancel |
{"task_id":string} |
Cancel a running task |
| GET | /v1/3d/health |
— | Liveness probe |
| GET | /v1/3d/provider/list |
— | List providers + supported models |
| GET | /v1/3d/model/download/{task_id}?type=model|preview |
— | Download local file (stream) |
| GET | /v1/3d/stats/summary · /v1/3d/stats/providers · /v1/3d/stats/provider-scores |
— | Stats & circuit-breaker state |
| GET | /metrics |
— | Prometheus metrics |
Submit a generation task. Passing model routes only to providers that declare it (see /provider/list); empty model = scheduler auto-pick.
| Field | Type | Required | Description |
|---|---|---|---|
prompt |
string | Yes* | Generation prompt; *required when reference_image_url is absent |
negative_prompt |
string | No | Negative prompt |
reference_image_url |
string | No | Image URL for image-to-3D; when present, prompt is optional |
provider |
string | No | Force a specific provider; empty = scheduler auto-pick |
model |
string | No | Target model/version; only routed to providers that declare it |
options |
object | No | Upstream generation knobs (see options table below) |
webhook_url |
string | No | Terminal-state webhook URL |
extra |
object | No | Generic passthrough map (forwarded verbatim) |
Example:
curl -X POST http://localhost:8080/v1/3d/task/generate \
-H "Authorization: Bearer sk-xxx" -H "Content-Type: application/json" \
-d '{
"prompt": "an ancient temple, low-poly",
"model": "v3.1-20260211",
"options": {
"texture": true,
"pbr": true,
"quad": false,
"texture_quality": "extreme",
"geometry_quality": "detailed"
}
}'Image-to-3D: add "reference_image_url": "https://..." (or WorldLabs-style "mode": "image" + "image").
| Field | Type | Required | Description |
|---|---|---|---|
requests |
array | Yes | Array of generate objects, each same as /task/generate (batch ≤100) |
Example:
curl -X POST http://localhost:8080/v1/3d/task/batch-generate \
-H "Authorization: Bearer sk-xxx" -H "Content-Type: application/json" \
-d '{"requests": [
{"prompt": "a cat", "options": {"texture": true}},
{"prompt": "a dog", "model": "mock-v1"}
]}'GET /v1/3d/task/query?task_id=<id> — response fields (data):
| Field | Type | Description |
|---|---|---|
task_id |
string | Task ID |
status |
string | running / success / failed / canceled |
progress |
int | 0–100 |
model_url |
string | Final model download URL (if success) |
preview_url |
string | Preview image URL (if success) |
provider |
string | Provider that processed the task |
model |
string | Model version used |
error |
string | Error message (if failed) |
created_at |
string | ISO-8601 creation time |
updated_at |
string | ISO-8601 last update time |
POST /v1/3d/task/cancel — body: {"task_id": string}. Returns data.status = "canceled".
On terminal state, the bridge POSTs asynchronously to webhook_url (or the global webhook.default_url) with header X-Webhook-Source: ModelSyncBridge. Exponential-backoff retry, default 3. Payload:
{
"event": "task.finished",
"task_id": "t_...",
"status": "success",
"provider": "tripo3d",
"model": "v3.1-20260211",
"model_url": "https://...",
"preview_url": "https://..."
}AUTH_FAILED 401 · RATE_LIMITED 429 · INVALID_PARAM 400 · TASK_NOT_FOUND 404 · PROVIDER_NOT_FOUND / PROVIDER_DISABLED 404 · NO_AVAILABLE_PROVIDER 503 · PROVIDER_ERROR 503 · TASK_TIMEOUT 400 · TASK_ALREADY_CANCELED / TASK_ALREADY_FINISHED 409 · INTERNAL_ERROR 500
Each provider exposes upstream-specific generation knobs. Put them in the top-level options object; the bridge forwards them to the upstream in the format that provider's API expects (nested options object for Tripo3D, form fields for Hyper3D, flattened JSON for Meshy / Neural4D / WorldLabs). options also participates in request dedup, so different options never hit a stale cache.
extra remains available as a generic passthrough map (forwarded verbatim); prefer options for structured upstream knobs.
| Parameter | Type | Tripo3D | Hyper3D | Meshy | Neural4D | WorldLabs | Default | Description |
|---|---|---|---|---|---|---|---|---|
texture |
bool | ✅ | ✅ | should_texture |
passthrough | passthrough | — | Enable texture generation |
pbr |
bool | ✅ | ✅ | enable_pbr |
passthrough | passthrough | — | Enable PBR material |
quad |
bool | ✅ | ✅ | enable_quad |
passthrough | passthrough | — | Use quad topology |
texture_quality |
string | ✅ (extreme/high/medium/low) |
✅ (extreme/high/medium/low) |
✅ (high/medium/low) |
passthrough | passthrough | — | Texture resolution / quality |
geometry_quality |
string | ✅ (detailed/standard/rough) |
✅ (detailed/standard/rough) |
— | passthrough | passthrough | — | Geometry detail level |
foveated |
bool | ✅ | — | — | — | — | — | Foveated rendering |
relight |
bool | ✅ | — | — | — | — | — | Relighting support |
art_style |
string | — | — | ✅ (realistic/sculpture/low-poly/...) |
— | — | — | Artistic style preset |
seed |
int | ✅ | — | — | passthrough | passthrough | — | Random seed for reproducibility |
Notes:
passthrough= the bridge forwards the key/value verbatim to the upstream (provider-specific names). Neural4D and WorldLabs accept arbitrary generation parameters in their native API format.- Meshy maps
texture→should_texture,pbr→enable_pbr,quad→enable_quadwhen flattening into the JSON body.- Tripo3D wraps the whole
optionsobject into a nestedoptionsfield; Hyper3D writes each option as a multipart form field.- Refer to each provider's official API docs for the full authoritative list.
Models come from config.yaml → providers.<name>.models (declare your own). Query the live list via GET /v1/3d/provider/list. Providers without declared models accept any model value.
| Provider | Declared models (default config) | Options format | Key options |
|---|---|---|---|
| Tripo3D | (none declared — accepts any) | nested options object |
texture, pbr, quad, texture_quality, geometry_quality, foveated, relight, seed |
| Hyper3D | hyper3d-rodin-1.5 (text), hyper3d-rodin-1.5-image (image) |
multipart form fields | texture, pbr, quad, texture_quality, geometry_quality |
| Meshy | (none declared) | flattened JSON body | art_style, should_texture, enable_pbr, enable_quad, texture_quality |
| Neural4D | (none declared) | flattened JSON body | passthrough — see Neural4D docs |
| WorldLabs | (none declared) | flattened JSON body | passthrough — see WorldLabs docs |
| Mock | mock-v1, mock-v2 |
ignored | — (no upstream) |
MCP (generate_3d_model):
{"prompt": "an ancient temple", "model": "v3.1-20260211", "options": {"texture": true, "pbr": true, "quad": false}}Go SDK:
req := &sdk.GenerateRequest{
Prompt: "an ancient temple",
Model: "v3.1-20260211",
Options: map[string]interface{}{
"texture": true,
"pbr": true,
"quad": false,
"texture_quality": "extreme",
"geometry_quality": "detailed",
},
}Dedup: enabled by default (task.enable_dedup, TTL 1h) — identical requests hit the cache, saving provider quota.