Unbound Zero

Unbound Zero API

The fastest 3D gen for agentic game development.

Clean quads. PBR textures. Your pipeline.

Best for

Speed and price

Per textured mesh from one image. Lower is better. Several views of the same object (up to 4 images): 3× the price, $0.30 per mesh.

Time per mesh
Unbound Zero 4 s
Meshy T2 60 s
Pixal3D on fal.ai 36 s
Tripo Smart Mesh 41 s
Tripo Smart Mesh 2 49 s
Price per mesh
Unbound Zero $0.10
Meshy T2 $0.30
Pixal3D on fal.ai $0.30
Tripo Smart Mesh $0.50
Tripo Smart Mesh 2 $1.10

Prices are from each provider’s published API pricing with texturing included. Timings tested with wall clock, November 2026.

60 free models when you sign up.

No credit card.

Get an API key
  • Basic 150 models/mo $9.99/mo
  • Pro 450 models/mo $29.99/mo
  • Max 1,950 models/mo $119.99/mo
  • See plans

Start in three steps

  1. Get an API key

    Sign up and create a key. It starts with ubue_.

    Get API key
  2. Give your agent the skill

    One markdown file. It teaches Claude Code, Codex or any coding agent to call the API.

    Download SKILL.md
  3. Ask for assets

    “Turn concept/chest.png into a game-ready mesh, 3,000 quads.”

API

Base URL https://unbound-3dgen-server-618775028388.us-central1.run.app/api/v2
Send your key on every request: Authorization: Bearer <key>

One file. Your agent learns the API, the parameters and the limits from it.

Download SKILL.md

Install

# Claude Code
mkdir -p ~/.claude/skills/unbound-zero
curl -sS https://loop.unbound.io/zero/SKILL.md -o ~/.claude/skills/unbound-zero/SKILL.md

# Your key, where the agent runs
export UNBOUND_API_KEY=ubue_…

Other agents: put the file where they read instructions, or give them the link.

SKILL.md

---
name: unbound-zero
description: Turn an image into a game-ready 3D asset with the Unbound Zero API - a GLB mesh with clean quad topology, UVs and PBR textures. Use when the user wants a 3D model, mesh or game asset made from a picture, photo, render or concept art.
---

# Unbound Zero: image to game-ready mesh

One image in, one GLB out: quad-remeshed geometry, UVs, PBR textures (base color, metallic, roughness) and a normal map.

No image yet, and no image generator of your own? See "Optional: make or edit the input image" below.

## Setup

- API base: `https://unbound-3dgen-server-618775028388.us-central1.run.app/api/v2`
- Read the key from the `UNBOUND_API_KEY` environment variable. If it is not set, ask the user for it; they create one at https://loop.unbound.io/account/api-keys. Keys start with `ubue_`.
- Never print or log the key, and never write it into a project file or version control.
- Send it on every request: `Authorization: Bearer $UNBOUND_API_KEY`.

## Generate one asset

1. Submit the image. Each created task is billed.

   ```bash
   BASE=https://unbound-3dgen-server-618775028388.us-central1.run.app/api/v2
   curl -sS -X POST "$BASE/tasks" \
     -H "Authorization: Bearer $UNBOUND_API_KEY" \
     -F image=@input.png -F material=pbr -F quads=5000
   # 201 {"task_id":"…","status":"queued"}
   ```

2. Download the mesh. The server holds the request open until the mesh is ready, for up to 60 s, and answers `409` if it is not ready by then. Repeat on `409`; stop if the task failed.

   ```bash
   TASK=<task_id>
   while :; do
     code=$(curl -sS -o out.glb -w '%{http_code}' \
       -H "Authorization: Bearer $UNBOUND_API_KEY" \
       "$BASE/tasks/$TASK/download?wait=60")
     [ "$code" = 200 ] && break
     rm -f out.glb
     [ "$code" = 409 ] || { echo "download failed: HTTP $code" >&2; break; }
     curl -sS -H "Authorization: Bearer $UNBOUND_API_KEY" "$BASE/tasks/$TASK" \
       | grep -q '"status": *"failed"' && { echo "generation failed" >&2; break; }
   done
   ```

3. Tell the user where the file is, and what it is: quad count target, material, file size.

## Endpoints

| Method | Path | Does |
|---|---|---|
| `POST` | `/tasks` | Create a task (multipart form). `201 {"task_id","status"}` |
| `GET` | `/tasks/{id}/download?wait=60` | The GLB once completed. `409` while not ready. |
| `GET` | `/tasks/{id}` | Task status. `status` is `completed` or `failed` when done; any other value means still working. |
| `GET` | `/tasks` | Your tasks, newest first. |
| `DELETE` | `/tasks/{id}` | Cancel a queued task, or delete a finished one. `409` while it is running. |

## Parameters for `POST /tasks`

| Field | Values | Default | Notes |
|---|---|---|---|
| `image` | PNG, JPEG or WebP file, max 20 MB each | required | One object, fully in frame. The background is removed automatically. Repeat the field for several views of the same object (see Multi-view). |
| `quads` | 1000–20000 | 5000 | Target quad count. The result lands near the target, not exactly on it. |
| `material` | `pbr` | - | Always send `material=pbr`: base color, metallic and roughness maps. |
| `normal_map` | `true`, `false` | `true` | Normal map of the fine surface detail. `false` makes the file about 1.4 MB smaller. |
| `seed` | integer | 42 | Same image and seed give the same mesh. Change it for a variation. |

## Multi-view

When the user has several pictures of the same object from different sides, send them all in one task: repeat the `image` field, up to 4 images. Any viewpoints work; no camera poses are needed.

- Put the front view first. The textures follow the first image.
- Every image is a view of the same object. Never mix different objects in one task.
- Several views take longer than one image: generation uses every view at every step, so expect roughly N times the wait for N views.
- A task with more than one image costs 3× a single image. Use several views only when the user provides them or asks for them; one good image is usually enough.

```bash
curl -sS -X POST "$BASE/tasks" \
  -H "Authorization: Bearer $UNBOUND_API_KEY" \
  -F image=@front.png -F image=@left.png -F image=@back.png \
  -F material=pbr -F quads=5000
```

## Optional: make or edit the input image

Only for when there is no image to start from. If the user gave you an image, use it as is. If you or the user already have an image generator, use that instead. This endpoint is a convenience on the same key: an image from a prompt, or an edit of the user's image (Nano Banana 2), billed in the same credits.

- URL: `https://loop.unbound.io/api/v1/images` (not the API base above). Same `Authorization` header.
- Synchronous: the response body is the image itself, usually within 10-30 s. The credits charged are in the `X-Unbound-Credits` header.
- Cost per image: about 0.67 credits at 1K, 1.01 at 2K, 1.51 at 4K, on top of the mesh. Tell the user before you use it.

```bash
code=$(curl -sS -o input.png -w '%{http_code}' -X POST "https://loop.unbound.io/api/v1/images" \
  -H "Authorization: Bearer $UNBOUND_API_KEY" \
  -F prompt="A weathered wooden treasure chest with iron bands, three-quarter view, the whole object in frame and centered, plain white background, soft even lighting, no text")
[ "$code" = 200 ] || { cat input.png >&2; rm -f input.png; }   # on error the body is JSON
```

To edit an image, send it too: `-F image=@photo.jpg -F prompt="Remove the table and the clutter, keep only the lamp, plain white background"`. With several images, the prompt can name them "image 1", "image 2" in upload order.

For a good mesh, ask for: one object, whole and centered in the frame, plain background, soft even light, no text or floor shadow. For multi-view, make the front first, then send it back as `image` with "the same object seen from the back" (and the sides), and pass all of them to `/tasks`.

| Field | Values | Default | Notes |
|---|---|---|---|
| `prompt` | text, up to 4000 characters | required | What to make, or how to change the images. |
| `image` | PNG, JPEG or WebP, max 10 MB each, 14 MB in all | none | Up to 4. Images to edit or follow. |
| `size` | `1K`, `2K`, `4K` | `1K` | 1K is plenty as Unbound Zero input. |
| `aspect_ratio` | 1:1, 2:3, 3:2, 3:4, 4:3, 4:5, 5:4, 9:16, 16:9, 21:9 | follows the input image, else square | Use `1:1` for an image meant for `/tasks`. |

Limits: at most 20 images a minute and 3 requests at once per key. A `422` with a `reason` means the content filter declined the request: change the prompt, don't resend it. Every image returned is billed, so don't retry a request that timed out on your side in a loop.

## Limits - follow these

- Keep at most 3 tasks in progress per key (created, not yet completed or failed). For a batch, keep a pool of 3 and submit the next image only when one finishes.
- Ask the user before submitting more than 10 images in one go. Every task costs credits.
- Use `download?wait=60` to wait. If you poll `GET /tasks/{id}` instead, wait at least 5 seconds between requests.
- Never retry `POST /tasks` blindly. After a timeout or network error, call `GET /tasks` and check whether the task was created before submitting again.
- Don't resubmit to get the same result again: the same image and seed give the same mesh. Download it again instead.
- Download results within an hour of completion. Finished tasks are not kept.

## Errors

Errors are JSON: `{"detail": "..."}`.

| Status | Do |
|---|---|
| `401` | Key missing, wrong or revoked. Stop and ask the user. |
| `402` | Out of credits. Stop and tell the user. Do not retry. |
| `404` | Unknown task ID. |
| `409` | Not ready yet (repeat the download), task failed, or the task is running (for `DELETE`). |
| `422` | Bad input: file type, size, a parameter out of range, or more than 4 images. With several images the message starts with "Image N:" for the one at fault. Fix it; don't resend unchanged. |
| `429`, `503` | Wait for `Retry-After` (or 30 s if absent), then retry with backoff. |

## Output

- Binary glTF (`.glb`), one mesh, one material, UVs, embedded PNG textures.
- Draco-compressed. Loaders need a Draco decoder: three.js `DRACOLoader`; Blender and Unreal import it as is.
- Y-up, roughly within a unit cube centered on the origin. Scale it to real-world size in the target engine.
- glTF stores triangles, so each quad is written as two triangles.

1. Submit an image

curl -sS -X POST https://unbound-3dgen-server-618775028388.us-central1.run.app/api/v2/tasks \
  -H "Authorization: Bearer $UNBOUND_API_KEY" \
  -F image=@chest.png -F material=pbr -F quads=5000

# {"task_id":"3f2c9a…","status":"queued"}

Several views of the same object: repeat -F image=@…, up to 4, front view first. Any viewpoints, no camera poses needed. Costs 3× and takes longer than one image.

2. Download the mesh

curl -sS -f -o chest.glb \
  -H "Authorization: Bearer $UNBOUND_API_KEY" \
  "https://unbound-3dgen-server-618775028388.us-central1.run.app/api/v2/tasks/3f2c9a…/download?wait=60"

The request waits up to 60 s for the mesh. 409 means not ready yet: send it again.

Endpoints

RequestDoes
POST /tasksCreate a task. Multipart form.
GET /tasks/{id}/download?wait=60The GLB, once complete.
GET /tasks/{id}Status: completed, failed, or still working.
GET /tasksYour tasks, newest first.
DELETE /tasks/{id}Cancel a queued task or delete a finished one.

Parameters

FieldValuesDefault
imagePNG, JPEG or WebP, max 20 MB each. Background removed automatically. Repeat for up to 4 views of one object, front first (3× price).required
quads1,000–20,000 target quads.5,000
materialpbr: base color, metallic, roughness. Always send it.–
normal_maptrue / false. Off saves ~1.4 MB.true
seedInteger. Same image and seed, same mesh.42

Errors

401Key missing or revoked.
402Out of credits.
409Not ready yet, or the task failed.
422Bad image or parameter, or more than 4 images.
429 503Back off. Honour Retry-After.

Limits

  • Up to 3 tasks in progress per key. Submit more as they finish.
  • Wait with ?wait=60 instead of polling. If you poll, every 5 s at most.
  • Don’t retry a create after a timeout. Check GET /tasks first: every task is billed.
  • Download within an hour. Results are not stored.

Optional: no image yet?

If you already have an image, or your own image generator, you don’t need this. Otherwise the same key makes one from a prompt, or edits yours, with Nano Banana 2. The image comes back in the response, ready for POST /tasks.

curl -sS -o chest.png -X POST https://loop.unbound.io/api/v1/images \
  -H "Authorization: Bearer $UNBOUND_API_KEY" \
  -F prompt="A wooden treasure chest, three-quarter view, centered, plain white background"

# Edit instead: add -F image=@photo.jpg and say what to change.

Base URL is the site, not the mesh API. Synchronous: the body is the image, usually in 10–30 s. Credits charged are in the X-Unbound-Credits header.

Price per image

SizeCreditsUSD
1K0.67$0.067
2K1.01$0.101
4K1.51$0.151

For a short prompt. Input images add a little; the charge is what the generation actually used.

Parameters

FieldValuesDefault
promptWhat to make, or how to change the images. Up to 4000 characters.required
imagePNG, JPEG or WebP to edit or follow, up to 4, max 10 MB each. The prompt can call them “image 1”, “image 2”.none
size1K, 2K, 4K. 1K is plenty for a mesh.1K
aspect_ratio1:1, 2:3, 3:2, 3:4, 4:3, 4:5, 5:4, 9:16, 16:9, 21:9follows the input, else 1:1

Up to 20 images a minute and 3 at once per key. 422 with a reason: the content filter declined it, so change the prompt.