Metadata-Version: 2.4
Name: picoberry
Version: 0.1.0
Summary: Python client and CLI for the PicoBerry API — generate 3D models and images across multiple engines through one async REST API.
Project-URL: Homepage, https://picoberry.ai
Project-URL: Documentation, https://api.picoberry.ai/docs/
Project-URL: Source, https://github.com/UModeler/picoberry-python
Project-URL: Issues, https://github.com/UModeler/picoberry-python/issues
Author-email: "UModeler, Inc." <support@umodeler.com>
License: MIT
License-File: LICENSE
Keywords: 3d,ai,api,gamedev,glb,image-to-3d,picoberry,sdk,text-to-3d
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Multimedia :: Graphics :: 3D Modeling
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.9
Requires-Dist: httpx>=0.27
Provides-Extra: dev
Requires-Dist: pytest>=8; extra == 'dev'
Description-Content-Type: text/markdown

# picoberry

[![PyPI](https://img.shields.io/pypi/v/picoberry?color=e11d48)](https://pypi.org/project/picoberry/)
[![Python](https://img.shields.io/pypi/pyversions/picoberry)](https://pypi.org/project/picoberry/)

Python client and CLI for the [PicoBerry](https://picoberry.ai) API — generate 3D
models and images across several engines through one async REST API, from a
script or your terminal.

**What PicoBerry is:** an AI 3D generation platform for game developers, made by
UModeler, Inc. It turns a text prompt, a single image, or 2–4 multi-view images
into a textured 3D model, then remeshes, retextures, auto-rigs and animates it,
and exports GLB / FBX / OBJ. The same pipeline is reachable three ways — the web
app, this REST API, and an
[MCP server](https://www.npmjs.com/package/@picoberry/mcp-server) so AI agents in
Claude, Cursor, or Codex can generate assets directly. Generated assets are
engine-agnostic: Unity, Unreal Engine, Godot, and Blender.

> **Note on the name.** "PicoBerry" (Korean: 피코베리) is shared with unrelated
> Korean brands — an anti-noise floor-mat brand and a wedding-photography studio.
> This package is the AI 3D generation platform by UModeler, Inc.

**Requirements:** Python 3.9+ and a PicoBerry API key.

```bash
pip install picoberry
```

## Quickstart

```bash
export PICOBERRY_API_KEY=pb_live_xxxxxxxxxxxxxxxx

picoberry models                                        # engines + credit cost
picoberry 3d "a low-poly treasure chest" --wait -o chest.glb
```

```python
from picoberry import PicoBerry

pb = PicoBerry()                                   # reads $PICOBERRY_API_KEY
asset = pb.text_to_3d("a low-poly treasure chest") # returns immediately
asset = pb.wait(asset["id"])                       # polls until taskStatus == 2
print(asset["files"]["model"])                     # signed GLB URL
```

### Get an API key

Sign in at <https://picoberry.ai>, open the
**[API Keys](https://picoberry.ai/dashboard/api-keys)** tab, and hit **Create
key**. The key is shown once — copy it immediately and treat it like a password.

API access needs a completed purchase: a subscription **or a one-off credit
pack**. A purchase entitles you permanently — you don't need a *current*
subscription.

> `pb_live_` means "real key", not "production". A key is only valid against the
> backend that issued it.

| Env var | Required | Default |
|---|---|---|
| `PICOBERRY_API_KEY` | ✅ | — |
| `PICOBERRY_API_BASE` | — | `https://api.picoberry.ai` |

## How generation works

Every generation call is **asynchronous**: it returns an asset id, and you poll
until it finishes.

```python
asset = pb.text_to_3d("a low-poly treasure chest", engine="tripo")   # → {"id": ...}
asset = pb.wait(asset["id"])                                         # → taskStatus 2
asset["files"]["model"]                                              # GLB URL
```

`taskStatus`: `0` pending · `1` processing · `2` succeeded · `3` failed.
`wait()` raises `GenerationFailed` on failure (read `errorDetail`) and
`WaitTimeout` if it gives up — a timeout doesn't cancel the job, so poll
`get_asset()` later rather than resubmitting, which would spend credits again.

Result URLs are **signed and short-lived**. Download promptly instead of storing
them.

## Don't hardcode engines

The catalog changes. Ask for it:

```python
pb.models("3d")       # [{"name": "tripo", "label": "PB Slim", "cost": 60, ...}, ...]
```

Categories: `3d` · `image` · `remesh` · `texture` · `animate`. Use each entry's
`name` as the `engine` argument, and read `cost` before you spend.

## What it can do

| | |
|---|---|
| `models(category)` · `animations(engine)` · `credits()` | catalog and balance |
| `text_to_image(prompt, …)` | text → image |
| `text_to_3d(prompt, …)` | text → 3D (GLB) |
| `image_to_3d(url \| urls \| path, …)` | image → 3D, single or 2–4 views |
| `remesh(id, polycount=…)` | retopologize → **new** asset |
| `texture(id, prompt=…)` | re-texture (PBR) → **new** asset |
| `animate(id, preset=…)` | auto-rig + animate → **new** asset |
| `get_asset(id)` · `list_assets(…)` · `wait(id)` | status and browsing |
| `download(id, format=…)` | export `glb` / `fbx` / `obj` |

### Multi-view image → 3D

Two to four views of the same subject beat one, because the engine stops guessing
at the back:

```python
pb.image_to_3d(image_urls=[front, left, back, right], engine="meshy6")
```

Order is `[front, left, back, right]` — pass a prefix of it. Out-of-order views
degrade the result rather than erroring. Supported by `tripo*`, `meshy6`, and
`hunyuan-3.x`; `models("3d")` is the live list.

### Exporting

```python
pb.download(asset_id, format="fbx", texture_preset="unity")
# → {"url": ..., "archive": True, "filename": "chest.zip", ...}
```

`glb` is a single self-contained file. **`fbx`/`obj` arrive as a zip** (model +
textures, plus Unity `.meta` files with `texture_preset="unity"`) — unzip before
importing. Unity has no built-in glb importer, so use `fbx` there.

## CLI

```
picoberry models [--category 3d|image|remesh|texture|animate]
picoberry credits
picoberry presets [--engine ENGINE]
picoberry 3d PROMPT [--engine E] [--polycount N] [--no-texture] [--wait] [-o FILE]
picoberry image PROMPT [--model M] [--aspect-ratio W:H] [--wait] [-o FILE]
picoberry from-image URL_OR_PATH... [--engine E] [--wait] [-o FILE]
picoberry asset ID
picoberry wait ID [--timeout SECONDS]
picoberry assets [--category C] [--limit N]
picoberry download ID [--format glb|fbx|obj] [--texture-preset standard|unity] [-o FILE]
```

Add `--json` to any command to get the raw API payload instead of a table, so it
composes with `jq`.

## Examples

Runnable scripts in [`examples/`](examples):

| | |
|---|---|
| [`text_to_3d.py`](examples/text_to_3d.py) | Prompt → GLB, saved to disk |
| [`image_to_3d.py`](examples/image_to_3d.py) | Single image and multi-view |
| [`remesh_and_export.py`](examples/remesh_and_export.py) | Generate → retopologize → Unity FBX |

## Errors

All of them subclass `PicoBerryError`:

| | |
|---|---|
| `AuthenticationError` | 401/403 — key missing, malformed, or from another environment |
| `InsufficientCreditsError` | 402 — check `credits()` and per-engine `cost` |
| `NotFoundError` | 404 |
| `RateLimitError` | 429 |
| `APIError` | any other non-2xx; carries `status_code` and `payload` |
| `GenerationFailed` | `taskStatus == 3`; `.asset` holds the payload |
| `WaitTimeout` | `wait()` gave up; the job is still running |

Messages come from the API, so a bad engine name comes back with the list of
valid ones.

## What you get — and what you don't

PicoBerry produces **strong starting points**, not finished art. A generated
asset is a candidate: useful for prototyping, iteration, review, and handoff.
Depending on your project you may still want to review topology, UVs, materials,
scale, collisions, rigging, and licensing before it ships.

We deliberately don't promise that every result drops into a game as-is. The
useful promise is workflow value: faster starting points, more candidate
directions, and export paths into your engine.

## Related

- **API reference** — <https://api.picoberry.ai/docs/>
- **Web app** — <https://picoberry.ai>
- **MCP server** — [`@picoberry/mcp-server`](https://www.npmjs.com/package/@picoberry/mcp-server) ([source](https://github.com/UModeler/picoberry-mcp)) — the same API inside Claude Code, Cursor, Claude Desktop, and Cline

## License

MIT
