Import a game

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

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

FieldDetails
bundleRequired. 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_tokenOptional, sent together: the media of a new-game upload session.
title1–255 characters. name is accepted as an alias if it matches.
descriptionPlain text, up to 4,000 characters.
thumbnailA separate PNG or JPEG, at most 2 MiB and 4096 pixels a side. Re-encoded to strip metadata.
contextA 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.

FieldValues
agent_clientcodex, claude-code, gemini-cli, cursor, other, unknown
agent_versionAt most 80 characters
model_provideropenai, anthropic, google, other, unknown
modelAt most 100 characters
use_caselearning, game-jam, prototype, portfolio, classroom, client-work, commercial, other
frameworkvanilla, phaser, three, other, unknown
discovery_sourcedocs, search, github, recommendation, existing-user, other, unknown

Response

HTTP 201, anonymous:

{
    "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:

{
    "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. 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.

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.

On this page