Developer API
Generate 3D models programmatically via the REST API. Authenticate with API keys, run async jobs, and receive webhooks on completion.
https://open3dai.com/api/v1
Bearer trf_live_…
JSON
600 / hour / key
Quickstart
Create an API key
Sign in, open Account → API Keys → Create. Copy the plaintext value immediately; it is shown only once.
Make your first request
Generate a 3D model from text:
curl -X POST https://open3dai.com/api/v1/generations/text-to-3d \
-H "Authorization: Bearer trf_live_xxx" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"type": "text_to_3d",
"prompt": "A medieval sword with a golden hilt",
"style": "realistic",
"mode": "quality",
"webhookUrl": "https://yourapp.com/hooks/open3dai"
}'
# 201 Created
{
"ok": true,
"data": {
"taskId": "gen_abc123",
"provider": "procedural",
"status": "processing",
"creditsUsed": 20,
"creditsRemaining": 980
},
"requestId": "req_1a2b3c4d"
}
Poll or wait for the webhook
Poll GET /generations/{taskId}. When status is completed, data.outputModelUrl points at the generated .glb.
curl https://open3dai.com/api/v1/generations/gen_abc123 \
-H "Authorization: Bearer trf_live_xxx"
Response envelope
All responses follow one envelope, and every response carries an X-Request-ID header — include it when reporting an issue.
// 成功 (2xx)
{ "ok": true, "data": { … }, "requestId": "req_abc123" }
// 失败 (4xx / 5xx)
{
"ok": false,
"error": {
"code": "snake_case_code",
"message": "Human-readable message.",
"requestId": "req_abc123",
"details": { }
}
}
Endpoints
| Method | Path | Scopes | Description |
|---|---|---|---|
POST | /generations/text-to-3d | write |
Generate a 3D model from a natural-language prompt. |
POST | /generations/image-to-3d | write |
Turn one reference image (JPG/PNG/WEBP as a base64 data URL) into a textured 3D model. |
POST | /generations/multiview-to-3d | write |
Reconstruct a 3D model from at least 2 photos taken from different angles. |
GET | /generations/{taskId} | read |
Poll task status, output URL and credit usage. |
GET | /generations/{taskId}/model | read |
Download the generated model file directly. |
GET | /usage | read |
Check credit balance and rate-limit quota without spending credits. |
GET | /api/docs | — | Interactive OpenAPI documentation. |
Idempotency
Network retries are common. Without idempotency, a retried request could create a duplicate task and charge credits twice.
-H "Idempotency-Key: 8f14e45f-ceea-467a-9a1e-3b1c2d4e5f60"
- Format: 1–255 characters from
A–Z a–z 0–9 _ -. A random UUID v4 per client action is recommended. - The same key with an identical body replays the first response and does not charge again.
- The same key with a different body returns
400 validation_failed. - A malformed key returns
400 invalid_idempotency_key.
Webhooks
Pass webhookUrl at creation and we POST the result when the job finishes, success or failure.
POST {your webhookUrl}
X-open3dai-Event: generation.completed # or generation.failed
X-open3dai-Delivery: gen_abc123
{
"taskId": "gen_abc123",
"status": "completed",
"outputModelUrl": "https://open3dai.com/api/v1/generations/gen_abc123/model",
"thumbnailUrl": "https://open3dai.com/api/v1/generations/gen_abc123/thumbnail",
"creditsUsed": 20,
"errorCode": null,
"timestamp": "2026-08-14T14:00:00Z"
}
Rate limiting
Each API key gets 600 requests per hour in a rolling window.
| Header | Meaning |
|---|---|
X-RateLimit-Limit | Maximum requests in the window (600). |
X-RateLimit-Remaining | Requests remaining in the current window. |
Retry-After | Returned on 429 only: seconds until the window resets. |
X-Request-ID | Unique per-request identifier for debugging. |
Errors
| Code | HTTP | Trigger |
|---|---|---|
missing_bearer_token | 401 | No Authorization: Bearer … header was supplied. |
invalid_api_key | 401 | The key is malformed, revoked or unknown. |
insufficient_scope | 403 | The key lacks the scope for this endpoint. |
insufficient_credits | 402 | Account balance is too low for this generation. |
validation_failed | 400 | The body failed validation; see details.issues. |
invalid_idempotency_key | 400 | The Idempotency-Key header is malformed. |
invalid_request_body | 400 | The request body is not valid JSON. |
rate_limit_exceeded | 429 | Hourly quota exhausted; see Retry-After. |
task_not_found | 404 | No such task for this account. |
internal_error | 500 | Unexpected server error; report the requestId. |
Validation issue codes
prompt_required— empty prompt for text-to-3D.prompt_too_long— prompt exceeds 2000 characters.image_required— imageDataUrl is missing.invalid_image_format— not a supported base64 data URL.image_too_large— decoded image exceeds 20MB.multiview_requires_two_images— fewer than 2 images for multiview.invalid_mode— mode must be speed or quality.invalid_style— style is not recognised.idempotency_key_reused— same idempotency key with a different body.
Create an API key
Sign in, open Account → API Keys → Create. Copy the plaintext value immediately; it is shown only once.