# Rosebud for developers

URL: /docs/get-started

> Host browser games for free and make game assets with your Rosebud credits, from a terminal or a coding agent.

The Rosebud CLI does two things:

* **Free game hosting.** Publish a browser game's build folder and get a link anyone can play. Updates go to the same link.
* **Game assets**. Make sprites, 2D art, skyboxes, 3D models, video clips, sound effects, music and speech with your Rosebud credits, at the same prices as the website.

Every command prints JSON, so coding agents like Claude Code, Codex and Cursor can run the whole flow and read the results.

- [Quickstart](/docs/get-started/quickstart.md): Install the CLI and publish a game in a few minutes.
- [Use a coding agent](/docs/get-started/coding-agents.md): Give your agent one prompt, or point it at the Markdown docs.
- [Make assets](/docs/guides/make-assets.md): Log in once, check the price, and save files into your game.
- [Models](/docs/models.md): Every model, its inputs, price and license.

## What's in these docs

| Section                                     | What's there                                               |
| ------------------------------------------- | ---------------------------------------------------------- |
| [Get started](/docs/get-started/quickstart.md) | Install, first publish, and how sign-in works.             |
| [Guides](/docs/guides/publish-a-game.md)       | Step-by-step tasks: publishing, claiming, updates, assets. |
| [CLI](/docs/cli.md)                            | One page per command, with every flag, output and error.   |
| [HTTP API](/docs/api.md)                       | The endpoints the CLI calls, for building your own client. |
| [Models](/docs/models.md)                      | The asset models, generated from the live model list.      |

Every page is also available as Markdown: add `.md` to its URL. The whole site is indexed for agents at [`/docs/llms.txt`](/docs/llms.txt).

# Quickstart

URL: /docs/get-started/quickstart

> Install the Rosebud CLI and publish your first game.

You need Node.js 22 or later.

### 1. Install the CLI

```sh
npm install --global @rosebudai/cli
```

To run it without installing, use `npx @rosebudai/cli` in place of `rosebud`, for example `npx @rosebudai/cli publish --directory ./dist`.

### 2. Publish your build folder

Build your game, then publish the build folder from your project's root:

```sh
rosebud publish --directory ./dist --title 'Moon Garden' \
  --description 'Collect five glowing seeds.'
```

Already have a ZIP? Use `--zip ./game.zip` instead of `--directory`. No build step? Copy `index.html` and everything it loads into a folder such as `./dist` and publish that, not the project root.

### 3. Play it

Open the `play_url` from the result and play the game. A successful upload means the files were accepted, not that the game works.

### 4. Claim it within an hour

Open the `claim_url`, sign in and select **Claim game**. Unclaimed games are deleted after one hour. If you ran [`rosebud login`](/docs/cli/login.md) first, the game is already in your account and there's nothing to claim.

Planning to ship updates? Run `rosebud connect` instead and open its `approval_url`. Approving it claims the game and lets the CLI update it, in one step.

The CLI saves the game's details in `.rosebud/project.json`, so later commands know which game to update. Add `.rosebud/` to `.gitignore`.

## Next steps

- [Publish updates](/docs/guides/publish-updates.md): Connect the game once, then ship new builds to the same link.
- [Make assets](/docs/guides/make-assets.md): Art, 3D models and sound, paid with your credits.

# Use a coding agent

URL: /docs/get-started/coding-agents

> Let Claude Code, Codex, Cursor or Gemini CLI publish your game and make its assets.

The CLI is built for agents: every command prints one JSON object, errors say what to fix, and an interrupted `update`, `pull` or `assets create` is safe to run again (an interrupted `publish` is not).

## Give your agent a prompt

Paste this into your agent:

```text
Publish this game with Rosebud. Follow the instructions at https://rosebud.ai/developer-publishing/AGENTS.md.
```

To make art and sound as well:

```text
Make the art and sound this game needs with Rosebud. Follow the instructions at https://rosebud.ai/developer-assets/AGENTS.md. Show me the price before you make anything over 500 credits, and save the files into the project's assets folder.
```

The agent installs the CLI, runs the commands and gives you any link you need to open, such as a claim or approval link.

## Agent instructions

These files have the same steps as the guides, written as instructions for an agent:

| File                                                                 | Covers                                          |
| -------------------------------------------------------------------- | ----------------------------------------------- |
| [`/developer-publishing/AGENTS.md`](/developer-publishing/AGENTS.md) | Publishing, claiming and updating a game.       |
| [`/developer-assets/AGENTS.md`](/developer-assets/AGENTS.md)         | Signing in, choosing a model and making assets. |

## Markdown for every page

* Add `.md` to any docs URL for its Markdown, for example [`/docs/cli/publish.md`](/docs/cli/publish.md).
* [`/docs/llms.txt`](/docs/llms.txt) lists every page with a one-line description.
* [`/docs/llms-full.txt`](/docs/llms-full.txt) has every page in one file.

Each page also has **Copy Markdown** and **Open** buttons for pasting it into ChatGPT, Claude or another tool.

## What agents can and can't do

Agents never see your password, and every kind of access needs you to approve a link. See [Sign-in and access](/docs/get-started/access.md) for what each approval allows.

# Sign-in and access

URL: /docs/get-started/access

> Claim links, game connections and agent logins, and what each one allows.

The CLI never asks for your password or an API key. Instead, it prints a private link, and you open it, sign in on rosebud.ai and approve.

| Link                             | Comes from                         | Lets the CLI                                                                         | Expires                                               |
| -------------------------------- | ---------------------------------- | ------------------------------------------------------------------------------------ | ----------------------------------------------------- |
| Claim link (`claim_url`)         | `rosebud publish`, without a login | Nothing. It moves the game into your account.                                        | One hour after upload                                 |
| Game connection (`approval_url`) | `rosebud connect`                  | Update one game: its files, title, description and cover.                            | Link: 30 minutes. Access: 90 days.                    |
| Agent login (`approval_url`)     | `rosebud login`                    | Make and download assets with your credits, and publish new games into your account. | Link: 30 minutes. Access: 90 days after its last use. |

Keep all three links private. Anyone who has one can use it.

## Game connections

A connection covers a single game. It can't reach your other games, your account or billing, or run AI generation. Revoke it in the game's **Project Settings → Manage connected agents** (not the Connected agents page), or run [`rosebud disconnect`](/docs/cli/disconnect.md).

## Agent logins

A login can make assets, list and download your assets, and publish new games into your account. It can't change billing or manage your account. Revoke it on your account's [Connected agents](/developers/keys) page, or run [`rosebud logout`](/docs/cli/logout.md).

An expired login isn't renewed: approve a new one with `rosebud login`. Logging out, or a login that expires, doesn't disconnect the games it published. Each of those has its own game connection, which lasts 90 days.

## Where credentials are stored

The CLI keeps credentials in `~/.config/rosebud/credentials` with private file permissions, separate from the project. Set `ROSEBUD_CREDENTIALS_DIR` to use another folder. Game details (not secrets) go in `.rosebud/project.json` in your project.

# Publish a game

URL: /docs/guides/publish-a-game

> Put a browser game online for free and get a link anyone can play.

You don't need an account to publish. To keep a game, sign in and [claim it](/docs/guides/claim-your-game.md) within an hour. Or run [`rosebud login`](/docs/cli/login.md) first, so new games go straight into your account.

No game yet? Clone [rosebudai/rosebud-cli](https://github.com/rosebudai/rosebud-cli) and run `rosebud publish --directory ./examples/signal-garden`.

## Publish the build folder

Build your game, then run this from your project's root:

```sh
rosebud publish --directory ./dist --title 'Moon Garden' \
  --description 'Collect five glowing seeds.'
```

* The title and description are optional. They appear on the game's play page.
* Add `--thumbnail ./cover.png` for a cover (see [Game details](#game-details)).
* Already have a ZIP? Use `--zip ./game.zip` instead of `--directory`.

Don't publish the project root. The CLI keeps its state in `.rosebud/` there, and hidden files such as `.gitignore` can't be uploaded. With no build step, copy the files your game needs into `./dist` and publish that.

Open the `play_url` and play the game. A successful upload means the files were accepted, not that the game works.

If you're signed in with a login that's still waiting for approval, `publish` fails with `login_pending`. Approve the login, or run `rosebud logout` to publish with a claim link instead.

## What you can upload

* `index.html` at the top level of the build folder.
* Text files, anywhere in the build: HTML, JavaScript, CSS and JSON, Markdown notes such as `AGENTS.md`, and any other UTF-8 file that isn't media. A text file may have any name the Rosebud editor allows, except hidden names (a leading dot), names of only spaces, and names with `< > : " | ? * / \` or control characters. A name is at most 255 characters and a path at most 500.
* UTF-8 text notices: `.txt` files (including `.TXT`) and extensionless `LICENSE`, `LICENCE`, `NOTICE`, `COPYING`, `COPYRIGHT` and `AUTHORS`. They keep their original names; the media naming rules don't apply to them. Don't remove required notices to make an upload pass.
* Media inside `assets/`. Names are lowercase letters, numbers, underscores and single hyphens; they start and end with a letter or number, and use dots only for the extension. Media elsewhere is refused with `media_path`, and an empty media file with `file_limit`.
  * Images: PNG, JPEG, WebP and SVG
  * Audio: MP3, WAV, OGG and OGA
  * Fonts: WOFF, WOFF2, TTF and OTF
  * WASM, and GLB and glTF models with their `.bin` buffers

Outside `assets/`, `.svg` and `.gltf` files are text. Names are compared in Unicode NFC, so two names that differ only in how an accented letter is stored are one name; keep one, or the upload is refused with `duplicate_path`.

### Limits

| Limit                              | Size                                                                   |
| ---------------------------------- | ---------------------------------------------------------------------- |
| Text files                         | One ZIP: 10 MiB zipped, 50 MiB unzipped, 500 entries                   |
| One media file                     | 19 MiB (media uploads file by file)                                    |
| Whole game                         | 2,000 files and 1 GiB                                                  |
| New media in one publish or update | 128 MiB (`release_upload_limit`)                                       |
| Image size                         | 10,000 pixels a side                                                   |
| `--zip` archive                    | All of it, media included: 10 MiB zipped, 50 MiB unzipped, 500 entries |

Files Rosebud already has, with the same path, size and MD5, aren't uploaded again and don't count toward the 128 MiB. Over that, publish with part of the media, then `update` with the rest. `--zip` sends your archive as it is, so use `--directory` for a game with more media than the ZIP limits allow. CLI 0.1.0 sends the whole build as one ZIP under the text-file limits; update to 0.2.0 for bigger games.

Large games can take minutes to upload, because each media file goes up on its own and Rosebud may first check the files it already has.

Rosebud serves your files as they are and doesn't run a build. `.DS_Store`, `Thumbs.db` and `desktop.ini` are skipped, never uploaded and never an error. Other hidden files, symbolic links, dependency folders and unsupported file types are rejected.

> Everything you upload is public. Keep credentials and `.env` files out of the build. Rosebud refuses names ending in `.env`, `credentials`, `secrets`, `credentials.json`, `service-account.json`, `service_account.json`, `node_modules` and anything containing `firebase-adminsdk` (`excluded_file`), and any file that holds a private key.

Hosted games are unlisted: anyone with the link can play, but they don't appear in Rosebud's game listings.

## Game details

All of these are optional, for both `publish` and `update`:

| Option          | Details                                                                  |
| --------------- | ------------------------------------------------------------------------ |
| `--title`       | Up to 255 characters. Changing it later keeps the same play link.        |
| `--description` | Up to 4,000 characters.                                                  |
| `--thumbnail`   | A PNG or JPEG gameplay screenshot, at most 2 MiB and 4096 pixels a side. |

Agents can also pass `--agent-client` (`claude-code`, `codex`, `cursor`, `gemini-cli` or `other`) to say which tool published the game.

# Claim your game

URL: /docs/guides/claim-your-game

> Keep a game you published without an account, before its one-hour deadline.

A new upload is playable right away, but it's temporary until someone claims it. The result's `claim_expires_at` is the deadline, one hour after upload.

To claim it, open the `claim_url`, sign in and select **Claim game**.

* **Claimed in time:** the game moves into your Rosebud account, keeps its link and opens in the Rosebud editor. It no longer expires.
* **Not claimed:** at the deadline the game, its files and its links stop working, and the game is permanently deleted. There's no late claim.

Keep the claim link private. Anyone who has it can claim the game.

> Signed in with [`rosebud login`](/docs/cli/login.md)? Then `publish` puts the game straight into your account. The
> result has `claimed: true` and an `editor_url`, and there's no claim link.

## If a game expires

Publish the same build again as a new game. Use a new state file so the CLI doesn't confuse it with the deleted one:

```sh
rosebud publish --directory ./dist --state .rosebud/new-project.json \
  --title 'Moon Garden'
```

The new game gets a new link. Pass the same `--state` to later commands for it.

# Publish updates

URL: /docs/guides/publish-updates

> Connect a game once, then ship new builds to the same link.

## Connect the game

```sh
rosebud connect
```

This prints a private `approval_url`. Open it, sign in and select **Allow updates**. If the game isn't claimed yet, the button reads **Claim game and allow updates**, and approving also claims it. The link expires after 30 minutes; run `rosebud connect` again for a new one.

Published with an active [`rosebud login`](/docs/cli/login.md)? The connection is already saved, so skip this step.

## Ship a new build

```sh
rosebud status
rosebud update --directory ./dist
```

* Rebuild first, or copy your files into `./dist` again if you have no build step.
* [`status`](/docs/cli/status.md) shows whether access is active and which version of the game is live.
* Titles, descriptions and covers you don't pass to `update` stay as they are.
* `update` makes the game exactly the folder you give it. A file the game has that the folder lacks is removed from the game, and files Rosebud already has aren't uploaded again.
* If an update is interrupted, run the same command again. It won't publish twice.

## If the game changed on Rosebud

Edits in the Rosebud editor, changes by Rosie and updates from another agent make your saved version stale. `update` then stops with `version_conflict` (exit 3) instead of overwriting, and changes nothing. Its `changed_paths` says what changed:

| `changed_paths` | Meaning                                                                                           |
| --------------- | ------------------------------------------------------------------------------------------------- |
| A list of paths | Rosebud changed, added or removed these files since your last sync (up to 4,000 paths).           |
| `[]`            | No file changed. Only the title, description, cover or published copy did.                        |
| `null`          | Rosebud can't tell which files changed, for example for a version you learned only from `status`. |
| Missing         | This Rosebud server doesn't report changed files.                                                 |

For `[]`, run `rosebud status` and pass its `content_version` as `--expected-version`.

Bring those changes in with [`rosebud pull`](/docs/cli/pull.md), then update:

```sh
rosebud pull --directory ./dist
rosebud update --directory ./dist
```

`pull` keeps your own edits and lists any file changed on both sides as a conflict to merge; `rosebud pull --force` takes Rosebud's version of each conflicted file instead. Files Rosebud has that your folder lacks are listed under `missing_locally`, and the next update removes them from the game unless you restore them. If your game has a build step, pull into a new, empty folder such as `./rosebud-files`, copy the changes into your source and rebuild, then update with `--expected-version <content_version from the pull>`. If you can't pull (it needs the owner's plan to include code download), ask what changed in the editor and make the same changes locally, then accept the current version explicitly:

```sh
rosebud update --directory ./dist --expected-version <content_version from status>
```

`update` never merges or overwrites on its own.

## On another computer

```sh
rosebud connect --project <project_id>
```

This works for a claimed game. The project ID is in `.rosebud/project.json`, or in the editor's address, `https://rosebud.ai/edit/<project_id>`. Approve the new link, then run `rosebud status` before your first update.

## Revoke access

Access lasts 90 days and covers only this game. Revoke it any time in the editor under **Project Settings → Manage connected agents**, or run:

```sh
rosebud disconnect
```

The game stays online.

# Edit a game made in Rosebud

URL: /docs/guides/edit-a-rosebud-game

> Bring a game made in the Rosebud editor into a folder, change it locally and publish it back.

Use this to change a game someone built in the Rosebud editor, with your own tools or a coding agent. Pulling needs Rosebud Pro or higher on the owner's account, for code download; see [Pricing](/pricing). Without it, `pull` fails with `plan_required`, while `update` still works: tell your agent what you changed in Rosebud before it updates.

### 1. Connect to the game

Find the project ID in the editor's address, `https://rosebud.ai/edit/<project_id>`, then run:

```sh
rosebud connect --project <project_id>
```

Open the `approval_url` it prints, sign in as the game's owner and approve. `rosebud status` reports `active` once you have.

### 2. Pull its files

```sh
rosebud pull --directory ./game
```

This writes the game's current files, text and media, including edits made in Rosebud, into `./game`. Use a folder that holds only the game: `update` refuses hidden files such as `.git`. On Windows, a name Windows can't keep (one ending in a dot or space, or a device name such as `con.js`) is skipped.

Games made with Rosie include `AGENTS.md` and other notes. Read them before you change anything.

### 3. Edit and publish

```sh
rosebud update --directory ./game
```

The game keeps its link. Files Rosebud already has aren't uploaded again. Keep new media in `assets/` with [lowercase names](/docs/guides/publish-a-game.md#what-you-can-upload).

Media the editor accepts but an update can't upload, such as MP4, GIF, WebM, M4A, FBX or OBJ, is kept only if you leave the file unchanged at the same path. Changing or renaming one is refused with `unsupported_file`: do that in the Rosebud editor, then pull again.

If someone keeps editing in Rosebud while you work, run `rosebud pull --directory ./game` again before each update. It brings in their changes and keeps yours. See [`rosebud pull`](/docs/cli/pull.md) for conflicts.

# Make assets

URL: /docs/guides/make-assets

> Make sprites, 2D art, skyboxes, 3D models, video and sound with your Rosebud credits.

Assets are paid for with your Rosebud credits, at the same prices as the website. Everything you make also shows up in [My assets](/assets). Need more credits? See [Pricing](/pricing).

### 1. Log in once

```sh
rosebud whoami
```

If it reports `"status": "active"`, skip ahead. If it reports another status, or fails with `login_required`, run:

```sh
rosebud login
```

Open the `approval_url` it prints, sign in and select **Allow**. Then run `rosebud whoami` again. It shows your credit balance once the login is active.

Agents should add `--agent-client` (for example `--agent-client claude-code`) so you can tell their logins apart when you approve them.

### 2. Choose a model

```sh
rosebud assets models --category image
```

Each model lists its inputs, price and license. Categories are `image`, `skybox`, `model_3d`, `video`, `sound_effect`, `music` and `speech`. Leave out `--category` to see every model, or browse the same list on [Models](/docs/models.md).

### 3. Check the price

```sh
rosebud assets quote --model flux-2-flash --prompt 'green slime monster, side view' \
  --input asset_type=sprite
```

Quotes are free and check your inputs. `--prompt` fills the model's `prompt` input, and `--input name=value` sets any other input it lists. Add-ons, such as a transparent background for a sprite, are included in the price.

### 4. Make the asset

```sh
rosebud assets create --model flux-2-flash --prompt 'green slime monster, side view' \
  --input asset_type=sprite \
  --max-credits 300 --out ./assets/slime.png
```

* `--max-credits` caps the price. `create` refuses a higher quote before anything is charged.
* `create` waits for the file (up to 10 minutes) and saves it to `--out`. It never replaces an existing file unless you pass `--force`.
* With `--no-wait` it returns the job at once. Check it with `rosebud assets status <job_id>`, then save the file with `rosebud assets download <asset_id> --out <path>`.
* Credits are charged when a job starts and returned if generation fails.

### 5. Use it in the game

Save files where the game loads them, then load the game and check each file appears or plays. If you'll publish with Rosebud's free hosting, keep media inside `assets/` with lowercase names. See [Asset formats and tips](/docs/guides/asset-results.md) for sizes and quirks.

## Reuse an asset you already made

Everything you make, from the CLI or the website, stays in My assets. Search it and download a file instead of paying again:

```sh
rosebud assets list --query 'slime'
rosebud assets download <asset_id> --out ./assets/slime.png
```

`list` shows the 25 newest matches. Narrow it with `--query` or `--category` (`image`, `sprite`, `skybox`, `model_3d`, `audio` or `file`). `sprite` means animated sprite sheets made on the website; images made with `asset_type=sprite` are `image`. `audio` covers sound effects and music.

## Rules for agents

* Show the person the price before anything expensive, and pick the cheapest model that fits.
* Make one asset per command. Make variations by changing the prompt or inputs.
* Run a few commands at a time, not dozens. Quotes and job starts share a limit of 30 per minute per account. The CLI waits out a throttle for up to a minute before it reports `throttled`.
* Keep the login while you work. Run `rosebud logout` only to switch accounts or when the person asks.
* If a command exits with code 4, run the identical command again. It resumes the same job and won't pay twice.
* Don't retry when the person is out of credits. Tell them instead.
* When you're done, tell the person what you made and what it cost.

# Asset formats and tips

URL: /docs/guides/asset-results

> Sizes, formats and quirks of each kind of asset, and how to use them in a game.

## Images

* Flux 2 Flash backgrounds and textures are 1024×1024, with no size or aspect-ratio input. Crop or scale them in the game.
* Transparent types (`sprite`, `icon`, `character_portrait` and the like) are cropped to their content, so their sizes vary.
* PNGs run 1–2 MB each. Add `--input output_format=webp` when the game will be hosted: smaller files load faster, and a hosted game has [size limits](/docs/guides/publish-a-game.md#limits).
* `texture_tile` images are close to seamless but not exact. Check the edges before tiling them across a large surface.
* To keep a character the same across poses or expressions, pass its image to a model that takes `image` (such as `nano-banana-pro` or `gpt-image-2-5`) and describe only the change. `qwen-multiple-angles` shows the same subject from another side. With Flux 2 Flash, which takes no image, repeat the same description and the same `--input seed=<n>`, changing only the pose.
* `remove-background`, `crisp-upscale` and `vectorize` take an existing image. `recraft-4-1-svg` and `vectorize` return SVG; `ideogram-tiling` returns a seamless texture.
* There's no sprite animation model yet. A sprite sheet asked of an image model often comes back in a different grid or frame count than requested, so slice it by content rather than by a fixed grid.

Run `rosebud assets models` for the current models and what each one accepts.

## Skyboxes

`rosebud-skybox` returns a 2:1 equirectangular WebP. In three.js, load it with `TextureLoader`, set its `mapping` to `THREE.EquirectangularReflectionMapping`, and assign it to both `scene.background` and `scene.environment`.

## 3D models

`rosie-3d` makes GLB files about 1 unit along their longest side, Y up, facing +Z, with the base at y = 0.

* They use the `KHR_mesh_quantization` and `EXT_texture_webp` extensions, which three.js loads.
* Humanoid characters usually come back rigged, with a Mixamo-style skeleton and about 80 animation clips such as `Idle`, `Walk`, `Run` and `Death01`. Read the clip names from the file.
* Metallic surfaces render nearly black without an environment map. A skybox set as the scene's environment lights them.

Other 3D models (`meshy-7-1`, `tripo-p2`, `rodin-2-5`) make GLBs at their own scale and facing, so measure the bounding box and scale each one in the game. They aren't rigged; `meshy-rigging` adds a humanoid skeleton to a character GLB.

## Videos

MP4 clips up to 10 seconds, for cutscenes, intros and backgrounds. An `image` input becomes the first frame. Clips cost far more than images, and the price depends on length, so quote first and keep them short.

## Speech

An MP3 of the prompt read aloud, priced by its length. Name an ElevenLabs voice with `--input voice=<name>`.

## Sound effects

0.5–5 second MP3s. Ask for one sound per clip, since a second event in the same prompt is usually dropped. Loudness varies between clips, so set each one's volume in the game.

## Music

At most 30 seconds, and it may fade out at the end even when the prompt asks for a loop. Trim the fade before looping it.

> Give every game with sound a mute button and a volume control, and start music quieter than effects. People often
> play with others around, on a call or in class.

# Troubleshooting

URL: /docs/guides/troubleshooting

> Common errors, what to do about each, and how to recover from interrupted commands.

Commands print JSON (except `--help` and `--version`): results on stdout, errors on stderr. Errors include a `code`, a `message` that says what to fix and often a `next_action`. When Rosebud rejects a specific file, `filename` names it. The [CLI overview](/docs/cli.md#exit-codes) lists the exit codes.

## Unknown results (exit 4)

* **`publish`:** the game may already exist. Don't publish again right away; a new publish creates a second game.
* **`update`:** run the same command again without changing your files. It won't publish twice, and it sends the media the way the first attempt did. If the folder changed meanwhile, it refuses with `pending_operation`.
* **`pull`:** run it again. It finishes the work.
* **`assets create`:** run the identical command again. It resumes the same job and won't pay twice.

With `outcome` `not_sent`, nothing was released.

When Rosebud throttles a request, the CLI waits as long as Rosebud asks and sends it again, for up to a minute. It never sends a publish or update again on its own.

## Common errors

### Publishing

| Error                                                             | Fix                                                                                                                                                                                                                                    |
| ----------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `state_in_build`, or `unsafe_path` for a hidden file              | You published the project root. Publish the build folder, or a copy of the game in `./dist`.                                                                                                                                           |
| `missing_index`                                                   | Put `index.html` at the top level of the folder you publish.                                                                                                                                                                           |
| `media_path`, `noncanonical_path`                                 | Usually bundler output. Vite adds mixed-case hashes to asset names and copies `public/` to the build root. Move `public/` media under `public/assets/` and set `build.rollupOptions.output.assetFileNames` to `'assets/[name].[ext]'`. |
| `compressed_limit`, `expanded_limit`, `entry_limit`, `file_limit` | The build or a file is too big, or a media file is empty. `limit` gives the bound. See [Limits](/docs/guides/publish-a-game.md#limits).                                                                                                   |
| `release_upload_limit`                                            | One publish or update adds more than 128 MiB of new media. Send part of it, then `update` with the rest.                                                                                                                               |
| `excluded_file`                                                   | Remove the credentials, `node_modules` or `.env` file the error names.                                                                                                                                                                 |
| `duplicate_path`                                                  | Two names in the folder are the same name in Unicode NFC. Keep one.                                                                                                                                                                    |
| `invalid_text`                                                    | The text file isn't UTF-8, has a NUL byte or holds a private key. Fix it, or move real binary media into `assets/`.                                                                                                                    |
| `unsupported_file`, `invalid_media`                               | Correct the named file. For editor-only media such as MP4, leave it unchanged at its path, or change it in the Rosebud editor.                                                                                                         |
| `file_changed`                                                    | A media file changed while uploading, for example during a build. Nothing was sent. Run the command again once the build has finished.                                                                                                 |
| `project_exists`                                                  | The state file already holds a game. Use `rosebud update`, or pass a new `--state` to publish another game.                                                                                                                            |
| `login_pending`                                                   | Your login still waits for approval. Approve it, or run `rosebud logout` to publish with a claim link.                                                                                                                                 |
| `game_expired`                                                    | The claim deadline passed. [Publish again as a new game](/docs/guides/claim-your-game.md#if-a-game-expires).                                                                                                                              |

### Updating

| Error                                                            | Fix                                                                                                                                             |
| ---------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| `connection_required`, `connection_pending`                      | Run `rosebud connect` and approve its link, then `rosebud status`.                                                                              |
| `invalid_connection`, `connection_expired`, `connection_revoked` | Access expired or was revoked. Run `rosebud connect` again.                                                                                     |
| `version_conflict`                                               | The game changed on Rosebud. See [Publish updates](/docs/guides/publish-updates.md#if-the-game-changed-on-rosebud).                                |
| `pull_conflicts`                                                 | Merge the files the last pull listed, then pull again or pass `--expected-version`. See [`rosebud pull`](/docs/cli/pull.md#conflicts).             |
| `directory_mismatch`                                             | You last pulled into another folder. Pull into this folder first, or pass `--expected-version` to release it anyway.                            |
| `pending_operation`                                              | An earlier update's outcome is unknown. Run it again unchanged, or run `rosebud status` and pass `--expected-version`.                          |
| `plan_required`                                                  | `pull` needs Rosebud Pro or higher on the owner's account. `update` still works; ask what changed in Rosebud first.                             |
| `folder_changed`, `download_corrupt`                             | A file changed while `pull` downloaded, or a download arrived damaged. `pull` left the folder as it was. Run it again.                          |
| `sync_unavailable`                                               | This Rosebud server can't read files back yet. Nothing changed; try again later.                                                                |
| `unsupported_project`                                            | Rosebud can't read this game's files back. Tell the game's owner.                                                                               |
| `upload_retry`                                                   | Rosebud is still checking the game's existing files. Run the same command again.                                                                |
| `project_busy`                                                   | Rosebud is generating in the game. Wait for it to finish, then run the command again.                                                           |
| `busy`                                                           | Rosebud is busy and changed nothing. Wait `retry_after_seconds`, then run the command again. A first `publish` refused as busy created nothing. |

### Assets

| Error                  | Fix                                                                                               |
| ---------------------- | ------------------------------------------------------------------------------------------------- |
| `login_required`       | No login on this computer. Run `rosebud login`.                                                   |
| `invalid_key`          | The login is pending or was disconnected. Run `rosebud whoami`, then `rosebud login`.             |
| `key_expired`          | The login wasn't used for 90 days. Run `rosebud login`.                                           |
| `insufficient_scope`   | The login lacks the permission in `required_scope`. Run `rosebud logout`, then `rosebud login`.   |
| `insufficient_credits` | You need more credits. Buy credits or upgrade on [Pricing](/pricing). Don't retry.                |
| `max_credits`          | The quote is above `--max-credits`. Nothing was charged. Raise the cap or choose a cheaper model. |
| `file_exists`          | `--out` already exists. Choose another path, or pass `--force` to replace it.                     |
| `job_unfinished`       | The wait ran out. Run the identical command again to keep waiting for the same job.               |
| `throttled`            | Too many requests at once. Wait `retry_after_seconds`, then run the identical command.            |

The [HTTP API errors](/docs/api/errors.md) page lists every code Rosebud returns.

## Moved the project folder?

The saved game connection is tied to the state file's path. After you move or rename the project folder, commands fail with `connection_required`. Run `rosebud connect` again.

## Lock files

The CLI locks its state file while a command runs, so run commands against one state file one at a time. If another command holds the lock, the CLI stops with `state_locked`.

A command stopped with Ctrl+C releases its lock, and a lock left by a process that has stopped is taken over automatically (CLI 0.2.0 and later). On 0.1.0, make sure the crashed command has stopped, then delete the `.lock` file next to the state file.

# Get help

URL: /docs/guides/get-help

> Report a bug, ask a question or report a security problem.

* **Bugs and questions:** open an issue on [rosebudai/rosebud-cli](https://github.com/rosebudai/rosebud-cli/issues). Include the command you ran and the JSON error, but never a claim link, approval link or credentials.
* **Security problems:** report them privately through the repository's [Security tab](https://github.com/rosebudai/rosebud-cli/security), not in a public issue.
* **Changes:** see the [changelog](/docs/cli/changelog.md).

## Source and releases

The CLI is open source under Apache-2.0. Each [npm release](https://www.npmjs.com/package/@rosebudai/cli) is built by GitHub Actions and published with npm provenance, which links it to the source it was built from.

## Coming soon

We're working on an in-game SDK for gameplay events and error reports, and dashboards for sessions and returning players. None of these are available yet, and hosting doesn't need an SDK in your game.

# CLI overview

URL: /docs/cli

> Install the Rosebud CLI, and how its output, exit codes, state and credentials work.

The Rosebud CLI publishes browser games and makes game assets. It's open source under Apache-2.0: [rosebudai/rosebud-cli](https://github.com/rosebudai/rosebud-cli).

## Install

You need Node.js 22 or later. It works on macOS, Linux and Windows.

```sh
npm install --global @rosebudai/cli
rosebud --version
```

Or run any command without installing: `npx @rosebudai/cli <command>`. `pull`, `login` and the `assets` commands need 0.2.0 or later; if one is reported as an unknown command, run the install again to update.

## Commands

| Command                                                | What it does                                                                                          |
| ------------------------------------------------------ | ----------------------------------------------------------------------------------------------------- |
| [`rosebud publish`](/docs/cli/publish.md)                 | Creates a new game from a build folder or ZIP.                                                        |
| [`rosebud connect`](/docs/cli/connect.md)                 | Prints a private link that lets you approve updates from this CLI.                                    |
| [`rosebud status`](/docs/cli/status.md)                   | Shows whether access is pending, active, revoked or expired.                                          |
| [`rosebud update`](/docs/cli/update.md)                   | Replaces the game's files and publishes them to the same link.                                        |
| [`rosebud disconnect`](/docs/cli/disconnect.md)           | Revokes this CLI's access. The game stays online.                                                     |
| [`rosebud pull`](/docs/cli/pull.md)                       | Brings the game's current files, including Rosebud edits, into a folder.                              |
| [`rosebud login`](/docs/cli/login.md)                     | Asks you to approve this CLI or agent to make assets with your credits and publish into your account. |
| [`rosebud whoami`](/docs/cli/whoami.md)                   | Shows the login's status and your credit balance.                                                     |
| [`rosebud logout`](/docs/cli/logout.md)                   | Revokes the login and removes it from this computer.                                                  |
| [`rosebud assets models`](/docs/cli/assets/models.md)     | Lists models with their inputs, prices and licenses.                                                  |
| [`rosebud assets quote`](/docs/cli/assets/quote.md)       | Checks inputs and prices an asset, free.                                                              |
| [`rosebud assets create`](/docs/cli/assets/create.md)     | Makes an asset, waits for it and saves the file.                                                      |
| [`rosebud assets status`](/docs/cli/assets/status.md)     | Shows a job's progress and, when done, its asset.                                                     |
| [`rosebud assets list`](/docs/cli/assets/list.md)         | Lists your assets, newest first.                                                                      |
| [`rosebud assets download`](/docs/cli/assets/download.md) | Saves an existing asset's file.                                                                       |

## Global options

| Option              | Default                 | Details                                                                                                                                                 |
| ------------------- | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--state <file>`    | `.rosebud/project.json` | Where the game's details are saved. Use one per game.                                                                                                   |
| `--timeout-ms <ms>` | `120000`                | How long to wait for Rosebud. For `assets create` it bounds the whole wait, default `600000`. Each file upload gets one extra second per 32 KiB on top. |
| `--help`            |                         | Lists commands and options.                                                                                                                             |
| `--version`         |                         | Prints the installed version.                                                                                                                           |

## Output

Every command except `--help` and `--version` prints one JSON object: results on stdout, errors on stderr. Many results include a `next_action` that says what to do next.

Errors look like this:

```json
{
    "error": {
        "code": "media_path",
        "message": "Move assets/Hero.PNG to assets/hero.png and update references.",
        "kind": "api",
        "outcome": "rejected",
        "status": 400,
        "filename": "assets/Hero.PNG"
    }
}
```

`outcome` is `not_sent`, `rejected` or `unknown`; with `not_sent`, nothing was released. `limit` is a number when Rosebud reports one. Asset errors include the `job_id` or `asset_id` once one is known.

A request that Rosebud throttles (HTTP 429) waits out its `Retry-After` and is sent again, for up to a minute in all. A longer wait fails with `throttled` and `retry_after_seconds`. A publish or update request is never sent again on its own.

## Exit codes

| Exit     | Meaning                                                                                             |
| -------- | --------------------------------------------------------------------------------------------------- |
| 0        | Success. Check `status` or `whoami` to see whether approval is still pending.                       |
| 2        | Local input or usage error. Fix the command or build.                                               |
| 3        | Rosebud rejected the request. Read `error.code` before retrying.                                    |
| 4        | The outcome is unknown. See [Troubleshooting](/docs/guides/troubleshooting.md#unknown-results-exit-4). |
| 130, 143 | Stopped by Ctrl+C or SIGTERM (`interrupted`). The state lock is released.                           |

## State and credentials

* `.rosebud/project.json` holds the game's ID, play link and last accepted version, but no secrets. Keep `.rosebud/` out of Git and outside your build folder.
* Credentials (game connections and the login) are kept in `~/.config/rosebud/credentials` with private file permissions. Set `ROSEBUD_CREDENTIALS_DIR` to use another folder.
* The CLI locks the state file while it runs. Run commands against one state file one at a time. A lock left by a process that no longer runs is taken over by the next command.

# rosebud publish

URL: /docs/cli/publish

> Create a new game from a build folder or ZIP and get a play link.

```sh
rosebud publish --directory <folder> [options]
rosebud publish --zip <file> [options]
```

Each `publish` creates a new game and saves its details to the state file. To change a game you already published, use [`rosebud update`](/docs/cli/update.md).

## Options

| Option                    | Details                                                                                                               |
| ------------------------- | --------------------------------------------------------------------------------------------------------------------- |
| `--directory <folder>`    | The build folder to upload. It needs `index.html` at the top level.                                                   |
| `--zip <file>`            | A ZIP of the build, instead of `--directory`.                                                                         |
| `--title <text>`          | Up to 255 characters. `--name` is accepted as an alias.                                                               |
| `--description <text>`    | Up to 4,000 characters.                                                                                               |
| `--thumbnail <file>`      | A PNG or JPEG cover, at most 2 MiB and 4096 pixels a side.                                                            |
| `--agent-client <client>` | `claude-code`, `codex`, `cursor`, `gemini-cli`, `other` or `unknown`.                                                 |
| `--context <file>`        | A JSON file with optional details about how the game was made. See [Import a game](/docs/api/hosting/import.md#context). |
| `--state <file>`          | Where to save the game's details. Default `.rosebud/project.json`.                                                    |

Use exactly one of `--directory` and `--zip`. See [what you can upload](/docs/guides/publish-a-game.md#what-you-can-upload).

## Example

```sh
rosebud publish --directory ./dist --title 'Moon Garden' \
  --description 'Collect five glowing seeds.'
```

Without a login, the result has a private claim link:

```json
{
    "project_id": "6f1d2c8e-...",
    "play_url": "https://rosebud.ai/play/moon-garden",
    "claim_url": "https://rosebud.ai/claim#...",
    "claim_expires_at": "2026-10-27T19:04:11Z",
    "content_version": "9f2c41e0b7...",
    "state_file": ".rosebud/project.json",
    "next_action": "Claim by 2026-10-27T19:04:11Z to keep this game online for free. ..."
}
```

With an active [`rosebud login`](/docs/cli/login.md), the game goes straight into the account. The result has `claimed: true`, the `owner` and an `editor_url` instead of a claim link, and `update` works at once. If Rosebud couldn't add the game to the account, the result has the claim fields instead.

## Notes

* Unclaimed games are deleted one hour after upload. See [Claim your game](/docs/guides/claim-your-game.md).
* If the result is unknown (exit 4), the game may already exist. Don't publish again right away. The same goes for an interrupted `publish`.
* A first `publish` refused with `busy` created nothing. Run it again after `retry_after_seconds`.
* A big game can take minutes, because each media file uploads on its own. Allow the time, or run the command in the background.
* If the state file already holds a game, `publish` stops with `project_exists`. Use `update`, or pass a new `--state`.
* If your login still waits for approval, `publish` stops with `login_pending`. Approve it, or run `rosebud logout` to publish with a claim link instead.

# rosebud connect

URL: /docs/cli/connect

> Ask the game's owner to approve updates from this CLI.

```sh
rosebud connect [--project <project_id>] [--agent-client <client>]
```

`connect` prints a private `approval_url`. The owner opens it, signs in and selects **Allow updates** (**Claim game and allow updates** for an unclaimed game). If the game isn't claimed yet, approving also claims it.

## Options

| Option                    | Details                                                                                                              |
| ------------------------- | -------------------------------------------------------------------------------------------------------------------- |
| `--project <project_id>`  | Connect to a claimed game, for example from another computer. Without it, `connect` uses the game in the state file. |
| `--agent-client <client>` | Which tool is asking, shown to the owner.                                                                            |
| `--state <file>`          | The game's state file. Default `.rosebud/project.json`.                                                              |

## Example

```sh
rosebud connect
```

```json
{
    "project_id": "6f1d2c8e-...",
    "status": "pending",
    "approval_url": "https://rosebud.ai/connect#...",
    "expires_at": "2026-10-27T18:34:11Z",
    "claim_expires_at": "2026-10-27T19:04:11Z"
}
```

## Notes

* The approval link expires after 30 minutes. Run `connect` again for a new one.
* If a connection is already pending or active, `connect` prints it instead of starting another.
* Approved access lasts 90 days and covers only this game. See [Sign-in and access](/docs/get-started/access.md).
* Not needed for games published with an active login.

# rosebud status

URL: /docs/cli/status

> Check whether this CLI can update the game, and which version is live.

```sh
rosebud status [--state <file>]
```

## Example

```json
{
    "project_id": "6f1d2c8e-...",
    "connection_id": "0b7a...",
    "status": "active",
    "expires_at": "2027-01-25T18:04:11Z",
    "title": "Moon Garden",
    "play_url": "https://rosebud.ai/play/moon-garden",
    "content_version": "c81d7a33f0...",
    "saved_content_version": "9f2c41e0b7..."
}
```

| Field                   | Meaning                                              |
| ----------------------- | ---------------------------------------------------- |
| `status`                | `pending`, `active`, `revoked` or `expired`.         |
| `content_version`       | The version live on Rosebud. Only shown when active. |
| `saved_content_version` | The last version this CLI published or accepted.     |
| `approval_url`          | Shown again while the connection is pending.         |

When `content_version` and `saved_content_version` differ, the game changed on Rosebud. See [Publish updates](/docs/guides/publish-updates.md#if-the-game-changed-on-rosebud).

# rosebud update

URL: /docs/cli/update

> Publish a new build of a connected game to the same link.

```sh
rosebud update --directory <folder> [options]
rosebud update --zip <file> [options]
```

`update` makes the game exactly the folder you give it: a file the game has that the folder lacks is removed from the game, and files Rosebud already has aren't uploaded again. It needs an active game connection: approve one with [`rosebud connect`](/docs/cli/connect.md), or publish with an active `rosebud login`, which saves one.

## Options

| Option                                  | Details                                                                                  |
| --------------------------------------- | ---------------------------------------------------------------------------------------- |
| `--directory <folder>` / `--zip <file>` | The complete new build. Use exactly one.                                                 |
| `--title <text>`                        | A new title. The play link stays the same.                                               |
| `--description <text>`                  | A new description. An empty value clears it.                                             |
| `--thumbnail <file>`                    | A new cover.                                                                             |
| `--expected-version <version>`          | The live version you accept replacing, from `pull` or `status`. Needed after a conflict. |
| `--state <file>`                        | The game's state file.                                                                   |

Details you don't pass stay as they are.

## Example

```sh
rosebud update --directory ./dist
```

```json
{
    "project_id": "6f1d2c8e-...",
    "play_url": "https://rosebud.ai/play/moon-garden",
    "content_version": "e4a09b12c6...",
    "operation_id": "a3c1..."
}
```

## Notes

* If the game changed on Rosebud since your last update, `update` stops with `version_conflict` and lists `changed_paths`. Run [`rosebud pull`](/docs/cli/pull.md) to bring those changes in, then update again. See [Publish updates](/docs/guides/publish-updates.md#if-the-game-changed-on-rosebud).
* After a pull that reported conflicts, `update` refuses with `pull_conflicts` (exit 2) until a pull reports none or you pass `--expected-version`. An update from a different folder than the last pull refuses with `directory_mismatch` (exit 2): pull into that folder first, or pass `--expected-version` to release it anyway.
* `update` has no force option and never merges for you.
* If an update is interrupted or its result is unknown (exit 4), run the identical command again with the folder unchanged. It reuses the same operation, sends the media the way the first attempt did, and won't publish twice. If the folder or options changed meanwhile, it refuses with `pending_operation`.
* `busy` means Rosebud changed nothing. Run the same command again after `retry_after_seconds`; you may change your files first unless an earlier update is still uncertain.
* `project_busy` means Rosebud is generating in the game. Wait for it to finish.

# rosebud pull

URL: /docs/cli/pull

> Bring a game's current files, including edits made in Rosebud, into a folder.

```sh
rosebud pull --directory <folder> [--force]
```

`pull` downloads the game's text files and media into the folder, creating it if needed. It needs an active [game connection](/docs/cli/connect.md), the game must be claimed, and the game owner's plan must include code download (Rosebud Pro or higher).

## Options

| Option                 | Details                                                                                                                                                                  |
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `--directory <folder>` | The folder you publish and update from.                                                                                                                                  |
| `--force`              | Take Rosebud's copy of every conflicted file, discarding your edits to it, and restore files missing locally. It never touches files changed or added only on your side. |
| `--state <file>`       | The game's state file.                                                                                                                                                   |

## Example

```sh
rosebud pull --directory ./dist
```

```json
{
    "project_id": "6f1d2c8e-...",
    "content_version": "e4a09b12c6...",
    "directory": "./dist",
    "status": "conflicts",
    "written": ["src/main.js"],
    "removed": [],
    "local_only": ["src/debug.js"],
    "missing_locally": [],
    "conflicts": [
        {
            "path": "src/player.js",
            "reason": "both_changed",
            "rosebud_copy": ".rosebud/project.remote/src/player.js"
        }
    ],
    "skipped": [],
    "next_action": "Merge Rosebud's copy of src/player.js into yours, then run rosebud update ..."
}
```

If your game has a build step, pull into a new, empty folder such as `./rosebud-files`, copy the changes into your source and rebuild. Then release the build with `--expected-version <content_version from the pull>`.

| Field             | Meaning                                                                                                                                                                                                         |
| ----------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `written`         | Files Rosebud changed or added, now in the folder.                                                                                                                                                              |
| `removed`         | Files Rosebud deleted, now removed from the folder.                                                                                                                                                             |
| `local_only`      | Your own new or changed files. `pull` keeps them, and the next update uploads them.                                                                                                                             |
| `missing_locally` | Files Rosebud and your last sync have but the folder lacks. The next update removes them from the game unless you restore them; `--force` restores them.                                                        |
| `conflicts`       | Files changed on both sides. Your copy stays; Rosebud's copy is saved under `rosebud_copy`.                                                                                                                     |
| `skipped`         | Names this disk can't keep, such as a Windows name ending in a dot or space or a device name like `con.js` (`unsafe_path`). The next update removes them from the game unless they're renamed in Rosebud first. |
| `status`          | `synced`, or `conflicts` while any remain.                                                                                                                                                                      |

## Conflicts

Merge each conflict into your own file, keeping both changes. Rosebud's copies go in a `.remote` folder beside the state file (`.rosebud/project.remote/` for the default state), outside your build folder, so `update` never uploads them. `pull` empties it each time, so don't edit there.

| `reason`         | Meaning                                                                                                    |
| ---------------- | ---------------------------------------------------------------------------------------------------------- |
| `both_changed`   | You and Rosebud both changed the file. Merge both changes into yours.                                      |
| `local_deleted`  | You deleted it and Rosebud changed it. Restore it from Rosebud's copy, or leave it deleted.                |
| `remote_deleted` | Rosebud deleted it and you changed it. There's no Rosebud copy: keep the file to restore it, or delete it. |

While conflicts remain, `update` refuses with `pull_conflicts`. Pull again until it reports none, or pass the version you merged against:

```sh
rosebud update --directory ./dist --expected-version <content_version from pull>
```

## Notes

* Without code download on the owner's plan, `pull` fails with `plan_required` (exit 3). `publish` and `update` still work: ask what changed in Rosebud before you update, so you don't replace those edits. Don't create a second game to get around it.
* `sync_unavailable` (exit 3) means this Rosebud server can't read files back yet, and `unsupported_project` means it can't read this game's files back. Nothing was changed.
* If a file changes while `pull` downloads, it stops with `folder_changed` (exit 2) before touching the folder. A download that doesn't match its checksum fails with `download_corrupt` (exit 4) and changes nothing. Either way, run it again.
* The last sync belongs to the folder it happened in. Pulling into another folder, or into an empty or missing one, writes all of Rosebud's files. `update` from a different folder than the last pull refuses with `directory_mismatch`. Pull into that folder first.
* `.DS_Store`, `Thumbs.db` and `desktop.ini` are skipped. `pull`'s `next_action` names other hidden files in the folder, such as `.git`, because `update` refuses them.

## Names that differ only by case or Unicode form

A name that differs from Rosebud's only by Unicode form (an accented letter stored as one character or two) is the same file on every system. One that differs only by letter case is the same file where the disk treats it so, by default on macOS and Windows. Either way your edits to it are kept.

`pull` never lets one name replace another:

* Rosebud's `foo.js` against your `Foo.js` is a `case_conflict`.
* Two Rosebud names that would land on one file or folder here (`Foo.js` and `foo.js`, `Scripts/` and `scripts/`) are each a `name_collision`, and `pull` writes neither.

`clashes_with` names the other side, Rosebud's copies go to the `.remote` folder, and `next_action` says what to rename. `--force` settles a `case_conflict` only when Rosebud renamed a file you had synced by letter case: it takes Rosebud's name and version and discards your edits to the file. It never replaces a file of your own under another case, and never settles a `name_collision`: rename first.

# rosebud disconnect

URL: /docs/cli/disconnect

> Revoke this CLI's access to the game.

```sh
rosebud disconnect [--state <file>]
```

```json
{ "project_id": "6f1d2c8e-...", "status": "revoked" }
```

The game stays online. To update it again, run [`rosebud connect`](/docs/cli/connect.md). Owners can also revoke access in the editor under **Project Settings → Manage connected agents**.

# rosebud login

URL: /docs/cli/login

> Approve this CLI or agent to make assets with your credits.

```sh
rosebud login [--agent-client <client>] [--name <label>]
```

`login` prints a private `approval_url`. Open it, sign in and select **Allow**. There's no API key to copy.

## Options

| Option                    | Details                                                                                           |
| ------------------------- | ------------------------------------------------------------------------------------------------- |
| `--agent-client <client>` | `claude-code`, `codex`, `cursor`, `gemini-cli` or `other`, so you can tell which agent is asking. |
| `--name <label>`          | A label for this login on Connected agents, up to 80 characters.                                  |

## Example

```sh
rosebud login --agent-client claude-code
```

```json
{
    "status": "pending",
    "approval_url": "https://rosebud.ai/connect/assets#...",
    "expires_at": "2026-10-27T18:34:11Z",
    "next_action": "Give the private approval_url to the person. After they sign in and approve, run rosebud whoami, then make assets."
}
```

## Notes

* The link expires after 30 minutes. Keep it out of commits, issues, shared logs and the game.
* If a login is already pending or active, `login` prints it instead of starting another. Run [`rosebud logout`](/docs/cli/logout.md) first to switch accounts.
* An approved login can make and download assets and publish new games into the account. It can't change billing or manage the account.
* It expires after 90 days without use, and ends when you disconnect it in Rosebud or run `rosebud logout`. [`rosebud whoami`](/docs/cli/whoami.md) shows its `scopes` and `expires_at`.
* After `key_expired`, run `rosebud login` again. After `insufficient_scope`, which names the `required_scope`, run `rosebud logout`, then `rosebud login`. For `assets create`, the error's `next_action` says to rerun the identical command once the new login is approved.

# rosebud whoami

URL: /docs/cli/whoami

> Show whether the login is active, and your credit balance.

```sh
rosebud whoami
```

```json
{
    "login_id": "2d9e...",
    "status": "active",
    "client": "claude-code",
    "name": "Claude Code",
    "scopes": ["assets:read", "assets:write", "games:write"],
    "expires_at": "2027-01-25T18:04:11Z",
    "account": { "display_name": "Sam", "balance": 12400 }
}
```

| `status`  | Meaning                                                               |
| --------- | --------------------------------------------------------------------- |
| `pending` | Waiting for approval. The `approval_url` is shown again.              |
| `active`  | Ready to make assets.                                                 |
| `expired` | Not approved in time, or unused for 90 days. Run `rosebud login`.     |
| `revoked` | Disconnected on Connected agents or by `logout`. Run `rosebud login`. |

`balance` is a number, or `"unlimited"` on plans without a credit limit. With no login on this computer, `whoami` fails with `login_required` (exit 2).

`expires_at` is the approval deadline while pending, then 90 days after the login's last use. A command that fails with `key_expired` needs `rosebud login` again; one that fails with `insufficient_scope` needs `rosebud logout`, then `rosebud login`.

# rosebud logout

URL: /docs/cli/logout

> Revoke the login and remove it from this computer.

```sh
rosebud logout
```

```json
{ "status": "revoked" }
```

This cancels a pending login or revokes an approved one. Game connections aren't affected, whether from [`rosebud connect`](/docs/cli/connect.md) or saved when the login published a game: each lasts until its own 90 days run out or [`rosebud disconnect`](/docs/cli/disconnect.md) revokes it.

Assets and publishing into the account need the login, so agents should keep it while they work and log out only to switch accounts or when asked. You can also disconnect logins on [Connected agents](/developers/keys).

# rosebud assets models

URL: /docs/cli/assets/models

> List the asset models, with their inputs, prices and licenses.

```sh
rosebud assets models [--category <category>]
```

No login needed. `--category` takes `image`, `skybox`, `model_3d`, `video`, `sound_effect`, `music` or `speech`; leave it out to see every model.

```json
{
    "models": [
        {
            "id": "flux-2-flash",
            "name": "Flux 2 Flash",
            "category": "image",
            "summary": "Fast, low-cost 2D game art: sprites, icons, UI pieces, backgrounds and textures.",
            "price": { "credits": 250, "add_ons": [{ "id": "transparent_background", "credits": 50 }] },
            "inputs": [
                { "name": "prompt", "type": "string", "required": true, "max_length": 1000 },
                { "name": "asset_type", "type": "enum", "required": false, "default": "any" }
            ],
            "output_formats": ["png", "webp"],
            "typical_seconds": 5
        }
    ]
}
```

An input of type `file` takes an asset ID from [`assets list`](/docs/cli/assets/list.md) or an `https` URL, such as `--input image=<asset_id>`. Video and speech prices depend on length, so quote the exact request.

Every model and input is listed on [Models](/docs/models.md).

# rosebud assets quote

URL: /docs/cli/assets/quote

> Check an asset's inputs and price without paying.

```sh
rosebud assets quote --model <id> --prompt <text> [--input name=value ...] [--input-json <file>]
```

## Options

| Option                | Details                                                      |
| --------------------- | ------------------------------------------------------------ |
| `--model <id>`        | A model ID from [`assets models`](/docs/cli/assets/models.md).  |
| `--prompt <text>`     | Fills the model's `prompt` input.                            |
| `--input name=value`  | Sets any other input the model lists. Repeat it for several. |
| `--input-json <file>` | All inputs as one JSON object.                               |

## Example

```sh
rosebud assets quote --model flux-2-flash --prompt 'green slime monster, side view' \
  --input asset_type=sprite
```

```json
{
    "id": "7c0e...",
    "model": "flux-2-flash",
    "input": { "prompt": "green slime monster, side view", "asset_type": "sprite", "seed": 18342 },
    "credits": 300,
    "balance": 12400,
    "payment_required": false,
    "expires_at": "2026-10-27T18:09:11Z"
}
```

Quotes are free. `credits` includes add-ons, such as the transparent background for sprites. A quote shows a sample `seed`; `create` picks its own unless you pass one.

# rosebud assets create

URL: /docs/cli/assets/create

> Make an asset with your credits, wait for it and save the file.

```sh
rosebud assets create --model <id> --prompt <text> [--max-credits <n>] [--out <file>] [options]
```

`create` quotes the asset, refuses a quote above `--max-credits`, starts the job, waits for it and saves the file.

## Options

| Option                | Details                                                                                                           |
| --------------------- | ----------------------------------------------------------------------------------------------------------------- |
| `--model <id>`        | A model ID from [`assets models`](/docs/cli/assets/models.md).                                                       |
| `--prompt <text>`     | Fills the model's `prompt` input.                                                                                 |
| `--input name=value`  | Sets any other input the model lists. Repeat it for several.                                                      |
| `--input-json <file>` | All inputs as one JSON object.                                                                                    |
| `--max-credits <n>`   | The most you'll pay. A higher quote stops with `max_credits` (exit 2) before anything is charged.                 |
| `--out <file>`        | Where to save the file.                                                                                           |
| `--force`             | Replace `--out` if it exists.                                                                                     |
| `--no-wait`           | Return the job at once. Check it with [`assets status`](/docs/cli/assets/status.md). Can't be combined with `--out`. |
| `--timeout-ms <ms>`   | How long to wait for the job. Default `600000` (10 minutes).                                                      |

## Example

```sh
rosebud assets create --model flux-2-flash --prompt 'green slime monster, side view' \
  --input asset_type=sprite \
  --max-credits 300 --out ./assets/slime.png
```

```json
{
    "id": "41b8...",
    "status": "succeeded",
    "model": "flux-2-flash",
    "credits": 300,
    "charged_credits": 300,
    "refunded_credits": 0,
    "asset": { "id": "e2f0...", "name": "green slime monster", "category": "image", "format": "png", "url": "..." },
    "error": null,
    "file": "/home/sam/moon-garden/assets/slime.png"
}
```

`file` is the absolute path of the saved file.

## Retries and billing

* Credits are charged when the job starts and returned if generation fails. A failed job exits 3 with the reason.
* After an unknown result (exit 4), including a wait that ran out, run the identical command again. It resumes the same job instead of paying again. The result then has `resumed: true`.
* Once a create has finished, the same command makes a new asset.
* Identical creates run one at a time (`state_locked`). To make variations in parallel, change the prompt or inputs.
* While `create` waits for a job, throttled and `busy` answers are waited out.
* After `key_expired` or `insufficient_scope`, approve a new login (see [`rosebud login`](/docs/cli/login.md)), then rerun the identical command.

# rosebud assets status

URL: /docs/cli/assets/status

> Check a job's progress and, when it's done, its asset.

```sh
rosebud assets status <job_id>
```

`status` is `queued`, `running`, `succeeded`, `failed`, `canceled` or `timed_out`. When it's `succeeded`, `asset` has the result; save it with [`assets download`](/docs/cli/assets/download.md).

```json
{
    "id": "41b8...",
    "status": "running",
    "model": "rosie-3d",
    "credits": 1000,
    "charged_credits": 1000,
    "refunded_credits": 0,
    "asset": null,
    "error": null,
    "created_at": "2026-10-27T18:04:11Z",
    "deadline_at": "2026-10-27T18:14:11Z"
}
```

# rosebud assets list

URL: /docs/cli/assets/list

> Search your assets, newest first.

```sh
rosebud assets list [--query <text>] [--category <category>]
```

| Option                  | Details                                                     |
| ----------------------- | ----------------------------------------------------------- |
| `--query <text>`        | Search names, prompts and captions.                         |
| `--category <category>` | `image`, `sprite`, `skybox`, `model_3d`, `audio` or `file`. |

```json
{
    "count": 42,
    "next": "https://api.rosebud.ai/api/v1/assets/?page=2&q=stone",
    "previous": null,
    "results": [
        {
            "id": "e2f0...",
            "name": "mossy stone tile",
            "category": "image",
            "format": "png",
            "url": "...",
            "created_at": "2026-10-27T18:04:20Z"
        }
    ]
}
```

`sprite` means animated sprite sheets made on the website; images made with `asset_type=sprite` are `image`. `audio` covers sound effects, music and speech. Videos are `file`.

It shows the 25 newest matches, with no paging. Narrow it with `--query` or `--category`. Results include assets made on the website and in games, not only from the CLI.

# rosebud assets download

URL: /docs/cli/assets/download

> Save an existing asset's file into the project.

```sh
rosebud assets download <asset_id> --out <file> [--force]
```

`download` never replaces an existing file unless you pass `--force`. The result is the asset with the saved `file` path added.

```sh
rosebud assets download <asset_id> --out ./assets/slime.png
```

# Changelog

URL: /docs/cli/changelog

> Changes in each release of @rosebudai/cli, newest first.

## 0.2.0

October 29, 2026. Highlights; the [full list](https://github.com/rosebudai/rosebud-cli/blob/main/CHANGELOG.md#020) has every detail.

* **Agent login:** `rosebud login` asks you to approve a private link, with no API key to copy. `whoami` shows its status, scopes and your credit balance; `logout` revokes it. Logins expire after 90 days without use.
* **Assets:** `rosebud assets models`, `quote`, `create`, `status`, `list` and `download` make and reuse assets with your credits. `create` refuses quotes above `--max-credits` and resumes the same job when rerun.
* **Publish into your account:** with an active login, `publish` puts the game in your account and saves the update connection: no claim link and no `connect`.
* **Pull:** `rosebud pull` brings a game's current files, including edits made in Rosebud, into a folder, keeping your edits and listing conflicts. `update` then refuses with `pull_conflicts` until they're merged.
* **Bigger games:** media uploads file by file. Limits are 19 MiB per file, and 2,000 files and 1 GiB per game. Files Rosebud already has aren't uploaded again.
* **More file names:** text files can have any name the Rosebud editor allows, such as Markdown notes. OS junk (`.DS_Store`, `Thumbs.db`, `desktop.ini`) is skipped instead of refused.
* **Clearer conflicts and retries:** update conflicts list `changed_paths`; a busy Rosebud (`busy`) is reported with `retry_after_seconds`; throttled requests wait and retry for up to a minute, but a publish or update is never resent on its own.
* **Safer interrupts:** Ctrl+C or SIGTERM releases the state lock and exits 130 or 143 (`interrupted`), and a lock left by a stopped process is taken over.

## 0.1.0

First public release.

* Publish a browser-ready build folder or ZIP with `rosebud publish` to get a play link and a private claim link. Unclaimed games are deleted after one hour.
* Approve updates once with `rosebud connect`, then ship new builds to the same link with `rosebud update`.
* Upload HTML, JavaScript, CSS, JSON, text notices, images, audio, fonts, WebAssembly and 3D models (GLB/glTF), up to 10 MiB zipped.
* Works on macOS, Linux and Windows with Node.js 22 or later.

# HTTP API overview

URL: /docs/api

> Base URL, authentication and conventions for the endpoints the Rosebud CLI calls.

> **The CLI is the supported client**
>
> These endpoints may still change. Use the [CLI](/docs/cli.md) unless you need your own client.

## Base URL

```text
https://api.rosebud.ai
```

`api.rosebud.ai` serves only the endpoints on these pages. Every other path returns HTTP 404. HTTPS is required for credentials outside local development.

## Authentication

| Credential                       | Comes from                                                    | Send it as                            | Used by                                                                         |
| -------------------------------- | ------------------------------------------------------------- | ------------------------------------- | ------------------------------------------------------------------------------- |
| None                             |                                                               |                                       | Importing a game anonymously, listing models, starting a login.                 |
| Connection token (`agent_token`) | [`POST .../connect/`](/docs/api/hosting/connect.md)              | `Authorization: Bearer <agent_token>` | One game's connection, status, files, upload sessions and releases.             |
| Login token (`rbk_...`)          | [`POST /api/v1/agent-logins/`](/docs/api/assets/agent-logins.md) | `Authorization: Bearer rbk_...`       | Quotes, jobs, assets, and importing into the account (with its upload session). |

Neither token is a Rosebud account session. Each one only works after the person approves its link. No endpoint accepts credentials in URL query strings.

## Conventions

* Request and response bodies are JSON, except uploads, which are `multipart/form-data`.
* Times are ISO 8601 in UTC.
* Connection, mutation and asset responses are sent with `Cache-Control: no-store`.
* Lists are paginated 25 at a time with `count`, `next`, `previous` and `results`. Follow `next` until it's null.
* Paid and write requests are rate limited per account: quotes and job starts share a limit of 30 per minute. A throttled request returns HTTP 429 with `Retry-After`; wait that long and send it again.
* When Rosebud is too busy to start a request, it returns HTTP 503 `busy` with `Retry-After` and changes nothing. Send the same request again after that many seconds.

## Endpoints

| Method          | Path                                               | Page                                                         |
| --------------- | -------------------------------------------------- | ------------------------------------------------------------ |
| `POST`          | `/api/developer/projects/import/`                  | [Import a game](/docs/api/hosting/import.md)                    |
| `POST`          | `/api/developer/uploads/`                          | [Upload media in a session](/docs/api/hosting/uploads.md)       |
| `POST`          | `/api/developer/projects/{project_id}/connect/`    | [Request a connection](/docs/api/hosting/connect.md)            |
| `GET`, `DELETE` | `/api/developer/projects/{project_id}/connection/` | [Check or revoke a connection](/docs/api/hosting/connection.md) |
| `GET`           | `/api/developer/projects/{project_id}/files/`      | [Read a game's files](/docs/api/hosting/files.md)               |
| `POST`          | `/api/developer/projects/{project_id}/releases/`   | [Publish a release](/docs/api/hosting/releases.md)              |
| `POST`          | `/api/v1/agent-logins/`                            | [Agent logins](/docs/api/assets/agent-logins.md)                |
| `GET`, `DELETE` | `/api/v1/agent-logins/current/`                    | [Agent logins](/docs/api/assets/agent-logins.md)                |
| `GET`           | `/api/v1/asset-models/`                            | [Models](/docs/api/assets/models.md)                            |
| `POST`          | `/api/v1/asset-quotes/`                            | [Quotes](/docs/api/assets/quotes.md)                            |
| `POST`, `GET`   | `/api/v1/asset-jobs/`                              | [Jobs](/docs/api/assets/jobs.md)                                |
| `GET`           | `/api/v1/assets/`                                  | [Assets](/docs/api/assets/assets.md)                            |

# Errors

URL: /docs/api/errors

> Error shapes and codes for the hosting and asset endpoints.

## Error shapes

Hosting endpoints (`/api/developer/...`) return:

```json
{
    "error": {
        "code": "media_path",
        "message": "Move assets/Hero.PNG to assets/hero.png.",
        "filename": "assets/Hero.PNG"
    }
}
```

`filename`, `limit`, `remaining`, `changed_paths` and `required_scope` are included when they apply. `limit` and `remaining` are numbers, and `changed_paths` is a list or `null`. Request validation failures use DRF field errors.

Asset endpoints (`/api/v1/...`) return:

```json
{
    "detail": "prompt: This field is required.",
    "code": "invalid",
    "fields": { "prompt": ["This field is required."] }
}
```

`fields` appears only for validation errors.

## Hosting codes

| Code                                                                                                                     | What to do                                                                                                                |
| ------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------- |
| `missing_index`, `unsafe_path`, `excluded_file`, `unsupported_file`, `invalid_media`, `invalid_text`                     | Fix the bundle. Keep browser-ready files and safe relative paths.                                                         |
| `media_path`, `noncanonical_path`                                                                                        | Move media under `assets/` and rename it to the lowercase path in the message, updating references.                       |
| `duplicate_path`                                                                                                         | Two paths are the same name in Unicode NFC, or a path is both in the ZIP and in the upload session. Keep one.             |
| `compressed_limit`, `expanded_limit`, `entry_limit`, `file_limit`, `release_upload_limit`                                | Reduce the size or count. `limit` gives the bound.                                                                        |
| `thumbnail_limit`, `invalid_thumbnail`                                                                                   | Send a valid PNG or JPEG cover within the limits.                                                                         |
| `game_expired`                                                                                                           | The claim deadline passed. Upload the build as a new game.                                                                |
| `claim_required`, `invalid_claim`, `used_claim`                                                                          | Use the original private claim link, or the owner's account.                                                              |
| `invalid_connection` (401)                                                                                               | The token is wrong, revoked or expired, or belongs to another game. Ask for a new connection.                             |
| `connection_pending` (403)                                                                                               | The owner hasn't approved the connection yet.                                                                             |
| `connection_expired`, `connection_revoked` (403)                                                                         | Ask for a new connection.                                                                                                 |
| `login_pending` (403), `login_inactive` (401)                                                                            | Publishing with a login token that isn't approved yet, or was revoked. Have the person approve it, or import anonymously. |
| `key_expired` (401), `insufficient_scope` (403)                                                                          | The login token expired or lacks `required_scope`. Start a new login. See [Agent logins](/docs/api/assets/agent-logins.md).  |
| `owner_required`                                                                                                         | Sign in as the game's current owner.                                                                                      |
| `plan_required` (403)                                                                                                    | The owner's plan doesn't include code download. Releases still work; ask what changed before you release.                 |
| `project_unavailable` (404)                                                                                              | The game doesn't exist or was deleted.                                                                                    |
| `unsupported_project` (409)                                                                                              | Rosebud can't read this game's files back.                                                                                |
| `version_conflict`                                                                                                       | Reconcile local and remote changes, then send the current version. `changed_paths` lists what changed.                    |
| `operation_reused`                                                                                                       | Retry the original input, or use a new operation ID after reconciling.                                                    |
| `project_busy`                                                                                                           | Wait for Rosebud generation in the game to finish.                                                                        |
| `busy` (503)                                                                                                             | Nothing changed. Wait `Retry-After` seconds, then send the same request.                                                  |
| `sync_unavailable` (503)                                                                                                 | This server has no file-by-file uploads or file reading. Nothing changed. Send media inside the ZIP.                      |
| `upload_retry` (409)                                                                                                     | Rosebud is still checking the game's files. Repeat the identical request while `remaining` keeps falling.                 |
| `invalid_upload`, `upload_expired`, `upload_mismatch`, `upload_missing`, `upload_corrupt`, `upload_stale`, `invalid_md5` | See [Upload media in a session](/docs/api/hosting/uploads.md#errors).                                                        |
| `update_failed`                                                                                                          | Retry the same operation and payload.                                                                                     |

## Asset codes

| Code                                                   | Status | What to do                                                                                                                                                                                                 |
| ------------------------------------------------------ | ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `invalid`, `invalid_input`                             | 400    | Fix the request. `detail` names the field.                                                                                                                                                                 |
| `missing_idempotency_key`, `invalid_idempotency_key`   | 400    | Send an `Idempotency-Key` of 1–128 letters, digits, `.`, `_`, `:` or `-`.                                                                                                                                  |
| `invalid_key`                                          | 401    | The login token is wrong, not approved yet, or was disconnected. Check it with [`GET /api/v1/agent-logins/current/`](/docs/api/assets/agent-logins.md), then have the person approve it or start a new login. |
| `key_expired`                                          | 401    | The login wasn't used for 90 days. Start a new login.                                                                                                                                                      |
| `insufficient_scope`                                   | 403    | The login lacks `required_scope`. Start a new login.                                                                                                                                                       |
| `key_not_allowed`                                      | 403    | This endpoint needs a signed-in browser session, not a login token.                                                                                                                                        |
| `insufficient_credits`                                 | 402    | The person needs more credits. Don't retry.                                                                                                                                                                |
| `unknown_model`, `not_found`                           | 404    | Use a model ID from `GET /api/v1/asset-models/`, or a job or asset in this account.                                                                                                                        |
| `quote_expired`                                        | 409    | Quotes last 10 minutes. Get a new quote.                                                                                                                                                                   |
| `idempotency_conflict`                                 | 409    | The key was used for a different quote. Use a new key.                                                                                                                                                     |
| `not_cancelable`                                       | 409    | The job already started. Wait for it instead.                                                                                                                                                              |
| `invalid_scope`                                        | 400    | A login asked for a scope it can't have. Ask for `assets:read`, `assets:write` or `games:write`.                                                                                                           |
| `key_limit`, `login_already_approved`, `login_revoked` | 409    | Start a new login.                                                                                                                                                                                         |
| `login_expired`                                        | 410    | The approval link expired. Start a new login.                                                                                                                                                              |
| `throttled`                                            | 429    | Wait `Retry-After` seconds, then send the same request.                                                                                                                                                    |
| `unavailable`                                          | 503    | Wait and send the same request again.                                                                                                                                                                      |

# Import a game

URL: /docs/api/hosting/import

> POST /api/developer/projects/import/ — upload a build and get a play link.

```http
POST /api/developer/projects/import/
Content-Type: multipart/form-data
```

Anonymous by default. Send a login token (`Authorization: Bearer rbk_...`) with the `games:write` scope to publish straight into the person's account. A login that isn't approved yet returns `login_pending` (403); one that was revoked or expired returns `login_inactive` (401).

## Fields

| Field                       | Details                                                                                                                                                                                                |
| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `bundle`                    | Required. One browser-ready ZIP with `index.html` at its root. 10 MiB compressed, 50 MiB expanded, 500 entries including folders. Holds the text files, and the media too unless a session carries it. |
| `upload_id`, `upload_token` | Optional, sent together: the media of a new-game [upload session](/docs/api/hosting/uploads.md).                                                                                                          |
| `title`                     | 1–255 characters. `name` is accepted as an alias if it matches.                                                                                                                                        |
| `description`               | Plain text, up to 4,000 characters.                                                                                                                                                                    |
| `thumbnail`                 | A separate PNG or JPEG, at most 2 MiB and 4096 pixels a side. Re-encoded to strip metadata.                                                                                                            |
| `context`                   | A JSON string with the fields below. Private to Rosebud.                                                                                                                                               |

Without a title the game is called “Uploaded game”.

### Context

All optional. Keep prompts, conversations, personal details, local paths and environment variables out of it.

| Field              | Values                                                                                              |
| ------------------ | --------------------------------------------------------------------------------------------------- |
| `agent_client`     | `codex`, `claude-code`, `gemini-cli`, `cursor`, `other`, `unknown`                                  |
| `agent_version`    | At most 80 characters                                                                               |
| `model_provider`   | `openai`, `anthropic`, `google`, `other`, `unknown`                                                 |
| `model`            | At most 100 characters                                                                              |
| `use_case`         | `learning`, `game-jam`, `prototype`, `portfolio`, `classroom`, `client-work`, `commercial`, `other` |
| `framework`        | `vanilla`, `phaser`, `three`, `other`, `unknown`                                                    |
| `discovery_source` | `docs`, `search`, `github`, `recommendation`, `existing-user`, `other`, `unknown`                   |

## Response

HTTP 201, anonymous:

```json
{
    "project_id": "6f1d2c8e-...",
    "play_url": "https://rosebud.ai/play/moon-garden",
    "claim_url": "https://rosebud.ai/claim#<secret>",
    "claim_expires_at": "2026-10-27T19:04:11Z",
    "content_version": "9f2c41e0b7..."
}
```

HTTP 201, with a login token:

```json
{
    "project_id": "6f1d2c8e-...",
    "play_url": "https://rosebud.ai/play/moon-garden",
    "editor_url": "https://rosebud.ai/edit/6f1d2c8e-...",
    "content_version": "9f2c41e0b7...",
    "claimed": true,
    "owner": "sam",
    "agent_token": "<agent_token>",
    "connection_expires_at": "2027-01-25T18:04:11Z"
}
```

The `claim_url` and `agent_token` are private. The `agent_token` is the game's update connection, already approved; use it with [releases](/docs/api/hosting/releases.md). If Rosebud publishes the game but can't add it to the account, the response falls back to the anonymous shape, so the person can still claim it.

A login token also answers `key_expired` (401), `insufficient_scope` (403, with `required_scope`) and `invalid_key` (401). See [Agent logins](/docs/api/assets/agent-logins.md#errors-on-the-publishing-endpoints).

## Expiry

Unclaimed games expire one hour after import. At `claim_expires_at` the game, code and asset URLs return HTTP 410 `game_expired`; cleanup then permanently deletes them and they return HTTP 404. There's no late claim.

Every import creates a new game. Retrying after a lost response can create a second one.

# Upload media in a session

URL: /docs/api/hosting/uploads

> POST /api/developer/uploads/ — declare a game's media, upload each file, then import or release with the session.

A game's media doesn't have to travel inside the ZIP. Declare it in an upload session, `PUT` each file to storage, then [import](/docs/api/hosting/import.md) or [release](/docs/api/hosting/releases.md) with the session. This is how a game gets past the 10 MiB ZIP limit.

```http
POST /api/developer/uploads/
Content-Type: application/json
```

```json
{
    "project_id": "6f1d2c8e-...",
    "files": [
        { "path": "assets/hero.png", "size": 48213, "md5": "0b4e7a0e5fe84ad35fb5f95b9ceeac79" },
        { "path": "assets/boom.wav", "size": 5, "md5": "5d41402abc4b2a76b9719d911017c592" }
    ]
}
```

| Field        | Details                                                                                                                                                                                                 |
| ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `files`      | Required, may be empty, at most 2,000 entries. Each `path` is a media path under `assets/` in canonical form, `size` is the byte length, and `md5` is 32 lowercase hex digits.                          |
| `project_id` | Optional. Send it with `Authorization: Bearer <agent_token>` for an update session. Leave it out for a new game: with a login token (`games:write`) the session is that account's, otherwise anonymous. |

Anonymous sessions are rate limited: over the limit the answer is HTTP 429 with `Retry-After`.

## Response

HTTP 201:

```json
{
    "upload_id": "9a4b2f0e-...",
    "upload_token": "<upload_token>",
    "expires_at": "2026-10-28T18:30:00Z",
    "linked": ["assets/hero.png"],
    "uploads": [
        {
            "path": "assets/boom.wav",
            "url": "<signed upload URL>",
            "method": "PUT",
            "headers": {
                "Content-Type": "audio/wav",
                "Content-MD5": "XUFAKrxLKna5cZ2REBfFkg==",
                "x-goog-content-length-range": "5,5"
            }
        }
    ]
}
```

* `linked` lists declared paths Rosebud already holds, with the same MD5 and size. They aren't uploaded again. An update session links the owner's files and the files the game already serves at the same path; a login session links the account's files; an anonymous session links nothing this way.
* A linked path skips the media type and folder rules but must still be a safe, canonical name. Editor-only media such as an MP4 can only be kept this way, unchanged at the same path.
* `uploads` has one entry per path that isn't linked. `PUT` the file's bytes to `url` with exactly the returned `headers`, all of them. Storage rejects bytes whose MD5 or length differs from the declaration.
* `upload_token` is shown once. Keep it private.
* Each signed URL works for one hour, and the session for 24 hours (`expires_at`).

While Rosebud is still checking files the game already serves, it can answer `409 upload_retry` with a `remaining` count and `Retry-After: 1`. Repeat the identical request: `remaining` falls until the session is created. Stop if it stops falling.

## Use the session

Send `upload_id` and `upload_token` as two more multipart fields, both or neither, with an import or a release.

* A release is a full snapshot: the game becomes the ZIP's files plus every path the session declared, linked or uploaded. Anything else is removed, so declare all of the game's media, not only the changes.
* A path in both the ZIP and the session is `duplicate_path`. The ZIP and the session count together toward the file-count and total-size limits.
* New (not linked) media in one release is at most 128 MiB (`413 release_upload_limit`, with the exact `limit`). Publish part of it, then release the rest; later sessions declare the earlier media again and link it.
* An update session releases only its game. A new-game session can't update a game, and is spent by the import that succeeds with it. A login session works only for that login's account.
* Retries use the release's `operation_id`. After the session expires, create a new one that declares the same paths and MD5s and retry with the same `operation_id`; its files needn't be uploaded.

## Errors

| Code                   | Status | When                                                                                               |
| ---------------------- | ------ | -------------------------------------------------------------------------------------------------- |
| `upload_retry`         | 409    | Rosebud is still checking the game's existing files. Repeat the identical request.                 |
| `invalid_upload`       | 404    | No session has this `upload_id` with this token.                                                   |
| `upload_expired`       | 410    | The session expired, or a new-game session was already used.                                       |
| `upload_mismatch`      | 403    | The session was made for another game, another account, or the other of import and update.         |
| `upload_missing`       | 400    | A declared file was never uploaded. `filename` is the first missing path.                          |
| `upload_corrupt`       | 400    | The stored bytes differ from the declared size or MD5.                                             |
| `upload_stale`         | 409    | A linked file is no longer available. Create a new session.                                        |
| `release_upload_limit` | 413    | New media exceeds 128 MiB. `limit` is the exact number of bytes.                                   |
| `invalid_md5`          | 400    | `md5` isn't 32 lowercase hex digits.                                                               |
| `duplicate_path`       | 400    | A path was declared twice, or is in both the ZIP and the session.                                  |
| `busy`                 | 503    | No room for the release's new media right now. Nothing changed; send it again after `Retry-After`. |
| `sync_unavailable`     | 503    | This server has no file-by-file uploads. Nothing changed.                                          |

The endpoint also answers the connection, login, limit and path errors on [Errors](/docs/api/errors.md). A failed release changes nothing.

# Request a connection

URL: /docs/api/hosting/connect

> POST /api/developer/projects/{project_id}/connect/ — ask the owner to approve updates.

```http
POST /api/developer/projects/{project_id}/connect/
Content-Type: application/json
```

```json
{ "claim_secret": "<fragment of the claim_url>", "client": "codex" }
```

| Field          | Details                                                                                                                        |
| -------------- | ------------------------------------------------------------------------------------------------------------------------------ |
| `claim_secret` | Required for an unclaimed game: the part of its `claim_url` after `#`. Omit it for a claimed game; only its owner can approve. |
| `client`       | Which tool is asking, shown to the owner.                                                                                      |

The project ID alone never grants access.

## Response

HTTP 201:

```json
{
    "project_id": "6f1d2c8e-...",
    "connection_id": "0b7a...",
    "agent_token": "<agent_token>",
    "approval_url": "https://rosebud.ai/connect#<secret>",
    "status": "pending",
    "expires_at": "2026-10-27T18:34:11Z"
}
```

Store `agent_token` securely and show only `approval_url` to the person. They're different secrets.

The person opens the link, signs in, reviews the game and client, and approves. Visiting the link alone never approves. Pending requests expire in 30 minutes; approved access lasts 90 days. Approving an unclaimed game also claims it.

# Check or revoke a connection

URL: /docs/api/hosting/connection

> GET and DELETE /api/developer/projects/{project_id}/connection/

Both use `Authorization: Bearer <agent_token>`.

## Check

```http
GET /api/developer/projects/{project_id}/connection/
```

```json
{
    "project_id": "6f1d2c8e-...",
    "connection_id": "0b7a...",
    "status": "active",
    "expires_at": "2027-01-25T18:04:11Z",
    "title": "Moon Garden",
    "play_url": "https://rosebud.ai/play/moon-garden",
    "content_version": "c81d7a33f0..."
}
```

`status` is `pending`, `active`, `revoked` or `expired`. `title`, `play_url` and `content_version` are included only when active. This check records nothing about the game's files, so a conflict against a version learned only here reports `changed_paths: null`.

## Revoke

```http
DELETE /api/developer/projects/{project_id}/connection/
```

Revokes this token and returns HTTP 204 with no body. The game stays online.

# Read a game's files

URL: /docs/api/hosting/files

> GET /api/developer/projects/{project_id}/files/ — the game's current text files and media, including edits made in Rosebud.

```http
GET /api/developer/projects/{project_id}/files/
Authorization: Bearer <agent_token>
```

Returns the editor's latest version of the game, including edits Rosie or the owner made in the browser, not the published copy.

## Response

HTTP 200:

```json
{
    "project_id": "6f1d2c8e-...",
    "content_version": "c81d7a33f0...",
    "files": [{ "path": "index.html", "content": "<h1>Edited in Rosie</h1>" }],
    "media": [
        {
            "path": "assets/fox.png",
            "url": "<file URL>",
            "size": 3,
            "md5": "dddddddddddddddddddddddddddddddd",
            "media_file_id": "6f1e1a0c-..."
        }
    ]
}
```

* `files` are text files with their full content, sorted by folder, then name. `media` are the game's media files; fetch each from `url`. `size` and `md5` are null for a media file with no recorded metadata.
* Compare `md5` and `size` with a local file to skip a download, and declare the same `md5` in an [upload session](/docs/api/hosting/uploads.md) so Rosebud links the file instead of asking for it again.
* `content_version` is what to send as `expected_version` on the next release. Reading also records the game's paths at that version, so a later [conflict](/docs/api/hosting/releases.md#retries-and-conflicts) can say what changed.
* Reading files back is code download, so the game's owner needs Rosebud Pro or higher. Publishing and releases work on every plan. An unclaimed game has no plan, so approve the connection first.

## Errors

| Code                                                             | Status | When                                                                     |
| ---------------------------------------------------------------- | ------ | ------------------------------------------------------------------------ |
| `plan_required`                                                  | 403    | The owner's plan lacks code download. The message links Rosebud's plans. |
| `invalid_connection`                                             | 401    | Missing, malformed or unknown agent token for this game.                 |
| `connection_pending`, `connection_expired`, `connection_revoked` | 403    | The connection isn't active.                                             |
| `project_unavailable`                                            | 404    | The game doesn't exist or was deleted.                                   |
| `game_expired`                                                   | 410    | The unclaimed game passed its one-hour deadline.                         |
| `unsupported_project`                                            | 409    | Rosebud can't read this game's files back.                               |
| `sync_unavailable`                                               | 503    | This server can't read files back.                                       |

# Publish a release

URL: /docs/api/hosting/releases

> POST /api/developer/projects/{project_id}/releases/ — replace a connected game's files.

```http
POST /api/developer/projects/{project_id}/releases/
Authorization: Bearer <agent_token>
Content-Type: multipart/form-data
```

## Fields

| Field                                        | Details                                                                                                    |
| -------------------------------------------- | ---------------------------------------------------------------------------------------------------------- |
| `bundle`                                     | Required. The complete replacement ZIP, checked like an import.                                            |
| `upload_id`, `upload_token`                  | Optional, together: an update session's media. See [Upload media in a session](/docs/api/hosting/uploads.md). |
| `expected_version`                           | Required. The last `content_version` the caller accepted.                                                  |
| `operation_id`                               | Required. A UUID saved before the request and reused for a retry.                                          |
| `title` / `name`, `description`, `thumbnail` | Optional. Omitted fields keep their values; an empty description clears it.                                |

## Response

HTTP 200:

```json
{
    "project_id": "6f1d2c8e-...",
    "play_url": "https://rosebud.ai/play/moon-garden",
    "content_version": "e4a09b12c6...",
    "operation_id": "a3c1..."
}
```

The project ID and play link stay the same even when the title changes. A release is a full snapshot: files the game had that aren't in it are removed. The current and published revisions commit together; a failure leaves the earlier game playable.

## Retries and conflicts

* A retry with the same `operation_id` and the same input returns the recorded result without another release. Reusing it with different input returns `operation_reused`.
* Editor changes on Rosebud change `content_version`. A stale `expected_version` returns `409 version_conflict`, and `changed_paths` says what changed. [Read the files back](/docs/api/hosting/files.md), merge locally, and send a new operation with the new `content_version`. A conflict is never merged for you.

| `changed_paths`       | Meaning                                                                            |
| --------------------- | ---------------------------------------------------------------------------------- |
| `["index.html", ...]` | Exactly these paths differ. Files not listed are as the caller last saw them.      |
| `[]`                  | No file changed. Only the title, description, thumbnail or published copy changed. |
| `null`                | Unknown. Rosebud has no record of `expected_version`, so reconcile everything.     |

Rosebud records a game's paths when it's imported, when a release commits and when its files are read back. A version learned only from [`GET .../connection/`](/docs/api/hosting/connection.md) has no record, so a conflict against it reports `null`.

* `project_busy` means Rosebud generation is running in the game.

No generative-model calls run on import, claim, approval or release.

# Agent logins

URL: /docs/api/assets/agent-logins

> Start a login, check it and end it. The login token pays for assets with the person's credits.

## Start a login

```http
POST /api/v1/agent-logins/
Content-Type: application/json
```

```json
{ "client": "claude-code", "name": "Claude Code" }
```

| Field    | Details                                                                                                |
| -------- | ------------------------------------------------------------------------------------------------------ |
| `client` | `claude-code`, `codex`, `cursor`, `gemini-cli`, `other` or `unknown`. Default `unknown`.               |
| `name`   | A label shown on Connected agents, up to 80 characters.                                                |
| `scopes` | A JSON list of scope names, or omit it for the defaults: `assets:read`, `assets:write`, `games:write`. |

No authentication. HTTP 201:

```json
{
    "login_id": "2d9e...",
    "token": "rbk_...",
    "approval_url": "https://rosebud.ai/connect/assets#<secret>",
    "status": "pending",
    "expires_at": "2026-10-27T18:34:11Z",
    "scopes": ["assets:read", "assets:write", "games:write"]
}
```

Keep `token` secret and give only `approval_url` to the person. The token works once they approve, within 30 minutes. They approve the whole set of scopes shown.

### Scopes

`scopes` defaults to all three below, also when it's `null`. Otherwise it must be a list of one to ten of these names; anything else, including `games:read` and `[]`, returns `400 invalid_scope`.

| Scope          | Lets the token                                                                                       |
| -------------- | ---------------------------------------------------------------------------------------------------- |
| `assets:read`  | List and read the person's assets and jobs.                                                          |
| `assets:write` | Quote and start paid jobs, cancel them, and rename or restore assets.                                |
| `games:write`  | Import a new game into the account, and open an [upload session](/docs/api/hosting/uploads.md) for one. |

No scope deletes assets, uploads to My assets, manages keys or reads usage. A login token isn't an agent token: importing a game with it creates that game's own connection (`agent_token`), which keeps working after the login is revoked or expires, until its own 90 days run out.

## Check the login

```http
GET /api/v1/agent-logins/current/
Authorization: Bearer rbk_...
```

```json
{
    "login_id": "2d9e...",
    "status": "active",
    "client": "claude-code",
    "name": "Claude Code",
    "scopes": ["assets:read", "assets:write", "games:write"],
    "expires_at": "2027-01-25T18:04:11Z",
    "account": { "display_name": "Sam", "balance": 12400 }
}
```

`status` is `pending`, `active`, `expired` or `revoked`. `expires_at` is the approval deadline while pending, then the token's expiry: 90 days after its last use. `balance` is a credit count or `"unlimited"`; `account` is null when the token doesn't work. A check counts as use.

Each use moves the expiry 90 days ahead, written at most once a day, so it can trail the last use by up to a day. An expired token is never renewed: the person approves a new login.

## End the login

```http
DELETE /api/v1/agent-logins/current/
Authorization: Bearer rbk_...
```

HTTP 204. Cancels a pending login or revokes an approved one, even an expired one. Revoking takes effect on the next request.

## Errors on the publishing endpoints

Publishing endpoints answer login errors as `{ "error": { "code", "message", "required_scope"? } }`, and a 401 carries `WWW-Authenticate: Bearer realm="api"`. The asset endpoints answer the same codes as `{ "detail", "code" }`.

| Code                           | Status | When                                                                                      |
| ------------------------------ | ------ | ----------------------------------------------------------------------------------------- |
| `login_pending`                | 403    | The login still waits for approval.                                                       |
| `login_inactive`               | 401    | The login was cancelled or revoked, or its approval link expired before approval.         |
| `key_expired`                  | 401    | The token went 90 days without use. The person approves a new login.                      |
| `insufficient_scope`           | 403    | The token lacks the scope in `required_scope`. Start a new login with the default scopes. |
| `invalid_key`, `invalid_token` | 401    | The token is unknown, malformed or revoked.                                               |
| `invalid_scope`                | 400    | A new login asked for a scope it can't have.                                              |

# Models

URL: /docs/api/assets/models

> GET /api/v1/asset-models/ — list the asset models with inputs, prices and licenses.

```http
GET /api/v1/asset-models/?category=image
GET /api/v1/asset-models/{model_id}/
```

No authentication. `category` is optional and takes any category in the list, such as `image` or `model_3d`.

## Model fields

| Field                         | Details                                                                                                                                                                                                                                                                        |
| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `id`                          | Pass it as `model` to quotes.                                                                                                                                                                                                                                                  |
| `name`, `summary`, `provider` | For display.                                                                                                                                                                                                                                                                   |
| `category`                    | One of the categories above.                                                                                                                                                                                                                                                   |
| `status`                      | `live` when it can be used.                                                                                                                                                                                                                                                    |
| `price.credits`               | Base price per asset.                                                                                                                                                                                                                                                          |
| `price.note`                  | When the price depends on inputs, what the base price covers, for example "for a 5 s 720p clip; priced per second".                                                                                                                                                            |
| `price.add_ons`               | Extra credits, each with the input values it `applies_to`.                                                                                                                                                                                                                     |
| `inputs`                      | Each input's `name`, `type` (`string`, `enum`, `integer`, ...), `required`, `description`, and where they apply `max_length`, `values`, `default`, `minimum`, `maximum`. A `file` input takes a My assets ID or an `https` URL; `accepts` lists the asset categories it takes. |
| `output_formats`              | File formats the model returns.                                                                                                                                                                                                                                                |
| `license`                     | `id`, `summary` and `url`.                                                                                                                                                                                                                                                     |
| `web_path`                    | The page on rosebud.ai that uses this model, or null.                                                                                                                                                                                                                          |
| `typical_seconds`             | Median time to a finished job over the last 30 days, or an estimate.                                                                                                                                                                                                           |

The [Models](/docs/models.md) section shows this list.

# Quotes

URL: /docs/api/assets/quotes

> POST /api/v1/asset-quotes/ — check inputs and lock a price, free.

```http
POST /api/v1/asset-quotes/
Authorization: Bearer rbk_...
Content-Type: application/json
```

```json
{
    "model": "flux-2-flash",
    "input": { "prompt": "mossy stone tile, top-down", "asset_type": "texture_tile" }
}
```

Needs the `assets:write` scope. HTTP 201:

```json
{
    "id": "7c0e...",
    "model": "flux-2-flash",
    "input": { "prompt": "mossy stone tile, top-down", "asset_type": "texture_tile", "seed": 18342 },
    "credits": 250,
    "balance": 12400,
    "payment_required": false,
    "expires_at": "2026-10-27T18:09:11Z"
}
```

* `credits` is the full price, including add-ons.
* `payment_required` is true when the balance is below the price.
* The quote holds its price for 10 minutes, until `expires_at`. Pass its `id` to [create a job](/docs/api/assets/jobs.md).

# Jobs

URL: /docs/api/assets/jobs

> Pay for a quote and start a job, then poll it until the asset is ready.

## Create a job

```http
POST /api/v1/asset-jobs/
Authorization: Bearer rbk_...
Idempotency-Key: 5b2f0c1e-...
Content-Type: application/json
```

```json
{ "quote_id": "7c0e..." }
```

Needs `assets:write`. The `Idempotency-Key` header (or an `idempotency_key` field) is required: 1–128 letters, digits, `.`, `_`, `:` or `-`. A UUID works. Sending the same key again returns the same job instead of paying twice.

HTTP 202 for a new job, or HTTP 200 for a replay:

```json
{
    "id": "41b8...",
    "status": "queued",
    "model": "flux-2-flash",
    "input": { "prompt": "mossy stone tile, top-down", "asset_type": "texture_tile", "seed": 18342 },
    "idempotency_key": "5b2f0c1e-...",
    "credits": 250,
    "charged_credits": 250,
    "refunded_credits": 0,
    "asset": null,
    "error": null,
    "created_at": "2026-10-27T18:04:11Z",
    "completed_at": null,
    "deadline_at": "2026-10-27T18:14:11Z"
}
```

Credits are charged when the job starts and returned if it fails.

## Get a job

```http
GET /api/v1/asset-jobs/{job_id}/
Authorization: Bearer rbk_...
```

Needs `assets:read`. `status` is `queued`, `running`, `succeeded`, `failed`, `canceled` or `timed_out`. Poll with backoff; when it's `succeeded`, `asset` has the result and its `url`. When it fails, `error` has the reason.

## List jobs

```http
GET /api/v1/asset-jobs/
```

The account's jobs, newest first, paginated.

# Assets

URL: /docs/api/assets/assets

> GET /api/v1/assets/ — search the person's assets and read one.

```http
GET /api/v1/assets/?q=stone&category=image
GET /api/v1/assets/{asset_id}/
Authorization: Bearer rbk_...
```

Needs `assets:read`. The list is everything in the person's [My assets](/assets), newest first, 25 per page.

| Query      | Details                                                     |
| ---------- | ----------------------------------------------------------- |
| `q`        | Search text, up to 200 characters.                          |
| `category` | `image`, `sprite`, `skybox`, `model_3d`, `audio` or `file`. |
| `source`   | Comma-separated: `generated`, `uploaded`, `remixed`.        |
| `game`     | A game ID, or `none` for assets not in a game.              |
| `page`     | Page number.                                                |

## Asset fields

```json
{
    "id": "e2f0...",
    "name": "mossy stone tile",
    "category": "image",
    "source": "generated",
    "made_with": "api",
    "prompt": "mossy stone tile, top-down",
    "caption": "",
    "file_name": "mossy-stone-tile.png",
    "format": "png",
    "url": "https://...",
    "preview_url": "https://...",
    "metadata": { "width": 412, "height": 398 },
    "model": "flux-2-flash",
    "job_id": "41b8...",
    "created_at": "2026-10-27T18:04:20Z",
    "deleted_at": null,
    "restore_until": null
}
```

Download the file from `url`. URLs on `api.rosebud.ai` need the same `Authorization` header.

# Website-only endpoints

URL: /docs/api/website-only

> Endpoints the rosebud.ai website calls from a signed-in browser. Agents don't call these.

The website uses a few more endpoints for claiming games, approving connections and logins, and managing them in Project Settings and on [Connected agents](/developers/keys). They run with a signed-in rosebud.ai session, aren't served on `api.rosebud.ai`, and refuse login tokens with `key_not_allowed`.

Agents never call them. Give the person the private `claim_url` or `approval_url` instead: visiting a link never claims or approves anything until they confirm on the page.

# All models

URL: /docs/models

> Every model you can make assets with, its price in credits, inputs and license.

This list comes from the live model catalog, the same one [`rosebud assets models`](/docs/cli/assets/models.md) and [`GET /api/v1/asset-models/`](/docs/api/assets/models.md) return. A free quote checks the price again before you pay. Credits are charged when a job starts and returned if it fails. New to assets? Start with [Make assets](/docs/guides/make-assets.md).

## 2D image

| Model | ID | Price | Summary |
| --- | --- | --- | --- |
| [Flux 2 Flash](/docs/models/flux-2-flash.md) | `flux-2-flash` | 250 credits | Fast, low-cost 2D game art: sprites, icons, UI pieces, backgrounds and textures. |
| [Nano Banana 2](/docs/models/nano-banana-2.md) | `nano-banana-2` | 1,700 credits | Detailed 2D game art that follows long prompts closely. |
| [GPT Image 2.5](/docs/models/gpt-image-2-5.md) | `gpt-image-2-5` | 1,800 credits at high quality; less at low or medium | OpenAI's image model: precise text and layouts, transparent backgrounds, and edits from a reference image. |
| [Nano Banana Pro](/docs/models/nano-banana-pro.md) | `nano-banana-pro` | 3,300 credits at 1K or 2K; double at 4K | Google's most capable image model, for detailed scenes and edits from a reference image. |
| [Seedream 5 Pro](/docs/models/seedream-5-pro.md) | `seedream-5-pro` | 1,500 credits at preset sizes; double at auto_2K | ByteDance's image model: strong illustration styles and edits from a reference image. |
| [Recraft 4.1](/docs/models/recraft-4-1.md) | `recraft-4-1` | 800 credits | Clean, design-led images: UI art, icons and illustrations. |
| [Recraft 4.1 SVG](/docs/models/recraft-4-1-svg.md) | `recraft-4-1-svg` | 1,800 credits | Vector art as an SVG that scales to any size: icons, logos, UI. |
| [Ideogram 3 Transparent](/docs/models/ideogram-3-transparent.md) | `ideogram-3-transparent` | 1,350 credits at BALANCED speed; less at TURBO, more at QUALITY | Images with a transparent background, good at lettering: logos, title text, stickers. |
| [Ideogram 4 Tiling](/docs/models/ideogram-tiling.md) | `ideogram-tiling` | 1,400 credits at BALANCED speed; less at TURBO, more at QUALITY | A seamless texture that tiles in both directions, or only one. |
| [Qwen Multiple Angles](/docs/models/qwen-multiple-angles.md) | `qwen-multiple-angles` | 900 credits | The same subject seen from another angle: side, back, above. |
| [Remove background](/docs/models/remove-background.md) | `remove-background` | 250 credits | Cuts the subject out of an image onto a transparent background. |
| [Crisp upscale](/docs/models/crisp-upscale.md) | `crisp-upscale` | 100 credits | Enlarges a PNG while keeping edges sharp. |
| [Vectorize](/docs/models/vectorize.md) | `vectorize` | 900 credits | Traces an image (PNG, JPEG or WebP under 5 MB) into an SVG. |

## Skybox

| Model | ID | Price | Summary |
| --- | --- | --- | --- |
| [Rosebud Skybox](/docs/models/rosebud-skybox.md) | `rosebud-skybox` | 2,000 credits | A 2:1 equirectangular sky panorama for 3D scenes. |

## 3D model

| Model | ID | Price | Summary |
| --- | --- | --- | --- |
| [Rosie 3D](/docs/models/rosie-3d.md) | `rosie-3d` | 1,000 credits | A textured GLB model from a text prompt. Supported humanoids come rigged and animated at no extra charge. |
| [Meshy 7.1](/docs/models/meshy-7-1.md) | `meshy-7-1` | 26,400 credits | A textured GLB from a prompt or one image, with clean topology options including low-poly. |
| [Tripo P2](/docs/models/tripo-p2.md) | `tripo-p2` | 24,200 credits with standard textures; more for detailed or extreme | A textured, PBR-ready GLB from a prompt or one image. |
| [Rodin 2.5](/docs/models/rodin-2-5.md) | `rodin-2-5` | 8,800 credits | The lowest-cost 3D model here: a 20k-triangle PBR GLB from a prompt or image. |
| [Meshy Rigging](/docs/models/meshy-rigging.md) | `meshy-rigging` | 17,600 credits | Adds a humanoid skeleton to a character GLB so it can be animated. |

## Sound effect

| Model | ID | Price | Summary |
| --- | --- | --- | --- |
| [Sound effect](/docs/models/sound-effect.md) | `sound-effect` | 250 credits | A short game sound effect. |

## Music

| Model | ID | Price | Summary |
| --- | --- | --- | --- |
| [Background music](/docs/models/background-music.md) | `background-music` | 1,550 credits | A background music track for a game scene. |

## Video

| Model | ID | Price | Summary |
| --- | --- | --- | --- |
| [Kling 4](/docs/models/kling-4.md) | `kling-4` | 17,300 credits for a 5 s 720p clip; priced per second, more at 1080p | Smooth, cinematic clips from a prompt or a first frame. |
| [Seedance 2.5](/docs/models/seedance-2-5.md) | `seedance-2-5` | 52,050 credits for a 5 s 720p clip; priced per second by resolution | Clips with matching sound and lip-synced speech, from a prompt or a first frame. |
| [Veo 3.1 Fast](/docs/models/veo-3-1-fast.md) | `veo-3-1-fast` | 26,400 credits for an 8 s 720p clip with sound; priced per second, less without sound | Google's fast video model, with generated sound. |
| [MiniMax H3 Max Turbo](/docs/models/minimax-h3-max-turbo.md) | `minimax-h3-max-turbo` | 4,400 credits for a 5 s 768P clip; priced per second by resolution | The lowest-cost video model here: quick clips from a prompt, optionally from a first frame. |

## Speech

| Model | ID | Price | Summary |
| --- | --- | --- | --- |
| [Eleven v4 speech](/docs/models/eleven-v4-speech.md) | `eleven-v4-speech` | 1,800 credits per 1,000 characters of text | Spoken lines for characters and narration. Audio tags such as [whispering] set the delivery. |

# Flux 2 Flash

URL: /docs/models/flux-2-flash

> Fast, low-cost 2D game art: sprites, icons, UI pieces, backgrounds and textures.

- ID: `flux-2-flash`
- Category: 2D image
- Price: 250 credits
  - +50 credits for transparent background when `asset_type` is `sprite`, `vfx_sprite`, `icon`, `ui_element`, `character_portrait`.
- Output: png, webp
- Provider: Black Forest Labs via fal
- On the website: https://rosebud.ai/2d-assets
- Typical time: about 5 seconds

## Make one

```sh
rosebud assets create --model flux-2-flash \
    --prompt 'health potion icon, red glass bottle' \
    --max-credits 250 \
    --out ./assets/health-potion.png
```

## Inputs

| Input | Type | Required | Details |
| --- | --- | --- | --- |
| `prompt` | string | Yes | What to draw. Up to 1000 characters. |
| `asset_type` | enum | No | Shapes the prompt and the background. Sprites, icons, UI elements, VFX sprites and portraits come back with a transparent background. One of `any`, `sprite`, `vfx_sprite`, `icon`, `ui_element`, `background`, `character_portrait`, `texture_tile`. Default `any`. |
| `output_format` | enum | No | Image file format. One of `png`, `webp`. Default `png`. |
| `seed` | integer | No | Repeat a result by reusing its seed. A random seed is chosen when omitted. From 0 to 2147483647. |

## License

Generated for your account. Use is governed by the Rosebud Terms of Service. [rosebud-generated](https://rosebud.ai/terms-of-service)

# Nano Banana 2

URL: /docs/models/nano-banana-2

> Detailed 2D game art that follows long prompts closely.

- ID: `nano-banana-2`
- Category: 2D image
- Price: 1,700 credits
  - +50 credits for transparent background when `asset_type` is `sprite`, `vfx_sprite`, `icon`, `ui_element`, `character_portrait`.
- Output: png, webp
- Provider: Google
- On the website: https://rosebud.ai/2d-assets
- Typical time: about 8 seconds

## Make one

```sh
rosebud assets create --model nano-banana-2 \
    --prompt 'health potion icon, red glass bottle' \
    --max-credits 1700 \
    --out ./assets/health-potion.png
```

## Inputs

| Input | Type | Required | Details |
| --- | --- | --- | --- |
| `prompt` | string | Yes | What to draw. Up to 1000 characters. |
| `asset_type` | enum | No | Shapes the prompt and the background. Sprites, icons, UI elements, VFX sprites and portraits come back with a transparent background. One of `any`, `sprite`, `vfx_sprite`, `icon`, `ui_element`, `background`, `character_portrait`, `texture_tile`. Default `any`. |
| `output_format` | enum | No | Image file format. One of `png`, `webp`. Default `png`. |
| `seed` | integer | No | Repeat a result by reusing its seed. A random seed is chosen when omitted. From 0 to 2147483647. |

## License

Generated for your account. Use is governed by the Rosebud Terms of Service. [rosebud-generated](https://rosebud.ai/terms-of-service)

# GPT Image 2.5

URL: /docs/models/gpt-image-2-5

> OpenAI's image model: precise text and layouts, transparent backgrounds, and edits from a reference image.

- ID: `gpt-image-2-5`
- Category: 2D image
- Price: 1,800 credits at high quality; less at low or medium
- Output: png, webp
- Provider: OpenAI via fal
- Typical time: about 40 seconds

## Make one

```sh
rosebud assets create --model gpt-image-2-5 \
    --prompt 'health potion icon, red glass bottle' \
    --max-credits 1800 \
    --out ./assets/health-potion.png
```

## Inputs

| Input | Type | Required | Details |
| --- | --- | --- | --- |
| `prompt` | string | Yes | What to draw, or how to change the image. Up to 4000 characters. |
| `image` | file | No | Edit or restyle this image. A My assets id or an https URL (image). |
| `quality` | enum | No | Detail; each step up costs more. One of `low`, `medium`, `high`. Default `high`. |
| `background` | enum | No | transparent gives a PNG cut-out for sprites and icons. One of `auto`, `transparent`, `opaque`. Default `auto`. |
| `image_size` | enum | No | Image shape. One of `square_hd`, `portrait_4_3`, `portrait_16_9`, `landscape_4_3`, `landscape_16_9`. Default `square_hd`. |
| `output_format` | enum | No | Image file format. One of `png`, `webp`. Default `png`. |

## License

Generated for your account. Use is governed by the Rosebud Terms of Service. [rosebud-generated](https://rosebud.ai/terms-of-service)

# Nano Banana Pro

URL: /docs/models/nano-banana-pro

> Google's most capable image model, for detailed scenes and edits from a reference image.

- ID: `nano-banana-pro`
- Category: 2D image
- Price: 3,300 credits at 1K or 2K; double at 4K
- Output: png, webp
- Provider: Google via fal
- Typical time: about 30 seconds

## Make one

```sh
rosebud assets create --model nano-banana-pro \
    --prompt 'health potion icon, red glass bottle' \
    --max-credits 3300 \
    --out ./assets/health-potion.png
```

## Inputs

| Input | Type | Required | Details |
| --- | --- | --- | --- |
| `prompt` | string | Yes | What to draw, or how to change the image. Up to 4000 characters. |
| `image` | file | No | Edit or restyle this image. A My assets id or an https URL (image). |
| `resolution` | enum | No | Output size. One of `1K`, `2K`, `4K`. Default `1K`. |
| `aspect_ratio` | enum | No | Image shape for a text-only image; an edit keeps the input's. One of `1:1`, `16:9`, `9:16`, `4:3`, `3:4`, `3:2`, `2:3`, `21:9`. Default `1:1`. |
| `output_format` | enum | No | Image file format. One of `png`, `webp`. Default `png`. |
| `seed` | integer | No | Repeat a result by reusing its seed. A random seed is chosen when omitted. From 0 to 2147483647. |

## License

Generated for your account. Use is governed by the Rosebud Terms of Service. [rosebud-generated](https://rosebud.ai/terms-of-service)

# Seedream 5 Pro

URL: /docs/models/seedream-5-pro

> ByteDance's image model: strong illustration styles and edits from a reference image.

- ID: `seedream-5-pro`
- Category: 2D image
- Price: 1,500 credits at preset sizes; double at auto_2K
- Output: png, jpeg
- Provider: ByteDance via fal
- Typical time: about 20 seconds

## Make one

```sh
rosebud assets create --model seedream-5-pro \
    --prompt 'health potion icon, red glass bottle' \
    --max-credits 1500 \
    --out ./assets/health-potion.png
```

## Inputs

| Input | Type | Required | Details |
| --- | --- | --- | --- |
| `prompt` | string | Yes | What to draw, or how to change the image. Up to 4000 characters. |
| `image` | file | No | Edit or restyle this image. A My assets id or an https URL (image). |
| `image_size` | enum | No | Image shape; auto_2K is larger. One of `square_hd`, `portrait_4_3`, `portrait_16_9`, `landscape_4_3`, `landscape_16_9`, `auto_2K`. Default `square_hd`. |
| `output_format` | enum | No | Image file format. One of `png`, `jpeg`. Default `png`. |

## License

Generated for your account. Use is governed by the Rosebud Terms of Service. [rosebud-generated](https://rosebud.ai/terms-of-service)

# Recraft 4.1

URL: /docs/models/recraft-4-1

> Clean, design-led images: UI art, icons and illustrations.

- ID: `recraft-4-1`
- Category: 2D image
- Price: 800 credits
- Output: webp, png
- Provider: Recraft via fal
- Typical time: about 15 seconds

## Make one

```sh
rosebud assets create --model recraft-4-1 \
    --prompt 'health potion icon, red glass bottle' \
    --max-credits 800 \
    --out ./assets/health-potion.webp
```

## Inputs

| Input | Type | Required | Details |
| --- | --- | --- | --- |
| `prompt` | string | Yes | What to draw. Up to 1000 characters. |
| `image_size` | enum | No | Image shape. One of `square_hd`, `portrait_4_3`, `portrait_16_9`, `landscape_4_3`, `landscape_16_9`. Default `square_hd`. |

## License

Generated for your account. Use is governed by the Rosebud Terms of Service. [rosebud-generated](https://rosebud.ai/terms-of-service)

# Recraft 4.1 SVG

URL: /docs/models/recraft-4-1-svg

> Vector art as an SVG that scales to any size: icons, logos, UI.

- ID: `recraft-4-1-svg`
- Category: 2D image
- Price: 1,800 credits
- Output: svg
- Provider: Recraft via fal
- Typical time: about 20 seconds

## Make one

```sh
rosebud assets create --model recraft-4-1-svg \
    --prompt 'health potion icon, red glass bottle' \
    --max-credits 1800 \
    --out ./assets/health-potion.svg
```

## Inputs

| Input | Type | Required | Details |
| --- | --- | --- | --- |
| `prompt` | string | Yes | What to draw. Up to 1000 characters. |
| `image_size` | enum | No | Image shape. One of `square_hd`, `portrait_4_3`, `portrait_16_9`, `landscape_4_3`, `landscape_16_9`. Default `square_hd`. |

## License

Generated for your account. Use is governed by the Rosebud Terms of Service. [rosebud-generated](https://rosebud.ai/terms-of-service)

# Ideogram 3 Transparent

URL: /docs/models/ideogram-3-transparent

> Images with a transparent background, good at lettering: logos, title text, stickers.

- ID: `ideogram-3-transparent`
- Category: 2D image
- Price: 1,350 credits at BALANCED speed; less at TURBO, more at QUALITY
- Output: png
- Provider: Ideogram via fal
- Typical time: about 15 seconds

## Make one

```sh
rosebud assets create --model ideogram-3-transparent \
    --prompt 'health potion icon, red glass bottle' \
    --max-credits 1350 \
    --out ./assets/health-potion.png
```

## Inputs

| Input | Type | Required | Details |
| --- | --- | --- | --- |
| `prompt` | string | Yes | What to draw. Up to 2000 characters. |
| `rendering_speed` | enum | No | TURBO is cheapest; QUALITY is most detailed. One of `TURBO`, `BALANCED`, `QUALITY`. Default `BALANCED`. |
| `aspect_ratio` | enum | No | Image shape. One of `1:1`, `16:9`, `9:16`, `4:3`, `3:4`, `3:2`, `2:3`. Default `1:1`. |
| `seed` | integer | No | Repeat a result by reusing its seed. A random seed is chosen when omitted. From 0 to 2147483647. |

## License

Generated for your account. Use is governed by the Rosebud Terms of Service. [rosebud-generated](https://rosebud.ai/terms-of-service)

# Ideogram 4 Tiling

URL: /docs/models/ideogram-tiling

> A seamless texture that tiles in both directions, or only one.

- ID: `ideogram-tiling`
- Category: 2D image
- Price: 1,400 credits at BALANCED speed; less at TURBO, more at QUALITY
- Output: png, jpeg
- Provider: Ideogram via fal
- Typical time: about 15 seconds

## Make one

```sh
rosebud assets create --model ideogram-tiling \
    --prompt 'health potion icon, red glass bottle' \
    --max-credits 1400 \
    --out ./assets/health-potion.png
```

## Inputs

| Input | Type | Required | Details |
| --- | --- | --- | --- |
| `prompt` | string | Yes | The surface, such as mossy cobblestones. Up to 2000 characters. |
| `image` | file | No | Turn this image into a tiling texture. A My assets id or an https URL (image). |
| `tiling_mode` | enum | No | Which edges wrap. One of `both`, `horizontal`, `vertical`. Default `both`. |
| `rendering_speed` | enum | No | TURBO is cheapest; QUALITY is most detailed. One of `TURBO`, `BALANCED`, `QUALITY`. Default `BALANCED`. |
| `output_format` | enum | No | Image file format. One of `png`, `jpeg`. Default `png`. |
| `seed` | integer | No | Repeat a result by reusing its seed. A random seed is chosen when omitted. From 0 to 2147483647. |

## License

Generated for your account. Use is governed by the Rosebud Terms of Service. [rosebud-generated](https://rosebud.ai/terms-of-service)

# Qwen Multiple Angles

URL: /docs/models/qwen-multiple-angles

> The same subject seen from another angle: side, back, above.

- ID: `qwen-multiple-angles`
- Category: 2D image
- Price: 900 credits
- Output: png
- Provider: Qwen via fal
- Typical time: about 20 seconds

## Make one

```sh
rosebud assets create --model qwen-multiple-angles \
    --input image=<asset_id> \
    --max-credits 900 \
    --out ./assets/health-potion.png
```

## Inputs

| Input | Type | Required | Details |
| --- | --- | --- | --- |
| `image` | file | Yes | The subject to turn. A My assets id or an https URL (image). |
| `horizontal_angle` | number | No | Degrees around the subject: 0 front, 90 right side, 180 back. Default `0`. From 0 to 360. |
| `vertical_angle` | number | No | Camera height in degrees: -30 looking up, 0 eye level, 60 above. Default `0`. From -30 to 90. |
| `zoom` | number | No | 0 far away, 5 medium, 10 close-up. Default `5`. From 0 to 10. |
| `seed` | integer | No | Repeat a result by reusing its seed. A random seed is chosen when omitted. From 0 to 2147483647. |

## License

Generated for your account. Use is governed by the Rosebud Terms of Service. [rosebud-generated](https://rosebud.ai/terms-of-service)

# Remove background

URL: /docs/models/remove-background

> Cuts the subject out of an image onto a transparent background.

- ID: `remove-background`
- Category: 2D image
- Price: 250 credits
- Output: png
- Provider: Ideogram via fal
- Typical time: about 8 seconds

## Make one

```sh
rosebud assets create --model remove-background \
    --input image=<asset_id> \
    --max-credits 250 \
    --out ./assets/health-potion.png
```

## Inputs

| Input | Type | Required | Details |
| --- | --- | --- | --- |
| `image` | file | Yes | The image to cut out. A My assets id or an https URL (image). |

## License

Generated for your account. Use is governed by the Rosebud Terms of Service. [rosebud-generated](https://rosebud.ai/terms-of-service)

# Crisp upscale

URL: /docs/models/crisp-upscale

> Enlarges a PNG while keeping edges sharp.

- ID: `crisp-upscale`
- Category: 2D image
- Price: 100 credits
- Output: webp
- Provider: Recraft via fal
- Typical time: about 10 seconds

## Make one

```sh
rosebud assets create --model crisp-upscale \
    --input image=<asset_id> \
    --max-credits 100 \
    --out ./assets/health-potion.webp
```

## Inputs

| Input | Type | Required | Details |
| --- | --- | --- | --- |
| `image` | file | Yes | The PNG to enlarge. A My assets id or an https URL (image). |

## License

Generated for your account. Use is governed by the Rosebud Terms of Service. [rosebud-generated](https://rosebud.ai/terms-of-service)

# Vectorize

URL: /docs/models/vectorize

> Traces an image (PNG, JPEG or WebP under 5 MB) into an SVG.

- ID: `vectorize`
- Category: 2D image
- Price: 900 credits
- Output: svg
- Provider: Recraft via fal
- Typical time: about 10 seconds

## Make one

```sh
rosebud assets create --model vectorize \
    --input image=<asset_id> \
    --max-credits 900 \
    --out ./assets/health-potion.svg
```

## Inputs

| Input | Type | Required | Details |
| --- | --- | --- | --- |
| `image` | file | Yes | The image to trace. A My assets id or an https URL (image). |

## License

Generated for your account. Use is governed by the Rosebud Terms of Service. [rosebud-generated](https://rosebud.ai/terms-of-service)

# Rosebud Skybox

URL: /docs/models/rosebud-skybox

> A 2:1 equirectangular sky panorama for 3D scenes.

- ID: `rosebud-skybox`
- Category: Skybox
- Price: 2,000 credits
- Output: webp
- Provider: Rosebud on Nano Banana 2
- On the website: https://rosebud.ai/skyboxes
- Typical time: about 32 seconds

## Make one

```sh
rosebud assets create --model rosebud-skybox \
    --prompt 'sunset over a desert canyon' \
    --input mode=surface \
    --max-credits 2000 \
    --out ./assets/desert-sky.webp
```

## Inputs

| Input | Type | Required | Details |
| --- | --- | --- | --- |
| `prompt` | string | Yes | The scene around the player. Up to 4000 characters. |
| `mode` | enum | Yes | surface: ground and a horizon. space: nothing to stand on. One of `surface`, `space`. |
| `seed` | integer | No | Repeat a result by reusing its seed. A random seed is chosen when omitted. From 0 to 2147483647. |

## License

Generated for your account. Use is governed by the Rosebud Terms of Service. [rosebud-generated](https://rosebud.ai/terms-of-service)

# Rosie 3D

URL: /docs/models/rosie-3d

> A textured GLB model from a text prompt. Supported humanoids come rigged and animated at no extra charge.

- ID: `rosie-3d`
- Category: 3D model
- Price: 1,000 credits
- Output: glb
- Provider: Rosebud
- On the website: https://rosebud.ai/3d-models
- Typical time: about 21 seconds

## Make one

```sh
rosebud assets create --model rosie-3d \
    --prompt 'wooden treasure chest' \
    --max-credits 1000 \
    --out ./assets/treasure-chest.glb
```

## Inputs

| Input | Type | Required | Details |
| --- | --- | --- | --- |
| `prompt` | string | Yes | The object or character. Up to 1024 characters. |

## License

Generated for your account. Use is governed by the Rosebud Terms of Service. [rosebud-generated](https://rosebud.ai/terms-of-service)

# Meshy 7.1

URL: /docs/models/meshy-7-1

> A textured GLB from a prompt or one image, with clean topology options including low-poly.

- ID: `meshy-7-1`
- Category: 3D model
- Price: 26,400 credits
- Output: glb
- Provider: Meshy via fal
- Typical time: about 3 minutes

## Make one

```sh
rosebud assets create --model meshy-7-1 \
    --prompt 'wooden treasure chest' \
    --max-credits 26400 \
    --out ./assets/treasure-chest.glb
```

## Inputs

| Input | Type | Required | Details |
| --- | --- | --- | --- |
| `prompt` | string | No | The object or character. Optional with an image. Up to 600 characters. |
| `image` | file | No | Build the model from this image instead of the prompt (one object, plain background works best). A My assets id or an https URL (image). |
| `model_type` | enum | No | standard: high detail. lowpoly: fewer, cleaner polygons for games. One of `standard`, `lowpoly`. Default `standard`. |
| `topology` | enum | No | Mesh faces. One of `triangle`, `quad`. Default `triangle`. |
| `target_polycount` | integer | No | About how many polygons the mesh should have. Default `30000`. From 100 to 300000. |
| `enable_pbr` | boolean | No | Add metallic, roughness and normal maps. `true` or `false`. Default `false`. |

## License

Generated for your account. Use is governed by the Rosebud Terms of Service. [rosebud-generated](https://rosebud.ai/terms-of-service)

# Tripo P2

URL: /docs/models/tripo-p2

> A textured, PBR-ready GLB from a prompt or one image.

- ID: `tripo-p2`
- Category: 3D model
- Price: 24,200 credits with standard textures; more for detailed or extreme
- Output: glb
- Provider: Tripo via fal
- Typical time: about 3 minutes

## Make one

```sh
rosebud assets create --model tripo-p2 \
    --prompt 'wooden treasure chest' \
    --max-credits 24200 \
    --out ./assets/treasure-chest.glb
```

## Inputs

| Input | Type | Required | Details |
| --- | --- | --- | --- |
| `prompt` | string | No | The object or character. Optional with an image. Up to 1024 characters. |
| `image` | file | No | Build the model from this image instead of the prompt (one object, plain background works best). A My assets id or an https URL (image). |
| `texture_quality` | enum | No | Texture detail; each step up costs more. One of `standard`, `detailed`, `extreme`. Default `standard`. |
| `quad` | boolean | No | Quad faces instead of triangles. `true` or `false`. Default `false`. |
| `face_limit` | integer | No | Most faces the mesh may have; at most 25,000 with quad. From 1000 to 50000. |

## License

Generated for your account. Use is governed by the Rosebud Terms of Service. [rosebud-generated](https://rosebud.ai/terms-of-service)

# Rodin 2.5

URL: /docs/models/rodin-2-5

> The lowest-cost 3D model here: a 20k-triangle PBR GLB from a prompt or image.

- ID: `rodin-2-5`
- Category: 3D model
- Price: 8,800 credits
- Output: glb
- Provider: Hyper3D via fal
- Typical time: about 2 minutes

## Make one

```sh
rosebud assets create --model rodin-2-5 \
    --prompt 'wooden treasure chest' \
    --max-credits 8800 \
    --out ./assets/treasure-chest.glb
```

## Inputs

| Input | Type | Required | Details |
| --- | --- | --- | --- |
| `prompt` | string | No | The object or character. Optional with an image. Up to 1000 characters. |
| `image` | file | No | Build the model from this image instead of the prompt (one object, plain background works best). A My assets id or an https URL (image). |
| `tier` | enum | No | Model quality; Low and Medium finish in under a minute. One of `Gen-2.5-Low`, `Gen-2.5-Medium`, `Gen-2.5-High`. Default `Gen-2.5-High`. |
| `t_a_pose` | boolean | No | Make a character in a T- or A-pose, ready for rigging. `true` or `false`. Default `false`. |

## License

Generated for your account. Use is governed by the Rosebud Terms of Service. [rosebud-generated](https://rosebud.ai/terms-of-service)

# Meshy Rigging

URL: /docs/models/meshy-rigging

> Adds a humanoid skeleton to a character GLB so it can be animated.

- ID: `meshy-rigging`
- Category: 3D model
- Price: 17,600 credits
- Output: glb
- Provider: Meshy via fal
- Typical time: about 2 minutes

## Make one

```sh
rosebud assets create --model meshy-rigging \
    --input model=<asset_id> \
    --max-credits 17600 \
    --out ./assets/treasure-chest.glb
```

## Inputs

| Input | Type | Required | Details |
| --- | --- | --- | --- |
| `model` | file | Yes | The humanoid character to rig, standing with clear arms and legs. A My assets id or an https URL (3d model). |
| `height_meters` | number | No | About how tall the character is. Default `1.7`. From 0.3 to 5. |

## License

Generated for your account. Use is governed by the Rosebud Terms of Service. [rosebud-generated](https://rosebud.ai/terms-of-service)

# Sound effect

URL: /docs/models/sound-effect

> A short game sound effect.

- ID: `sound-effect`
- Category: Sound effect
- Price: 250 credits
- Output: mp3
- Provider: ElevenLabs
- Typical time: about 4 seconds

## Make one

```sh
rosebud assets create --model sound-effect \
    --prompt 'coin pickup chime' \
    --max-credits 250 \
    --out ./assets/coin-pickup.mp3
```

## Inputs

| Input | Type | Required | Details |
| --- | --- | --- | --- |
| `prompt` | string | Yes | What it should sound like. Up to 1000 characters. |
| `duration_seconds` | number | No | Length of the clip in seconds. Default `1`. From 0.5 to 5. |

## License

Generated for your account. Use is governed by the Rosebud Terms of Service. [rosebud-generated](https://rosebud.ai/terms-of-service)

# Background music

URL: /docs/models/background-music

> A background music track for a game scene.

- ID: `background-music`
- Category: Music
- Price: 1,550 credits
- Output: mp3
- Provider: ElevenLabs
- Typical time: about 7 seconds

## Make one

```sh
rosebud assets create --model background-music \
    --prompt 'calm village theme that loops' \
    --max-credits 1550 \
    --out ./assets/village-theme.mp3
```

## Inputs

| Input | Type | Required | Details |
| --- | --- | --- | --- |
| `prompt` | string | Yes | What it should sound like. Up to 1000 characters. |
| `duration_seconds` | number | No | Length of the clip in seconds. Default `30`. From 3 to 30. |

## License

Generated for your account. Use is governed by the Rosebud Terms of Service. [rosebud-generated](https://rosebud.ai/terms-of-service)

# Kling 4

URL: /docs/models/kling-4

> Smooth, cinematic clips from a prompt or a first frame.

- ID: `kling-4`
- Category: Video
- Price: 17,300 credits for a 5 s 720p clip; priced per second, more at 1080p
- Output: mp4
- Provider: Kling via fal
- Typical time: about 3 minutes

## Make one

```sh
rosebud assets create --model kling-4 \
    --prompt 'title screen flythrough of a floating castle' \
    --max-credits 17300 \
    --out ./assets/title-intro.mp4
```

## Inputs

| Input | Type | Required | Details |
| --- | --- | --- | --- |
| `prompt` | string | No | What happens in the clip. Optional with an image. Up to 2500 characters. |
| `image` | file | No | Animate this image: it becomes the first frame. A My assets id or an https URL (image). |
| `duration` | integer | No | Length of the clip in seconds. Default `5`. From 3 to 10. |
| `resolution` | enum | No | Output resolution. One of `720p`, `1080p`. Default `720p`. |
| `aspect_ratio` | enum | No | Frame shape for a text-only clip; an image input sets its own. One of `16:9`, `9:16`, `1:1`, `21:9`. Default `16:9`. |

## License

Generated for your account. Use is governed by the Rosebud Terms of Service. [rosebud-generated](https://rosebud.ai/terms-of-service)

# Seedance 2.5

URL: /docs/models/seedance-2-5

> Clips with matching sound and lip-synced speech, from a prompt or a first frame.

- ID: `seedance-2-5`
- Category: Video
- Price: 52,050 credits for a 5 s 720p clip; priced per second by resolution
- Output: mp4
- Provider: ByteDance via fal
- Typical time: about 3 minutes

## Make one

```sh
rosebud assets create --model seedance-2-5 \
    --prompt 'title screen flythrough of a floating castle' \
    --max-credits 52050 \
    --out ./assets/title-intro.mp4
```

## Inputs

| Input | Type | Required | Details |
| --- | --- | --- | --- |
| `prompt` | string | No | What happens in the clip. Optional with an image. Up to 2500 characters. |
| `image` | file | No | Animate this image: it becomes the first frame. A My assets id or an https URL (image). |
| `duration` | enum | No | Length of the clip in seconds. One of `4`, `5`, `6`, `7`, `8`, `9`, `10`. Default `5`. |
| `resolution` | enum | No | Output resolution; 480p costs about half of 720p. One of `480p`, `720p`, `1080p`. Default `720p`. |
| `generate_audio` | boolean | No | Add sound effects, ambience and speech that match the clip. `true` or `false`. Default `true`. |
| `aspect_ratio` | enum | No | Frame shape for a text-only clip; an image input sets its own. One of `16:9`, `9:16`, `1:1`. Default `16:9`. |

## License

Generated for your account. Use is governed by the Rosebud Terms of Service. [rosebud-generated](https://rosebud.ai/terms-of-service)

# Veo 3.1 Fast

URL: /docs/models/veo-3-1-fast

> Google's fast video model, with generated sound.

- ID: `veo-3-1-fast`
- Category: Video
- Price: 26,400 credits for an 8 s 720p clip with sound; priced per second, less without sound
- Output: mp4
- Provider: Google via fal
- Typical time: about 2 minutes

## Make one

```sh
rosebud assets create --model veo-3-1-fast \
    --prompt 'title screen flythrough of a floating castle' \
    --max-credits 26400 \
    --out ./assets/title-intro.mp4
```

## Inputs

| Input | Type | Required | Details |
| --- | --- | --- | --- |
| `prompt` | string | Yes | What happens in the clip. Up to 2500 characters. |
| `image` | file | No | Animate this image: it becomes the first frame. A My assets id or an https URL (image). |
| `duration` | enum | No | Length of the clip. One of `4s`, `6s`, `8s`. Default `8s`. |
| `resolution` | enum | No | Output resolution. One of `720p`, `1080p`. Default `720p`. |
| `generate_audio` | boolean | No | Add sound effects, ambience and speech that match the clip. `true` or `false`. Default `true`. |
| `aspect_ratio` | enum | No | Frame shape for a text-only clip; an image input sets its own. One of `16:9`, `9:16`. Default `16:9`. |
| `seed` | integer | No | Repeat a result by reusing its seed. A random seed is chosen when omitted. From 0 to 2147483647. |

## License

Generated for your account. Use is governed by the Rosebud Terms of Service. [rosebud-generated](https://rosebud.ai/terms-of-service)

# MiniMax H3 Max Turbo

URL: /docs/models/minimax-h3-max-turbo

> The lowest-cost video model here: quick clips from a prompt, optionally from a first frame.

- ID: `minimax-h3-max-turbo`
- Category: Video
- Price: 4,400 credits for a 5 s 768P clip; priced per second by resolution
- Output: mp4
- Provider: MiniMax via fal
- Typical time: about 60 seconds

## Make one

```sh
rosebud assets create --model minimax-h3-max-turbo \
    --prompt 'title screen flythrough of a floating castle' \
    --max-credits 4400 \
    --out ./assets/title-intro.mp4
```

## Inputs

| Input | Type | Required | Details |
| --- | --- | --- | --- |
| `prompt` | string | Yes | What happens in the clip. Up to 2000 characters. |
| `image` | file | No | Animate this image: it becomes the first frame. A My assets id or an https URL (image). |
| `duration` | integer | No | Length of the clip in seconds. Default `5`. From 1 to 10. |
| `resolution` | enum | No | Output resolution. One of `480P`, `768P`, `1080P`. Default `768P`. |
| `aspect_ratio` | enum | No | Frame shape for a text-only clip; an image input sets its own. One of `16:9`, `9:16`, `1:1`, `4:3`, `3:4`, `21:9`. Default `16:9`. |
| `seed` | integer | No | Repeat a result by reusing its seed. A random seed is chosen when omitted. From 0 to 2147483647. |

## License

Generated for your account. Use is governed by the Rosebud Terms of Service. [rosebud-generated](https://rosebud.ai/terms-of-service)

# Eleven v4 speech

URL: /docs/models/eleven-v4-speech

> Spoken lines for characters and narration. Audio tags such as [whispering] set the delivery.

- ID: `eleven-v4-speech`
- Category: Speech
- Price: 1,800 credits per 1,000 characters of text
- Output: mp3
- Provider: ElevenLabs via fal
- Typical time: about 8 seconds

## Make one

```sh
rosebud assets create --model eleven-v4-speech \
    --prompt 'Welcome, traveler. The gate opens at dawn.' \
    --max-credits 1800 \
    --out ./assets/gate-guard.mp3
```

## Inputs

| Input | Type | Required | Details |
| --- | --- | --- | --- |
| `prompt` | string | Yes | The words to say. Up to 5000 characters. |
| `voice` | string | No | An ElevenLabs voice name, such as Rachel, Adam, Bella or Antoni. Default `Rachel`. Up to 64 characters. |
| `stability` | number | No | Lower is more expressive; higher is more even. Default `0.5`. From 0 to 1. |
| `language_code` | string | No | ISO 639-1 language, such as en or ja. Detected when omitted. Up to 8 characters. |

## License

Generated for your account. Use is governed by the Rosebud Terms of Service. [rosebud-generated](https://rosebud.ai/terms-of-service)
