ScenebrewDevelopers

Changelog

What each published version of the api.scenebrew.com contract added, and how to migrate across the breaking ones.

The contract is published as @scenebrew/public-api-spec; its version is the info.version the API reports at /openapi.json and the version shown at the bottom of this site's sidebar.

Scenebrew is a development preview, so the contract is pre-1.0 and there is no major version: a change that breaks callers bumps the minor like any other and says so in its entry below, which is where the warning lives rather than in the digit. Releases up to and including 0.9.0 were originally numbered 1.0.0 to 5.0.0; they were renumbered onto this scheme, one release per minor, without any change to what they contain.

0.14.0 — September 2026

Add a file to an existing asset. Additive.

  • add_asset_file — POST /v1/assets/{id}/files with an uploaded file id and a role (mesh, texture, or a material channel: albedo, normal, roughness, height, metallic, ao, emission, opacity, mask) fills an empty role of an asset, whether or not a recipe already references it. Answers the asset with ETag = the role's digest: 201 when it filled the role, 200 when the role already held exactly these bytes. A role holding different bytes is never replaced here: 409 role_filled names the recipes (with slots) and themes using the asset under consumers. There is no force flag. See Library → Add a file to an asset.
  • replace_asset_file — PUT /v1/assets/{id}/files/{role} with an uploaded file id and If-Match on the digest the role holds (files[role].sha256) replaces the bytes deliberately: stale 412 precondition_failed with current_sha256, missing header 428, empty role 412. The replaced digest keeps resolving through download_asset_file?sha256= for the retention period.
  • Problem documents carry the platform's extension members (consumers, current_sha256, role) next to code; 412 and 428 join the relayed statuses. The MCP server exposes both operations (tools 0.6.0).

0.13.0 — September 2026

Theme export. Additive.

  • export_theme — GET /v1/themes/{id}/export answers the theme and everything reachable from it (its designs, their recipes, the assets those slot and the assets those reference, embedded once each) as one Scenebrew entity container (.sbe, application/vnd.scenebrew.entity+json): the file a Unity project or the standalone Architect imports. The body is byte for byte what the library wrote; X-Scenebrew-Content-Hash carries the container's hash, the same whatever the attachment mode. ?attachments=full|by-size|by-role|reference (default by-size) decides whether asset bytes ride inline or by reference; roles and slots (repeatable) name what by-role inlines. Every attachment uri is download_asset_file by digest (/v1/assets/{id}/files/{role}?sha256=), never a storage URL. A theme in another project is a 404. See Library → Export a theme; the MCP server exposes it as export_theme (tools 0.5.0).
  • EntityContainer and EmbeddedEntity join the published schemas, so generated clients type the export's body.

0.12.0 — September 2026

Assets by role, recipe slots as identity. Breaking in two places; the rest is additive.

  • AssetRecord.files — the asset's stored bytes as attachments keyed by role: mesh for a mesh asset, one map per channel for a material (albedo, normal, roughness, height, metallic, ao, emission, opacity, mask), texture for a texture asset. The record also carries what its type holds: format/resolution (texture), shader_name/shader_parameters/texture_refs (material), meshes/materials/textures (mesh). attachment stays on texture records, deprecated, for exports made before this version.
  • download_asset_file is GET /v1/assets/{id}/files/{role} and takes ?sha256=: with a digest it serves those bytes while they are retained, not the asset's current binding. Breaking: AssetOut.files is now the record's map by role; the presigned list moved to stored_files (with media_type, sha256, size_bytes). Migration: read download URLs from stored_files, roles from files.
  • link_recipe_asset requires slot. A slot holds one asset (409 when filled); one asset may fill several slots. New unlink_recipe_slot (DELETE /v1/recipes/{id}/slots/{slot}) empties one slot. Breaking: create_recipe takes assets (slot → asset id) instead of asset_ids. Migration: name the operator slot for every asset you bind.
  • ThemeStyle — the style profile under a theme's metadata.style, published as a schema and validated on write. Creates and updates accept metadata. New recipe type scatter_props and design type scatter-props; DesignTypeOut.hda_operator is nullable.

0.11.0 — September 2026

Stable asset files and the shared reference shapes. One schema rename; otherwise additive.

  • download_asset_file — GET /v1/assets/{id}/files/{filename} answers 307 to a short-lived presigned URL, like download_scene_artifact does for artifacts: the stable form of an attachment's uri in an exported entity container. The route never expires; the URL it redirects to does.
  • EntityReference is now Reference, and Attachment is scenebrew-formats' own model, so the API and the .sbe container share one definition of both shapes. Same keys, same constraints; only the schema name moved. Migration: rename the one generated type.

0.10.0 — September 2026

Library records — the entity container payloads. Additive.

  • Records. ThemeRecord, DesignRecord, RecipeRecord and AssetRecord are what a library entity is, independent of the cloud: the payload a Scenebrew entity container embeds. The responses ThemeOut, DesignOut, RecipeOut, AssetOut are each a record plus the server-only fields (id, slug, project_id, thumbnail_url, created_at, updated_at).
  • Theme: world (the constraints-first world block), scene_parameters keyed by planning module, designs as ordered references. Design: recipes as ordered references. Recipe: operator, operator_version, assets keyed by operator slot. Asset: attachment.
  • Inputs: create_theme / update_theme accept world and scene_parameters; create_recipe / update_recipe accept operator_version; link_recipe_asset accepts slot.

0.9.1 — September 2026

Wording only. The delete operations now say what deletion does: a deleted project or scene is hidden at once and purged — rows, stored artifacts, uploaded files and conversation transcripts — 30 days later, and a Scenebrew user can restore it from the app's trash until then. No shape, status or field changed.

0.9.0 — September 2026

Artifact-format and validation follow-up. Breaking for the artifact kind enum; the rest is additive or a stricter upload check.

  • tilemap is no longer an artifact kind. A tilemap is never a standalone artifact — it rides inside the blueprint swfbpx package, alongside heightmaps and shapes. ?kind=tilemap and GET …/artifacts/tilemap now return 422/404. Migration: read the blueprint; the tilemap is inside it.
  • download_expires_at (RFC 3339) is added next to download_expires_in on every presigned download — scene artifacts, files, asset files and recipe previews — the absolute instant the URL stops working.
  • Upload validation. The sdd is open-ended (an AI reads it): only UTF-8 is required, plus that every image it references is embedded inline as a data: URI (SDD_IMAGE_NOT_CONTAINED otherwise). The peg is fully schema-validated, and the blueprint swfbpx is schema- and integrity-validated, on upload — invalid documents answer 400 INVALID_ARTIFACT before anything is stored.

0.8.0 — September 2026

The full developer surface: one name per action across REST, SDK and MCP; everything slow is an operation; cursor pagination; files as a resource; the library. Old names are gone — there are no aliases.

  • Steps are named after the tool that runs them: create_sdd → generate_scene_sdd, build_peg → generate_scene_peg, generate_layout → generate_scene_blueprint, brew_scene → generate_scene_model. Artifact kind glb → model. Declared but not yet available (501 not_implemented): revise_scene_sdd, revise_scene_peg, analyze_scene_image, decorate_scene.
  • Operations: GET /v1/scenes/{id}/steps/{step_id} and GET /v1/sessions/{id}/turns/{turn_id} are replaced by GET /v1/operations/{id} (one resource for scene steps, session turns and library generations; statuses queued | running | canceling | succeeded | failed | canceled), GET /v1/operations?target_id= (history) and POST /v1/operations/{id}/cancel. Every write that starts work answers 202 with the operation and honours Prefer: wait=N (N ≤ 60): 200 with the finished operation when it completes in time.
  • Pagination is limit/cursor with next_cursor everywhere (page/page_size are gone); transcripts page with before/after message ids, newest first, and carry operation_id.
  • Sessions: POST /v1/projects/{id}/sessions requires text — a session is born with its first message and returns initial_turn. Added PATCH/DELETE /v1/sessions/{id}, POST /v1/sessions/{id}/context, DELETE /v1/sessions/{id}/context/{kind}/{entity_id}; messages take file_ids.
  • Files and artifacts: POST /v1/files (many files per request, 100 MB) and GET /v1/files/{id}; scenes take theme_id and source_file_id at create; DELETE /v1/scenes/{id}; GET /v1/scenes/{id}/sessions; GET /v1/scenes/{id}/artifacts/{kind} (?inline for SDD/PEG text), GET …/artifacts/{kind}/content (307 to the bytes) and PUT /v1/scenes/{id}/artifacts/{kind} to bring your own SDD, PEG or blueprint.
  • Projects, credits, models: POST /v1/projects, GET/PATCH/DELETE /v1/projects/{id}, GET /v1/me/credits and GET /v1/models (model is accepted on AI steps, sessions and generations).
  • Library: /v1/projects/{id}/{themes,designs,recipes,assets} (list, create) and /v1/{themes,designs,recipes,assets}/{id} (get, update, delete), the three membership links, GET /v1/design-types, GET /v1/recipe-types, POST /v1/recipes/{id}/preview and POST /v1/projects/{id}/generations (one contract for all four kinds; asset runs today).
  • MCP tools 0.2.0 at mcp.scenebrew.com/v1/mcp: the same names as tools, a library toolset via ?toolsets=, every operation-backed tool takes wait.

Migration from 0.7.0: rename the four step values and the three tool names, read kind: model where glb was read, poll GET /v1/operations/{id} instead of the step/turn paths, page with limit/cursor, and give POST /v1/projects/{id}/sessions a text. Prefer: wait=N replaces any implicit hold a client relied on.

0.7.0 — September 2026

Layout and brew became steps, not synchronous calls: a brew of a real scene runs for minutes, longer than a request should stay open.

  • POST /v1/scenes/{id}/layout and POST /v1/scenes/{id}/brew were removed. Both ran as POST /v1/scenes/{id}/steps (generate_layout, brew_scene; 202) and were polled like the AI steps. Preconditions 409 MISSING_PEG / MISSING_BLUEPRINT; failures layout_failed, brew_failed, runner_unavailable. The procedural steps stayed free.

0.6.0 — September 2026

AI work became keyed by scene, not by session.

  • POST /v1/sessions/{id}/turns (step runs) was removed; AI steps ran as POST /v1/scenes/{id}/steps on a scene created with the new POST /v1/projects/{id}/scenes.
  • A session carried context — the scenes and library entities it refers to — instead of a scene_id; a turn described a posted message (POST /v1/sessions/{id}/messages).
  • Added GET /v1/projects/{id}/sessions and GET /v1/sessions/{id}/messages.

0.5.0 — September 2026

The first write surface: sessions, turns, layout, brew, scene updates, the write scope, and the MCP server at mcp.scenebrew.com/v1/mcp.

0.4.0 — September 2026

  • size_bytes declared int64 on artifacts.
  • Contract version now equals the API's info.version.

0.3.0 — September 2026

  • Description-only changes.

0.2.0 — August 2026

  • Scopes enforced: read required on the data operations, 403 with WWW-Authenticate: Bearer error="insufficient_scope" otherwise. GET /v1/me stays scope-free.

0.1.0 — August 2026

Initial public API: GET /v1/me, GET /v1/projects, GET /v1/projects/{project_id}/scenes, GET /v1/scenes/{scene_id}/artifacts with presigned downloads; API keys in the app; problem+json errors.

On this page