Getting started

Quickstart

From an API key to a downloaded 3D model in four steps. Every snippet below is copy-paste-ready in curl, Python, or JavaScript — pick your language in the top bar.

Base URLhttps://api.picoberry.ai
AuthBearer / x-api-key
FormatJSON · { success, data }

1. Get your API key

The API is open to paying customers — an active subscription or at least one completed credit purchase. Open Account → API keys, create a key, and copy it — the secret is shown once. Full detail on the Authentication page.

setup
export PB_KEY="pb_live_xxxxxxxxxxxx"
export BASE="https://api.picoberry.ai"
import requests, time

BASE = "https://api.picoberry.ai"
headers = {"Authorization": "Bearer pb_live_xxxxxxxxxxxx"}
const BASE = "https://api.picoberry.ai";
const headers = { Authorization: "Bearer pb_live_xxxxxxxxxxxx" };
Keep keys server-side A pb_live_ key can spend your whole credit balance — never ship it in client code or commit it to a repo.

2. Start a generation

Kick off a text-to-3D job. The call returns immediately with an asset id and taskStatus: 0 — generation runs in the background. Images work the same way via POST /v1/images.

request
curl -X POST $BASE/v1/models/from-text \
  -H "Authorization: Bearer $PB_KEY" -H "Content-Type: application/json" \
  -d '{"prompt":"a stylized treasure chest, game ready","engine":"tripo"}'
r = requests.post(f"{BASE}/v1/models/from-text", headers=headers,
    json={"prompt": "a stylized treasure chest, game ready", "engine": "tripo"})
asset_id = r.json()["data"]["id"]
const r = await fetch(`${BASE}/v1/models/from-text`, { method: "POST",
  headers: { ...headers, "Content-Type": "application/json" },
  body: JSON.stringify({ prompt: "a stylized treasure chest, game ready", engine: "tripo" }) });
const assetId = (await r.json()).data.id;
response · 200
{ "success": true, "data": { "id": "019f3a39-…", "taskStatus": 0, "type": "model_3d" } }

3. Poll until it's done

Generation is asynchronous. Poll GET /v1/assets/{id} until taskStatus reaches 2. A 3D job typically takes ~60–120s; an image, a few seconds. On success, files.model holds a signed GLB URL.

0 Queued1 Processing2 Succeeded3 Failed
poll
# set ASSET_ID from the response above, then repeat until .data.taskStatus is 2
curl $BASE/v1/assets/$ASSET_ID -H "Authorization: Bearer $PB_KEY"
while True:
    a = requests.get(f"{BASE}/v1/assets/{asset_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/${assetId}`, { headers })).json()).data;
  if (a.taskStatus < 2) await new Promise(res => setTimeout(res, 4000));
} while (a.taskStatus < 2);
const modelUrl = a.files.model;
Skip polling with a webhook Register a callbackUrl and PicoBerry pushes the finished asset to your server. See Webhooks and Async & polling.

4. Download the model

files.model is a ready-to-use GLB. To get a specific format — FBX/OBJ, or a Unity-ready texture split — export it for a fresh signed download URL.

request
curl -X POST $BASE/v1/assets/$ASSET_ID/download \
  -H "Authorization: Bearer $PB_KEY" -H "Content-Type: application/json" \
  -d '{"format":"glb"}'
d = requests.post(f"{BASE}/v1/assets/{asset_id}/download", headers=headers,
    json={"format": "glb"}).json()["data"]
download_url = d["url"]
const d = (await (await fetch(`${BASE}/v1/assets/${assetId}/download`, { method: "POST",
  headers: { ...headers, "Content-Type": "application/json" },
  body: JSON.stringify({ format: "glb" }) })).json()).data;
const downloadUrl = d.url;
response · 200
{ "success": true, "data": { "url": "https://…signed", "format": "glb", "filename": "model.glb" } }
fbx / obj are ZIP bundles glb is a single file; fbx and obj come back as a .zip (model + textures). Full options — Unity preset, custom filename — on the Download & export page.

Next steps

That's the whole loop — key → create → poll → download. From here: