Async & polling
Create calls return immediately with an asset and its task state. Poll until it is done, or register a webhook.
1 · POST
Create
→ id · taskStatus 0
→
2 · poll / webhook
Wait
0 → 1 → 2 / 3
→
3 · files
Result
signed URLs
↺
chain by id
Refine
remesh · texture · rig
0 Queued1 Processing2 Succeeded3 Failed
Task lifecycle
| taskStatus | State | Terminal? |
|---|---|---|
| 0 | Queued — accepted, waiting for an engine. | no |
| 1 | Processing — generation is running; progress climbs 0 → 100. | no |
| 2 | Succeeded — files hold the results. | yes |
| 3 | Failed — credits are refunded; read errorCategory / errorDetail. | yes |
Future-proof your loop Treat any value other than
0 or 1 as terminal (taskStatus >= 2). A status added later can then never make your loop wait forever.On success, files holds short-lived signed URLs for the outputs — model (GLB), plus image, thumbnail, and textures where applicable. Fetch them promptly; the signatures expire.
GET /v1/assets/{id} · succeeded
{ "success": true, "data": {
"id": "019f3a39-…",
"type": "model_3d",
"taskStatus": 2,
"progress": 100,
"files": {
"model": "https://…/model.glb?signed",
"thumbnail": "https://…/thumb.webp?signed"
}
} }Poll until done
poll
curl https://api.picoberry.ai/v1/assets/019f3a39-… \
-H "Authorization: Bearer pb_live_xxx"import time, requests
while True:
a = requests.get(f"https://api.picoberry.ai/v1/assets/{id}", headers=headers).json()["data"]
if a["taskStatus"] in (2, 3): break
time.sleep(4)
model_url = a["files"]["model"]let a;
do {
a = (await (await fetch(`${BASE}/v1/assets/${id}`, { headers })).json()).data;
if (a.taskStatus < 2) await new Promise(r => setTimeout(r, 4000));
} while (a.taskStatus < 2);
const modelUrl = a.files.model;Set a generous timeout A 3D job typically takes ~60–120s. Poll every few seconds and keep polling well past a minute before treating a job as stuck.
Chain the next step
A finished asset's id is the input to every refinement — no re-upload, no format juggling. Post-process jobs are async too: each returns a new asset id you poll exactly the same way, and never mutates the original.