{"openapi":"3.2.0","info":{"title":"Scenebrew API","description":"The Scenebrew public developer API. Authenticate every request with a first-party API key: `Authorization: Bearer sbk_live_…`.","version":"0.17.0"},"servers":[{"url":"https://api.scenebrew.com"}],"paths":{"/v1/me":{"get":{"tags":["identity"],"summary":"Get Me","description":"Who the presented API key acts as.","operationId":"get_me","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MeResponse"}}}},"default":{"$ref":"#/components/responses/Problem"}},"security":[{"apiKey":[]}]}},"/v1/me/credits":{"get":{"tags":["identity"],"summary":"Get Credits","description":"The tenant's credit balance and its most recent ledger entries, so a\ncaller can assert what an operation cost. Requires the `read` scope.","operationId":"get_credits","security":[{"apiKey":[]}],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"Ledger entries to include","default":20,"title":"Limit"},"description":"Ledger entries to include"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreditsOut"}}}},"default":{"$ref":"#/components/responses/Problem"}}}},"/v1/models":{"get":{"tags":["identity"],"summary":"List Models","description":"The models this tenant may pick — the same list the web UI offers:\nScenebrew's default (credits) and the vendors the tenant stored keys for\n(BYOK). Their ids are what `model` arguments accept. Requires the `read`\nscope.","operationId":"list_models","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ModelsOut"}}}},"default":{"$ref":"#/components/responses/Problem"}},"security":[{"apiKey":[]}]}},"/v1/projects":{"get":{"tags":["projects"],"summary":"List Projects","description":"The tenant's active projects the key's user can see. Requires the `read` scope.","operationId":"list_projects","security":[{"apiKey":[]}],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"Items per page","default":20,"title":"Limit"},"description":"Items per page"},{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"description":"The `next_cursor` of the previous page; omit for the first page.","title":"Cursor"},"description":"The `next_cursor` of the previous page; omit for the first page."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CursorPage_ProjectOut_"}}}},"default":{"$ref":"#/components/responses/Problem"}}},"post":{"tags":["projects"],"summary":"Create Project","description":"Create a project owned by the key's user. Plan quotas apply as in the\napp (402 when exhausted). Requires the `write` scope.","operationId":"create_project","security":[{"apiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectCreateIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectDetailOut"}}}},"default":{"$ref":"#/components/responses/Problem"}}}},"/v1/projects/{project_id}":{"get":{"tags":["projects"],"summary":"Get Project","description":"One project with its counts. Requires the `read` scope.","operationId":"get_project","security":[{"apiKey":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Project Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectDetailOut"}}}},"default":{"$ref":"#/components/responses/Problem"}}},"patch":{"tags":["projects"],"summary":"Update Project","description":"Rename, re-describe, archive or unarchive. Requires the `write` scope.","operationId":"update_project","security":[{"apiKey":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Project Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectUpdateIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectDetailOut"}}}},"default":{"$ref":"#/components/responses/Problem"}}},"delete":{"tags":["projects"],"summary":"Delete Project","description":"Delete the project. It and everything in it are hidden at once and\npurged — rows, stored artifacts, uploaded files and conversation\ntranscripts — 30 days later; until then a Scenebrew user can restore it\nfrom the app's trash. The app's rule stands: the last active project\ncannot be deleted (409). Requires the `write` scope.","operationId":"delete_project","security":[{"apiKey":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Project Id"}}],"responses":{"204":{"description":"Successful Response"},"default":{"$ref":"#/components/responses/Problem"}}}},"/v1/files":{"post":{"tags":["files"],"summary":"Upload Files","description":"Upload files once and reference them by id afterwards — a scene's\nsource model, an asset's files, a message's attachments. Unreferenced\nfiles expire after 24 hours. Requires the `write` scope.","operationId":"upload_files","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_upload_files"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FilesOut"}}}},"default":{"$ref":"#/components/responses/Problem"}},"security":[{"apiKey":[]}]}},"/v1/files/{file_id}":{"get":{"tags":["files"],"summary":"Get File","description":"One uploaded file with a fresh short-lived download URL. Requires the `read` scope.","operationId":"get_file","security":[{"apiKey":[]}],"parameters":[{"name":"file_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"File Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FileOut"}}}},"default":{"$ref":"#/components/responses/Problem"}}}},"/v1/projects/{project_id}/scenes":{"get":{"tags":["scenes"],"summary":"List Scenes","description":"The project's scenes; 404 when the project is not visible to the key.\nRequires the `read` scope.","operationId":"list_scenes","security":[{"apiKey":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Project Id"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"Items per page","default":20,"title":"Limit"},"description":"Items per page"},{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"description":"The `next_cursor` of the previous page; omit for the first page.","title":"Cursor"},"description":"The `next_cursor` of the previous page; omit for the first page."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CursorPage_SceneOut_"}}}},"default":{"$ref":"#/components/responses/Problem"}}},"post":{"tags":["scenes"],"summary":"Create Scene","description":"Create a scene in a project — the container for everything the\npipeline produces. Every scene has a library theme of the project\n(`theme_id`, required; 404 `theme_not_found` for any other). Run the\n`generate_scene_*` steps against it, or bring your own SDD and PEG with\n`upload_scene_artifact`. Requires the `write` scope.","operationId":"create_scene","security":[{"apiKey":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Project Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SceneCreateIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SceneOut"}}}},"default":{"$ref":"#/components/responses/Problem"}}}},"/v1/scenes/{scene_id}":{"get":{"tags":["scenes"],"summary":"Get Scene","description":"One scene with its current artifacts (presigned). Requires the `read` scope.","operationId":"get_scene","security":[{"apiKey":[]}],"parameters":[{"name":"scene_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Scene Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SceneDetailOut"}}}},"default":{"$ref":"#/components/responses/Problem"}}},"patch":{"tags":["scenes"],"summary":"Update Scene","description":"Rename, re-describe or re-theme a scene. Only the fields sent change;\na scene keeps a theme, so `theme_id: null` is a 400 `theme_required`.\nRequires the `write` scope.","operationId":"update_scene","security":[{"apiKey":[]}],"parameters":[{"name":"scene_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Scene Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SceneUpdateIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SceneOut"}}}},"default":{"$ref":"#/components/responses/Problem"}}},"delete":{"tags":["scenes"],"summary":"Delete Scene","description":"Delete the scene: hidden at once, purged with its artifacts after 30\ndays. A step still running on it is asked to stop. Requires the `write`\nscope.","operationId":"delete_scene","security":[{"apiKey":[]}],"parameters":[{"name":"scene_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Scene Id"}}],"responses":{"204":{"description":"Successful Response"},"default":{"$ref":"#/components/responses/Problem"}}}},"/v1/scenes/{scene_id}/sessions":{"get":{"tags":["scenes"],"summary":"List Scene Sessions","description":"The conversations that refer to this scene. Requires the `read` scope.","operationId":"list_scene_sessions","security":[{"apiKey":[]}],"parameters":[{"name":"scene_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Scene Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/SceneSessionOut"},"title":"Response List Scene Sessions"}}}},"default":{"$ref":"#/components/responses/Problem"}}}},"/v1/scenes/{scene_id}/artifacts":{"get":{"tags":["scenes"],"summary":"List Scene Artifacts","description":"The scene's artifacts — current versions unless `all_versions` — each\nwith a short-lived presigned download URL. The model's URL serves the\nvariant `materials` / `meshes` ask for — self-contained by default; a\nvariant is produced on its first request, which can take a while, and\nstored. Requires the `read` scope.","operationId":"list_scene_artifacts","security":[{"apiKey":[]}],"parameters":[{"name":"scene_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Scene Id"}},{"name":"kind","in":"query","required":false,"schema":{"anyOf":[{"enum":["sdd","peg","blueprint","model","layout_preview","thumbnail"],"type":"string"},{"type":"null"}],"description":"Only this kind.","title":"Kind"},"description":"Only this kind."},{"name":"all_versions","in":"query","required":false,"schema":{"type":"boolean","description":"Every version, not only the current one of each kind.","default":false,"title":"All Versions"},"description":"Every version, not only the current one of each kind."},{"name":"materials","in":"query","required":false,"schema":{"enum":["reference","embed"],"type":"string","description":"The model only: its materials `embed`ded with their maps (default — a self-contained file) or by `reference` (thin materials naming the library material, resolved with POST /v1/projects/{project_id}/assets/resolve).","default":"embed","title":"Materials"},"description":"The model only: its materials `embed`ded with their maps (default — a self-contained file) or by `reference` (thin materials naming the library material, resolved with POST /v1/projects/{project_id}/assets/resolve)."},{"name":"meshes","in":"query","required":false,"schema":{"enum":["reference","embed"],"type":"string","description":"The model only: its library meshes `embed`ded (default) or by `reference` (instance nodes naming the mesh asset).","default":"embed","title":"Meshes"},"description":"The model only: its library meshes `embed`ded (default) or by `reference` (instance nodes naming the mesh asset)."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SceneArtifactsResponse"}}}},"default":{"$ref":"#/components/responses/Problem"}}}},"/v1/scenes/{scene_id}/artifacts/{kind}":{"get":{"tags":["scenes"],"summary":"Get Scene Artifact","description":"One artifact: the current version, or `version`. With `inline`, the\nSDD or PEG text travels in the record — what a host agent wants to read.\nThe model comes in the variant `materials` / `meshes` ask for, as in\n`list_scene_artifacts`. Requires the `read` scope.","operationId":"get_scene_artifact","security":[{"apiKey":[]}],"parameters":[{"name":"scene_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Scene Id"}},{"name":"kind","in":"path","required":true,"schema":{"enum":["sdd","peg","blueprint","model","layout_preview","thumbnail"],"type":"string","title":"Kind"}},{"name":"version","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","minimum":1},{"type":"null"}],"description":"A specific version; the current one when omitted.","title":"Version"},"description":"A specific version; the current one when omitted."},{"name":"inline","in":"query","required":false,"schema":{"type":"boolean","description":"Include the text of an SDD or PEG in `content`.","default":false,"title":"Inline"},"description":"Include the text of an SDD or PEG in `content`."},{"name":"materials","in":"query","required":false,"schema":{"enum":["reference","embed"],"type":"string","description":"The model only: its materials `embed`ded with their maps (default — a self-contained file) or by `reference` (thin materials naming the library material, resolved with POST /v1/projects/{project_id}/assets/resolve).","default":"embed","title":"Materials"},"description":"The model only: its materials `embed`ded with their maps (default — a self-contained file) or by `reference` (thin materials naming the library material, resolved with POST /v1/projects/{project_id}/assets/resolve)."},{"name":"meshes","in":"query","required":false,"schema":{"enum":["reference","embed"],"type":"string","description":"The model only: its library meshes `embed`ded (default) or by `reference` (instance nodes naming the mesh asset).","default":"embed","title":"Meshes"},"description":"The model only: its library meshes `embed`ded (default) or by `reference` (instance nodes naming the mesh asset)."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SceneArtifactDetailOut"}}}},"default":{"$ref":"#/components/responses/Problem"}}},"put":{"tags":["scenes"],"summary":"Upload Scene Artifact","description":"Bring your own document: write a new version of the SDD (Markdown),\nPEG (JSON) or blueprint (swfbpx zip) from the request body, then run\nonly the free steps. Identical content is not a new version. Requires\nthe `write` scope.","operationId":"upload_scene_artifact","security":[{"apiKey":[]}],"parameters":[{"name":"scene_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Scene Id"}},{"name":"kind","in":"path","required":true,"schema":{"enum":["sdd","peg","blueprint"],"type":"string","title":"Kind"}}],"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SceneArtifactDetailOut"}}}},"default":{"$ref":"#/components/responses/Problem"}},"requestBody":{"required":true,"content":{"text/markdown":{"schema":{"type":"string"}},"application/json":{"schema":{"type":"object"}},"application/zip":{"schema":{"type":"string","format":"binary"}}}}}},"/v1/scenes/{scene_id}/artifacts/{kind}/content":{"get":{"tags":["scenes"],"summary":"Download Scene Artifact","description":"The artifact's bytes: a 307 to a short-lived presigned URL — for the\nmodel, of the variant `materials` / `meshes` ask for. Requires the `read`\nscope.","operationId":"download_scene_artifact","security":[{"apiKey":[]}],"parameters":[{"name":"scene_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Scene Id"}},{"name":"kind","in":"path","required":true,"schema":{"enum":["sdd","peg","blueprint","model","layout_preview","thumbnail"],"type":"string","title":"Kind"}},{"name":"version","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","minimum":1},{"type":"null"}],"title":"Version"}},{"name":"materials","in":"query","required":false,"schema":{"enum":["reference","embed"],"type":"string","description":"The model only: its materials `embed`ded with their maps (default — a self-contained file) or by `reference` (thin materials naming the library material, resolved with POST /v1/projects/{project_id}/assets/resolve).","default":"embed","title":"Materials"},"description":"The model only: its materials `embed`ded with their maps (default — a self-contained file) or by `reference` (thin materials naming the library material, resolved with POST /v1/projects/{project_id}/assets/resolve)."},{"name":"meshes","in":"query","required":false,"schema":{"enum":["reference","embed"],"type":"string","description":"The model only: its library meshes `embed`ded (default) or by `reference` (instance nodes naming the mesh asset).","default":"embed","title":"Meshes"},"description":"The model only: its library meshes `embed`ded (default) or by `reference` (instance nodes naming the mesh asset)."}],"responses":{"307":{"description":"Redirect to the presigned artifact bytes."},"default":{"$ref":"#/components/responses/Problem"}}}},"/v1/scenes/{scene_id}/steps":{"post":{"tags":["scenes"],"summary":"Run Scene Step","description":"Run one step on the scene as an Operation (202 + `Location`).\n\n`generate_scene_sdd` writes the Scene Design Document from `brief`;\n`generate_scene_peg` builds the Player Experience Graph from the current\nSDD (409 `missing_sdd`); `generate_scene_blueprint` turns the current PEG\ninto a blueprint (the swfbpx package) and a layout preview (409 `missing_peg`);\n`generate_scene_model` cooks the current blueprint into the model (409\n`missing_blueprint`). Rerunning a step versions its artifact. The AI\nsteps deduct credits once they complete; the procedural steps are free.\nOne step at a time per scene (409 `step_in_progress`). `Prefer: wait=N`\nholds the response. Requires the `write` scope.","operationId":"run_scene_step","security":[{"apiKey":[]}],"parameters":[{"name":"scene_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Scene Id"}},{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string","minLength":1,"maxLength":200},{"type":"null"}],"description":"Optional. Repeating a request with the same key returns what it already created (200) instead of running it again.","title":"Idempotency-Key"},"description":"Optional. Repeating a request with the same key returns what it already created (200) instead of running it again."},{"name":"Prefer","in":"header","required":false,"schema":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"description":"RFC 7240. `wait=N` (N ≤ 60) holds the response until the operation is terminal or N seconds passed: 200 with the finished operation, or the same 202 as without it. `respond-async` (the default) returns the queued operation at once.","title":"Prefer"},"description":"RFC 7240. `wait=N` (N ≤ 60) holds the response until the operation is terminal or N seconds passed: 200 with the finished operation, or the same 202 as without it. `respond-async` (the default) returns the queued operation at once."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SceneStepCreateIn"}}}},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OperationOut"}}}},"200":{"description":"The operation finished within `Prefer: wait`, or the Idempotency-Key replayed an operation that already exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OperationOut"}}}},"default":{"$ref":"#/components/responses/Problem"}}}},"/v1/projects/{project_id}/sessions":{"get":{"tags":["sessions"],"summary":"List Sessions","description":"The project's sessions — the designers' conversations — pinned first,\nthen most recently active, each with the entities it refers to.\nRequires the `read` scope.","operationId":"list_sessions","security":[{"apiKey":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Project Id"}},{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"enum":["active","archived"],"type":"string"},{"type":"null"}],"description":"Only this status.","title":"Status"},"description":"Only this status."},{"name":"q","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"description":"Title search.","title":"Q"},"description":"Title search."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"Items per page","default":20,"title":"Limit"},"description":"Items per page"},{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"description":"The `next_cursor` of the previous page; omit for the first page.","title":"Cursor"},"description":"The `next_cursor` of the previous page; omit for the first page."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CursorPage_SessionOut_"}}}},"default":{"$ref":"#/components/responses/Problem"}}},"post":{"tags":["sessions"],"summary":"Create Session","description":"Open a conversation with its first message. The context named in the\nrequest is attached before the agent runs; the reply arrives on the\nreturned `initial_turn` operation, which `Prefer: wait=N` waits for. If\nthat turn fails the session and the message stay — retry with\n`send_session_message`. Requires the `write` scope.","operationId":"create_session","security":[{"apiKey":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Project Id"}},{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string","minLength":1,"maxLength":200},{"type":"null"}],"description":"Optional. Repeating a request with the same key returns what it already created (200) instead of running it again.","title":"Idempotency-Key"},"description":"Optional. Repeating a request with the same key returns what it already created (200) instead of running it again."},{"name":"Prefer","in":"header","required":false,"schema":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"description":"RFC 7240. `wait=N` (N ≤ 60) holds the response until the operation is terminal or N seconds passed: 200 with the finished operation, or the same 202 as without it. `respond-async` (the default) returns the queued operation at once.","title":"Prefer"},"description":"RFC 7240. `wait=N` (N ≤ 60) holds the response until the operation is terminal or N seconds passed: 200 with the finished operation, or the same 202 as without it. `respond-async` (the default) returns the queued operation at once."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionCreateIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionCreatedOut"}}}},"default":{"$ref":"#/components/responses/Problem"}}}},"/v1/sessions/{session_id}":{"get":{"tags":["sessions"],"summary":"Get Session","description":"The session with its context — the scenes and library entities it\nrefers to. Requires the `read` scope.","operationId":"get_session","security":[{"apiKey":[]}],"parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Session Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionOut"}}}},"default":{"$ref":"#/components/responses/Problem"}}},"patch":{"tags":["sessions"],"summary":"Update Session","description":"Rename, pin, archive, or switch the model the next turns run on.\nRequires the `write` scope.","operationId":"update_session","security":[{"apiKey":[]}],"parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Session Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionUpdateIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionOut"}}}},"default":{"$ref":"#/components/responses/Problem"}}},"delete":{"tags":["sessions"],"summary":"Delete Session","description":"Delete the conversation: hidden at once, its transcript purged after\n30 days; a running turn is asked to stop first. Scenes and artifacts it\nproduced survive. Requires the `write` scope.","operationId":"delete_session","security":[{"apiKey":[]}],"parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Session Id"}}],"responses":{"204":{"description":"Successful Response"},"default":{"$ref":"#/components/responses/Problem"}}}},"/v1/sessions/{session_id}/messages":{"get":{"tags":["sessions"],"summary":"List Session Messages","description":"A page of the conversation, newest first, as the app shows it.\n`next_cursor` is the id to pass as `before` for the next page. Requires\nthe `read` scope.","operationId":"list_session_messages","security":[{"apiKey":[]}],"parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Session Id"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}},{"name":"before","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Only messages older than this message id.","title":"Before"},"description":"Only messages older than this message id."},{"name":"after","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Only messages newer than this message id.","title":"After"},"description":"Only messages newer than this message id."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionMessagesOut"}}}},"default":{"$ref":"#/components/responses/Problem"}}},"post":{"tags":["sessions"],"summary":"Send Session Message","description":"Post a message in the key's user's name and run one agent turn on it,\nas an Operation (202 + `Location`). The agent answers as it would in the\napp — reading the session's context, running tools, writing artifacts to\nthe scenes it touches — and the turn is billed like a web turn. One turn\nat a time per session (409 `turn_in_progress`). `Prefer: wait=N` holds\nthe response; `result.reply` then carries the answer. Requires the\n`write` scope.","operationId":"send_session_message","security":[{"apiKey":[]}],"parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Session Id"}},{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string","minLength":1,"maxLength":200},{"type":"null"}],"description":"Optional. Repeating a request with the same key returns what it already created (200) instead of running it again.","title":"Idempotency-Key"},"description":"Optional. Repeating a request with the same key returns what it already created (200) instead of running it again."},{"name":"Prefer","in":"header","required":false,"schema":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"description":"RFC 7240. `wait=N` (N ≤ 60) holds the response until the operation is terminal or N seconds passed: 200 with the finished operation, or the same 202 as without it. `respond-async` (the default) returns the queued operation at once.","title":"Prefer"},"description":"RFC 7240. `wait=N` (N ≤ 60) holds the response until the operation is terminal or N seconds passed: 200 with the finished operation, or the same 202 as without it. `respond-async` (the default) returns the queued operation at once."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageCreateIn"}}}},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OperationOut"}}}},"200":{"description":"The operation finished within `Prefer: wait`, or the Idempotency-Key replayed an operation that already exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OperationOut"}}}},"default":{"$ref":"#/components/responses/Problem"}}}},"/v1/sessions/{session_id}/context":{"post":{"tags":["sessions"],"summary":"Link Session Context","description":"Pull a scene, theme, design, recipe or asset into the conversation's\ncontext. Attaching twice is a 409. Requires the `write` scope.","operationId":"link_session_context","security":[{"apiKey":[]}],"parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Session Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionContextRefIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionContextItemOut"}}}},"default":{"$ref":"#/components/responses/Problem"}}}},"/v1/sessions/{session_id}/context/{kind}/{entity_id}":{"delete":{"tags":["sessions"],"summary":"Unlink Session Context","description":"Remove an entity from context, addressed by what it is. Requires the\n`write` scope.","operationId":"unlink_session_context","security":[{"apiKey":[]}],"parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Session Id"}},{"name":"kind","in":"path","required":true,"schema":{"enum":["scene","theme","design","recipe","asset"],"type":"string","title":"Kind"}},{"name":"entity_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Entity Id"}}],"responses":{"204":{"description":"Successful Response"},"default":{"$ref":"#/components/responses/Problem"}}}},"/v1/operations/{operation_id}":{"get":{"tags":["operations"],"summary":"Get Operation","description":"The operation's state; with `wait`, a bounded long-poll (≤ 60 s) that\nanswers as soon as it is terminal. Requires the `read` scope.","operationId":"get_operation","security":[{"apiKey":[]}],"parameters":[{"name":"operation_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Operation Id"}},{"name":"wait","in":"query","required":false,"schema":{"type":"integer","maximum":60,"minimum":0,"description":"Seconds to hold the request open waiting for a terminal state (bounded long-poll).","default":0,"title":"Wait"},"description":"Seconds to hold the request open waiting for a terminal state (bounded long-poll)."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OperationOut"}}}},"default":{"$ref":"#/components/responses/Problem"}}}},"/v1/operations":{"get":{"tags":["operations"],"summary":"List Operations","description":"The operations on one target, newest first: a scene's step history,\na session's turn history, a project's generations — receipts, not\ncontent. Requires the `read` scope.","operationId":"list_operations","security":[{"apiKey":[]}],"parameters":[{"name":"target_id","in":"query","required":true,"schema":{"type":"string","format":"uuid","description":"A scene, session or project id.","title":"Target Id"},"description":"A scene, session or project id."},{"name":"kind","in":"query","required":false,"schema":{"anyOf":[{"enum":["scene_step","session_turn","generation"],"type":"string"},{"type":"null"}],"title":"Kind"}},{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"enum":["queued","running","canceling","succeeded","failed","canceled"],"type":"string"},{"type":"null"}],"title":"Status"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"Items per page","default":20,"title":"Limit"},"description":"Items per page"},{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"description":"The `next_cursor` of the previous page; omit for the first page.","title":"Cursor"},"description":"The `next_cursor` of the previous page; omit for the first page."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CursorPage_OperationOut_"}}}},"default":{"$ref":"#/components/responses/Problem"}}}},"/v1/operations/{operation_id}/cancel":{"post":{"tags":["operations"],"summary":"Cancel Operation","description":"Ask the worker to stop: 202 with the operation in `canceling`; it ends\n`canceled` at the worker's next boundary. A turn keeps its partial reply\nand pays for the calls it made; a flat-priced step pays nothing. Cancel\non a terminal operation is a no-op 200. Asset generation cannot be\nstopped once started (409 `not_cancelable`). Requires the `write` scope.","operationId":"cancel_operation","security":[{"apiKey":[]}],"parameters":[{"name":"operation_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Operation Id"}}],"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OperationOut"}}}},"200":{"description":"The operation was already terminal; nothing changed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OperationOut"}}}},"default":{"$ref":"#/components/responses/Problem"}}}},"/v1/projects/{project_id}/themes":{"get":{"tags":["library"],"summary":"List Themes","description":"The project's themes, most recently changed first. Filters: q, tags. Requires the `read` scope.","operationId":"list_themes","security":[{"apiKey":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Project Id"}},{"name":"q","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"description":"Name search.","title":"Q"},"description":"Name search."},{"name":"tags","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Tags"}},{"name":"type","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Type"}},{"name":"category","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Category"}},{"name":"theme_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Theme Id"}},{"name":"design_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Design Id"}},{"name":"recipe_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Recipe Id"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"Items per page","default":20,"title":"Limit"},"description":"Items per page"},{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"description":"The `next_cursor` of the previous page; omit for the first page.","title":"Cursor"},"description":"The `next_cursor` of the previous page; omit for the first page."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CursorPage_ThemeOut_"}}}},"default":{"$ref":"#/components/responses/Problem"}}},"post":{"tags":["library"],"summary":"Create Theme","description":"Create a theme in the project. Membership ids given here are linked right after. Requires the `write` scope.","operationId":"create_theme","security":[{"apiKey":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Project Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ThemeCreateIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ThemeOut"}}}},"default":{"$ref":"#/components/responses/Problem"}}}},"/v1/themes/{entity_id}":{"get":{"tags":["library"],"summary":"Get Theme","description":"One theme with its memberships. Requires the `read` scope.","operationId":"get_theme","security":[{"apiKey":[]}],"parameters":[{"name":"entity_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Entity Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ThemeOut"}}}},"default":{"$ref":"#/components/responses/Problem"}}},"patch":{"tags":["library"],"summary":"Update Theme","description":"Change a theme; omitted fields stay. Requires the `write` scope.","operationId":"update_theme","security":[{"apiKey":[]}],"parameters":[{"name":"entity_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Entity Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LibraryUpdateIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ThemeOut"}}}},"default":{"$ref":"#/components/responses/Problem"}}},"delete":{"tags":["library"],"summary":"Delete Theme","description":"Delete a theme. Requires the `write` scope. A theme that scenes still use — trashed ones included — is a 409 `theme_in_use` naming `scene_count` and `trashed_scene_count`: delete those scenes first.","operationId":"delete_theme","security":[{"apiKey":[]}],"parameters":[{"name":"entity_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Entity Id"}}],"responses":{"204":{"description":"Successful Response"},"default":{"$ref":"#/components/responses/Problem"}}}},"/v1/projects/{project_id}/designs":{"get":{"tags":["library"],"summary":"List Designs","description":"The project's designs, most recently changed first. Filters: q, tags, type, category, theme_id. Requires the `read` scope.","operationId":"list_designs","security":[{"apiKey":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Project Id"}},{"name":"q","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"description":"Name search.","title":"Q"},"description":"Name search."},{"name":"tags","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Tags"}},{"name":"type","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Type"}},{"name":"category","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Category"}},{"name":"theme_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Theme Id"}},{"name":"design_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Design Id"}},{"name":"recipe_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Recipe Id"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"Items per page","default":20,"title":"Limit"},"description":"Items per page"},{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"description":"The `next_cursor` of the previous page; omit for the first page.","title":"Cursor"},"description":"The `next_cursor` of the previous page; omit for the first page."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CursorPage_DesignOut_"}}}},"default":{"$ref":"#/components/responses/Problem"}}},"post":{"tags":["library"],"summary":"Create Design","description":"Create a design in the project. Membership ids given here are linked right after. Requires the `write` scope.","operationId":"create_design","security":[{"apiKey":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Project Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DesignCreateIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DesignOut"}}}},"default":{"$ref":"#/components/responses/Problem"}}}},"/v1/designs/{entity_id}":{"get":{"tags":["library"],"summary":"Get Design","description":"One design with its memberships. Requires the `read` scope.","operationId":"get_design","security":[{"apiKey":[]}],"parameters":[{"name":"entity_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Entity Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DesignOut"}}}},"default":{"$ref":"#/components/responses/Problem"}}},"patch":{"tags":["library"],"summary":"Update Design","description":"Change a design; omitted fields stay. Requires the `write` scope.","operationId":"update_design","security":[{"apiKey":[]}],"parameters":[{"name":"entity_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Entity Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LibraryUpdateIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DesignOut"}}}},"default":{"$ref":"#/components/responses/Problem"}}},"delete":{"tags":["library"],"summary":"Delete Design","description":"Delete a design. Requires the `write` scope.","operationId":"delete_design","security":[{"apiKey":[]}],"parameters":[{"name":"entity_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Entity Id"}}],"responses":{"204":{"description":"Successful Response"},"default":{"$ref":"#/components/responses/Problem"}}}},"/v1/projects/{project_id}/recipes":{"get":{"tags":["library"],"summary":"List Recipes","description":"The project's recipes, most recently changed first. Filters: q, tags, type, category, design_id. Requires the `read` scope.","operationId":"list_recipes","security":[{"apiKey":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Project Id"}},{"name":"q","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"description":"Name search.","title":"Q"},"description":"Name search."},{"name":"tags","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Tags"}},{"name":"type","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Type"}},{"name":"category","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Category"}},{"name":"theme_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Theme Id"}},{"name":"design_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Design Id"}},{"name":"recipe_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Recipe Id"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"Items per page","default":20,"title":"Limit"},"description":"Items per page"},{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"description":"The `next_cursor` of the previous page; omit for the first page.","title":"Cursor"},"description":"The `next_cursor` of the previous page; omit for the first page."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CursorPage_RecipeOut_"}}}},"default":{"$ref":"#/components/responses/Problem"}}},"post":{"tags":["library"],"summary":"Create Recipe","description":"Create a recipe in the project. Membership ids given here are linked right after. Requires the `write` scope.","operationId":"create_recipe","security":[{"apiKey":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Project Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecipeCreateIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecipeOut"}}}},"default":{"$ref":"#/components/responses/Problem"}}}},"/v1/recipes/{entity_id}":{"get":{"tags":["library"],"summary":"Get Recipe","description":"One recipe with its memberships. Requires the `read` scope.","operationId":"get_recipe","security":[{"apiKey":[]}],"parameters":[{"name":"entity_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Entity Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecipeOut"}}}},"default":{"$ref":"#/components/responses/Problem"}}},"patch":{"tags":["library"],"summary":"Update Recipe","description":"Change a recipe; omitted fields stay. Requires the `write` scope.","operationId":"update_recipe","security":[{"apiKey":[]}],"parameters":[{"name":"entity_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Entity Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LibraryUpdateIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecipeOut"}}}},"default":{"$ref":"#/components/responses/Problem"}}},"delete":{"tags":["library"],"summary":"Delete Recipe","description":"Delete a recipe. Requires the `write` scope.","operationId":"delete_recipe","security":[{"apiKey":[]}],"parameters":[{"name":"entity_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Entity Id"}}],"responses":{"204":{"description":"Successful Response"},"default":{"$ref":"#/components/responses/Problem"}}}},"/v1/projects/{project_id}/assets":{"get":{"tags":["library"],"summary":"List Assets","description":"The project's assets, most recently changed first. Filters: q, tags, type, category, recipe_id. Requires the `read` scope.","operationId":"list_assets","security":[{"apiKey":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Project Id"}},{"name":"q","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"description":"Name search.","title":"Q"},"description":"Name search."},{"name":"tags","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Tags"}},{"name":"type","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Type"}},{"name":"category","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Category"}},{"name":"theme_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Theme Id"}},{"name":"design_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Design Id"}},{"name":"recipe_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Recipe Id"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"Items per page","default":20,"title":"Limit"},"description":"Items per page"},{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"description":"The `next_cursor` of the previous page; omit for the first page.","title":"Cursor"},"description":"The `next_cursor` of the previous page; omit for the first page."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CursorPage_AssetOut_"}}}},"default":{"$ref":"#/components/responses/Problem"}}},"post":{"tags":["library"],"summary":"Create Asset","description":"Create a asset in the project. Membership ids given here are linked right after. Requires the `write` scope.","operationId":"create_asset","security":[{"apiKey":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Project Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssetCreateIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssetOut"}}}},"default":{"$ref":"#/components/responses/Problem"}}}},"/v1/assets/{entity_id}":{"get":{"tags":["library"],"summary":"Get Asset","description":"One asset with its memberships. Requires the `read` scope.","operationId":"get_asset","security":[{"apiKey":[]}],"parameters":[{"name":"entity_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Entity Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssetOut"}}}},"default":{"$ref":"#/components/responses/Problem"}}},"patch":{"tags":["library"],"summary":"Update Asset","description":"Change a asset; omitted fields stay. Requires the `write` scope.","operationId":"update_asset","security":[{"apiKey":[]}],"parameters":[{"name":"entity_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Entity Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LibraryUpdateIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssetOut"}}}},"default":{"$ref":"#/components/responses/Problem"}}},"delete":{"tags":["library"],"summary":"Delete Asset","description":"Delete a asset. Requires the `write` scope.","operationId":"delete_asset","security":[{"apiKey":[]}],"parameters":[{"name":"entity_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Entity Id"}}],"responses":{"204":{"description":"Successful Response"},"default":{"$ref":"#/components/responses/Problem"}}}},"/v1/assets/{asset_id}/files/{role}":{"get":{"tags":["library"],"summary":"Download Asset File","description":"One of the asset's stored files by role (`files` on `get_asset`: mesh,\ntexture, albedo, normal, …): a 307 to a short-lived presigned URL. With\n`sha256` this is the digest-addressed form an exported entity container\ncarries as an attachment's `uri` — it keeps resolving after the file was\nreplaced, and never expires itself; the URL it redirects to does. A stored\nfilename (`texture.png`) is accepted in place of the role for exports made\nbefore roles existed. Requires the `read` scope.","operationId":"download_asset_file","security":[{"apiKey":[]}],"parameters":[{"name":"asset_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Asset Id"}},{"name":"role","in":"path","required":true,"schema":{"type":"string","title":"Role"}},{"name":"sha256","in":"query","required":false,"schema":{"anyOf":[{"type":"string","pattern":"^[0-9a-f]{64}$"},{"type":"null"}],"description":"The digest of the bytes wanted. Served while those bytes are retained, even after the asset's file was replaced; omitted, the current file.","title":"Sha256"},"description":"The digest of the bytes wanted. Served while those bytes are retained, even after the asset's file was replaced; omitted, the current file."}],"responses":{"307":{"description":"Redirect to the presigned file bytes."},"default":{"$ref":"#/components/responses/Problem"}}},"put":{"tags":["library"],"summary":"Replace Asset File","description":"Replace the bytes of a filled role deliberately, even when recipes and\nthemes use the asset. `If-Match` must name the digest the role holds\nnow (`412` `precondition_failed` with `current_sha256` when it does not,\n`428` without the header, `412` on an empty role — fill that with\n`add_asset_file`), so a caller replaces what it looked at and never\nwhat someone else put there in between. The same bytes again are a\nno-op `200`. The replaced digest keeps resolving through\n`download_asset_file?sha256=` for the retention period, so exports made\nbefore still work; it leaves the workspace's storage usage now.\nRequires the `write` scope.","operationId":"replace_asset_file","security":[{"apiKey":[]}],"parameters":[{"name":"asset_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Asset Id"}},{"name":"role","in":"path","required":true,"schema":{"type":"string","description":"`mesh` on a mesh asset, `texture` on a texture asset, a channel role (`albedo`, `normal`, `roughness`, `height`, `metallic`, `ao`, `emission`, `opacity`, `mask`) on a material","title":"Role"},"description":"`mesh` on a mesh asset, `texture` on a texture asset, a channel role (`albedo`, `normal`, `roughness`, `height`, `metallic`, `ao`, `emission`, `opacity`, `mask`) on a material"},{"name":"If-Match","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"The digest the role holds now — `files[role].sha256` of the asset you looked at, quoted or bare. Required: a stale value answers `412`, a missing one `428`.","title":"If-Match"},"description":"The digest the role holds now — `files[role].sha256` of the asset you looked at, quoted or bare. Required: a stale value answers `412`, a missing one `428`."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssetFileReplaceIn"}}}},"responses":{"200":{"description":"The role holds the new bytes (or already held them).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssetOut"}}},"headers":{"ETag":{"description":"The role's digest now, quoted.","schema":{"type":"string"}}}},"default":{"$ref":"#/components/responses/Problem"}}}},"/v1/projects/{project_id}/assets/resolve":{"post":{"tags":["library"],"summary":"Resolve Assets","description":"Many assets of the project in one call — what a renderer needs to draw\na scene model whose materials are references (`extras.scenebrew.asset`):\neach material's `fallback_color` and `normal_convention` and its maps by\nrole (`albedo`, `normal`, `ao`, …), every map addressed by digest so the\nbytes are cached for good. Ids that are not assets of this project come\nback `not_found` in their place; the call never fails for one of them.\nRequires the `read` scope.","operationId":"resolve_assets","security":[{"apiKey":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Project Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssetResolveIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssetResolveOut"}}}},"default":{"$ref":"#/components/responses/Problem"}}}},"/v1/assets/{asset_id}/files":{"post":{"tags":["library"],"summary":"Add Asset File","description":"Fill an empty file role of an existing asset from an uploaded file\n(`POST /v1/files`), through the same ingest as `create_asset` (digest,\ndeduplicated storage, quota). The role names what the file is for:\n`mesh` on a mesh asset, `texture` on a texture asset, a channel role\n(`albedo`, `normal`, `roughness`, `height`, `metallic`, `ao`, `emission`,\n`opacity`, `mask`) on a material. Works whether or not a recipe already\nreferences the asset. The same bytes again answer `200` with the\nunchanged digest. A role that holds *different* bytes is never\nreplaced here: `409` `role_filled` names the recipes (with their slots)\nand themes using the asset under `consumers` — replace deliberately\nwith `replace_asset_file` and `If-Match`, or create a new asset and\nrebind the slots that should use it. Of two concurrent fills with\ndifferent bytes exactly one succeeds. Requires the `write` scope.","operationId":"add_asset_file","security":[{"apiKey":[]}],"parameters":[{"name":"asset_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Asset Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssetFileAddIn"}}}},"responses":{"201":{"description":"The role was empty and now holds the file.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssetOut"}}},"headers":{"ETag":{"description":"The role's digest (`files[role].sha256`), quoted.","schema":{"type":"string"}}}},"200":{"description":"The role already held exactly these bytes; nothing changed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssetOut"}}}},"default":{"$ref":"#/components/responses/Problem"}}}},"/v1/themes/{theme_id}/export":{"get":{"tags":["library"],"summary":"Export Theme","description":"The theme and everything reachable from it — its designs, their\nrecipes, the assets those slot and the assets *those* reference — as one\nself-contained Scenebrew entity container (`.sbe`, JSON), the file a\nUnity project or the standalone Architect imports. Each asset's bytes\nride inline or as an attachment whose `uri` is this API's\n`download_asset_file` route by digest (`/v1/assets/{id}/files/{role}?sha256=`),\nwhich keeps resolving after the asset's file is replaced; `attachments`\ndecides which. `X-Scenebrew-Content-Hash` is the container's hash, the\nsame in every mode. Bytes are exactly what the library wrote — hash the\nbody to verify. A theme in another project is a 404. Requires the `read`\nscope.","operationId":"export_theme","security":[{"apiKey":[]}],"parameters":[{"name":"theme_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Theme Id"}},{"name":"attachments","in":"query","required":false,"schema":{"enum":["full","by-size","by-role","reference"],"type":"string","description":"How asset bytes travel: `full` (every attachment inline), `by-size` (inline up to the server's threshold, else by digest URI), `by-role` (inline only the `roles` and `slots` named), `reference` (never bytes — URIs only).","default":"by-size","title":"Attachments"},"description":"How asset bytes travel: `full` (every attachment inline), `by-size` (inline up to the server's threshold, else by digest URI), `by-role` (inline only the `roles` and `slots` named), `reference` (never bytes — URIs only)."},{"name":"roles","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"},"maxItems":50},{"type":"null"}],"description":"`by-role`: file roles to inline (`mask`, `height`, `mesh`, …).","title":"Roles"},"description":"`by-role`: file roles to inline (`mask`, `height`, `mesh`, …)."},{"name":"slots","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"},"maxItems":50},{"type":"null"}],"description":"`by-role`: glob patterns over recipe slots to inline (`mesh:wall_*`).","title":"Slots"},"description":"`by-role`: glob patterns over recipe slots to inline (`mesh:wall_*`)."}],"responses":{"200":{"description":"The theme as a Scenebrew entity container (`.sbe`).","content":{"application/vnd.scenebrew.entity+json":{"schema":{"$ref":"#/components/schemas/EntityContainer"}}},"headers":{"X-Scenebrew-Content-Hash":{"description":"SHA-256 over the container's content, independent of how attachments travel: the same theme hashes the same in every mode.","schema":{"type":"string","pattern":"^[0-9a-f]{64}$"}},"Content-Disposition":{"description":"`attachment; filename=\"<theme slug>.sbe\"`.","schema":{"type":"string"}}}},"default":{"$ref":"#/components/responses/Problem"}}}},"/v1/themes/{theme_id}/designs":{"post":{"tags":["library"],"summary":"Link Theme Design","description":"Attach a design to a theme (same project). Requires the `write` scope.","operationId":"link_theme_design","security":[{"apiKey":[]}],"parameters":[{"name":"theme_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Theme Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ThemeDesignLinkIn"}}}},"responses":{"204":{"description":"Successful Response"},"default":{"$ref":"#/components/responses/Problem"}}}},"/v1/themes/{theme_id}/designs/{design_id}":{"delete":{"tags":["library"],"summary":"Unlink Theme Design","description":"Detach a design from a theme. Requires the `write` scope.","operationId":"unlink_theme_design","security":[{"apiKey":[]}],"parameters":[{"name":"theme_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Theme Id"}},{"name":"design_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Design Id"}}],"responses":{"204":{"description":"Successful Response"},"default":{"$ref":"#/components/responses/Problem"}}}},"/v1/designs/{design_id}/recipes":{"post":{"tags":["library"],"summary":"Link Design Recipe","description":"Attach a recipe to a design (same project). Requires the `write` scope.","operationId":"link_design_recipe","security":[{"apiKey":[]}],"parameters":[{"name":"design_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Design Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DesignRecipeLinkIn"}}}},"responses":{"204":{"description":"Successful Response"},"default":{"$ref":"#/components/responses/Problem"}}}},"/v1/designs/{design_id}/recipes/{recipe_id}":{"delete":{"tags":["library"],"summary":"Unlink Design Recipe","description":"Detach a recipe from a design. Requires the `write` scope.","operationId":"unlink_design_recipe","security":[{"apiKey":[]}],"parameters":[{"name":"design_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Design Id"}},{"name":"recipe_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Recipe Id"}}],"responses":{"204":{"description":"Successful Response"},"default":{"$ref":"#/components/responses/Problem"}}}},"/v1/recipes/{recipe_id}/assets":{"post":{"tags":["library"],"summary":"Link Recipe Asset","description":"Bind an asset into one operator slot of a recipe (same project). The\nslot is the link's identity: a slot holds one asset (409 when filled),\none asset may fill several slots. Requires the `write` scope.","operationId":"link_recipe_asset","security":[{"apiKey":[]}],"parameters":[{"name":"recipe_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Recipe Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecipeAssetLinkIn"}}}},"responses":{"204":{"description":"Successful Response"},"default":{"$ref":"#/components/responses/Problem"}}}},"/v1/recipes/{recipe_id}/assets/{asset_id}":{"delete":{"tags":["library"],"summary":"Unlink Recipe Asset","description":"Detach an asset from every slot it fills on a recipe. Requires the\n`write` scope.","operationId":"unlink_recipe_asset","security":[{"apiKey":[]}],"parameters":[{"name":"recipe_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Recipe Id"}},{"name":"asset_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Asset Id"}}],"responses":{"204":{"description":"Successful Response"},"default":{"$ref":"#/components/responses/Problem"}}}},"/v1/recipes/{recipe_id}/slots/{slot}":{"delete":{"tags":["library"],"summary":"Unlink Recipe Slot","description":"Empty one operator slot of a recipe (404 when it is empty). Requires the\n`write` scope.","operationId":"unlink_recipe_slot","security":[{"apiKey":[]}],"parameters":[{"name":"recipe_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Recipe Id"}},{"name":"slot","in":"path","required":true,"schema":{"type":"string","title":"Slot"}}],"responses":{"204":{"description":"Successful Response"},"default":{"$ref":"#/components/responses/Problem"}}}},"/v1/design-types":{"get":{"tags":["library"],"summary":"List Design Types","description":"The design types with their compatible recipe types — what a valid\n`create_design` needs. The catalogue is platform-wide; a visible project\nis needed to read it. Requires the `read` scope.","operationId":"list_design_types","security":[{"apiKey":[]}],"parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"string","format":"uuid","description":"Any project the key can see.","title":"Project Id"},"description":"Any project the key can see."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/DesignTypeOut"},"title":"Response List Design Types"}}}},"default":{"$ref":"#/components/responses/Problem"}}}},"/v1/recipe-types":{"get":{"tags":["library"],"summary":"List Recipe Types","description":"The recipe types; with `with_schema`, each carries the JSON Schema of\nits parameters, which an agent needs before `create_recipe`. Requires\nthe `read` scope.","operationId":"list_recipe_types","security":[{"apiKey":[]}],"parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"string","format":"uuid","description":"Any project the key can see.","title":"Project Id"},"description":"Any project the key can see."},{"name":"category","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Category"}},{"name":"with_schema","in":"query","required":false,"schema":{"type":"boolean","description":"Include each type's parameter JSON Schema.","default":false,"title":"With Schema"},"description":"Include each type's parameter JSON Schema."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/RecipeTypeOut"},"title":"Response List Recipe Types"}}}},"default":{"$ref":"#/components/responses/Problem"}}}},"/v1/projects/{project_id}/generations":{"post":{"tags":["library"],"summary":"Generate Library Entity","description":"Ask the AI for a library entity, as an Operation (202 + `Location`).\nOne contract for themes, designs, recipes and assets: `kind` names what\nis made, `model` where inference runs and who is billed. Today `asset`\nruns — a material or prop generator from `GET /v1/models`, billed by its\nvendor (BYOK) — and `result.entity` names the new asset; the other kinds\nanswer 501 until available. Requires the `write` scope.","operationId":"generate_library_entity","security":[{"apiKey":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Project Id"}},{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string","minLength":1,"maxLength":200},{"type":"null"}],"description":"Optional. Repeating a request with the same key returns what it already created (200) instead of running it again.","title":"Idempotency-Key"},"description":"Optional. Repeating a request with the same key returns what it already created (200) instead of running it again."},{"name":"Prefer","in":"header","required":false,"schema":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"description":"RFC 7240. `wait=N` (N ≤ 60) holds the response until the operation is terminal or N seconds passed: 200 with the finished operation, or the same 202 as without it. `respond-async` (the default) returns the queued operation at once.","title":"Prefer"},"description":"RFC 7240. `wait=N` (N ≤ 60) holds the response until the operation is terminal or N seconds passed: 200 with the finished operation, or the same 202 as without it. `respond-async` (the default) returns the queued operation at once."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerationCreateIn"}}}},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OperationOut"}}}},"200":{"description":"The operation finished within `Prefer: wait`, or the Idempotency-Key replayed an operation that already exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OperationOut"}}}},"default":{"$ref":"#/components/responses/Problem"}}}},"/v1/recipes/{recipe_id}/preview":{"post":{"tags":["library"],"summary":"Preview Recipe","description":"Cook a sample of the recipe — with the given parameters, or its own —\nand get a short-lived URL of the GLB. The one synchronous cook, bounded\nby the small sample. Requires the `write` scope.","operationId":"preview_recipe","security":[{"apiKey":[]}],"parameters":[{"name":"recipe_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Recipe Id"}}],"requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/RecipePreviewIn"},{"type":"null"}],"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PreviewOut"}}}},"default":{"$ref":"#/components/responses/Problem"}}}}},"components":{"schemas":{"ApiKeyOut":{"properties":{"name":{"type":"string","title":"Name"},"prefix":{"type":"string","title":"Prefix"}},"type":"object","required":["name","prefix"],"title":"ApiKeyOut","description":"The authenticated key itself — name and display prefix, never the secret."},"AssetCreateIn":{"properties":{"name":{"type":"string","maxLength":255,"minLength":1,"title":"Name"},"type":{"type":"string","enum":["mesh","material","texture"],"title":"Type"},"category":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Category"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"tags":{"items":{"type":"string"},"type":"array","title":"Tags"},"metadata":{"additionalProperties":true,"type":"object","title":"Metadata","description":"Free-form; the prop convention puts `fit` (height_units, width_units, footprint, pivot, blocking, tier) and `aliases` here.","default":{}},"file_ids":{"items":{"type":"string","format":"uuid"},"type":"array","maxItems":20,"title":"File Ids","description":"Uploaded files (POST /v1/files) that become the asset's files.","default":[]}},"type":"object","required":["name","type"],"title":"AssetCreateIn"},"AssetFileAddIn":{"properties":{"file_id":{"type":"string","format":"uuid","title":"File Id","description":"An uploaded file (POST /v1/files); its bytes fill the role."},"role":{"type":"string","maxLength":64,"minLength":1,"title":"Role","description":"`mesh` on a mesh asset, `texture` on a texture asset, or a channel role of a material: albedo, normal, roughness, height, metallic, ao, emission, opacity, mask."}},"type":"object","required":["file_id","role"],"title":"AssetFileAddIn","description":"Fill an empty file role of an asset from an uploaded file."},"AssetFileOut":{"properties":{"filename":{"type":"string","title":"Filename"},"role":{"type":"string","title":"Role","description":"mesh, texture, albedo, normal, roughness, …"},"media_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Media Type"},"sha256":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sha256"},"size_bytes":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Size Bytes"},"download_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Download Url"},"download_expires_in":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Download Expires In"},"download_expires_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Download Expires At"}},"type":"object","required":["filename","role"],"title":"AssetFileOut","description":"One stored file: its role, name, media type, digest and size, plus a\nshort-lived download URL. `GET /v1/assets/{id}/files/{role}` is the\nstable form."},"AssetFileReplaceIn":{"properties":{"file_id":{"type":"string","format":"uuid","title":"File Id","description":"An uploaded file (POST /v1/files); its bytes replace the role's."}},"type":"object","required":["file_id"],"title":"AssetFileReplaceIn","description":"Replace the bytes of a filled role; the precondition travels as `If-Match`."},"AssetOut":{"properties":{"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"tags":{"items":{"type":"string"},"type":"array","title":"Tags","default":[]},"metadata":{"additionalProperties":true,"type":"object","title":"Metadata","default":{}},"id":{"type":"string","format":"uuid","title":"Id"},"slug":{"type":"string","title":"Slug"},"project_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Project Id"},"thumbnail_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Thumbnail Url"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Type","description":"mesh, material, texture, …"},"category":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Category"},"files":{"additionalProperties":{"$ref":"#/components/schemas/Attachment"},"type":"object","title":"Files","description":"The stored bytes by role.","default":{}},"attachment":{"anyOf":[{"$ref":"#/components/schemas/Attachment"},{"type":"null"}],"description":"A texture's image, as exports before SCBR-678 carried it; `files.texture` now.","deprecated":true},"format":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Format"},"resolution":{"anyOf":[{"items":{"type":"integer"},"type":"array"},{"type":"null"}],"title":"Resolution"},"shader_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Shader Name"},"shader_parameters":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Shader Parameters"},"texture_refs":{"anyOf":[{"items":{"$ref":"#/components/schemas/MaterialTextureRef"},"type":"array"},{"type":"null"}],"title":"Texture Refs"},"meshes":{"anyOf":[{"items":{"$ref":"#/components/schemas/MeshSlotRecord"},"type":"array"},{"type":"null"}],"title":"Meshes"},"materials":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Materials"},"textures":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Textures"},"fallback_color":{"anyOf":[{"type":"string","pattern":"^#[0-9a-f]{6}$"},{"type":"null"}],"title":"Fallback Color","description":"A material's colour where its maps are not drawn: the mean of its albedo map, sRGB `#rrggbb`. Read from the maps when they are stored; null while unknown."},"normal_convention":{"anyOf":[{"type":"string","enum":["opengl","directx"]},{"type":"null"}],"title":"Normal Convention","description":"The green-channel convention of a material's normal map, read when it is stored. glTF expects `opengl`; a renderer flips a `directx` map's green channel. Null while unknown (no normal map, or an undecidable one)."},"stored_files":{"items":{"$ref":"#/components/schemas/AssetFileOut"},"type":"array","title":"Stored Files","default":[]}},"type":"object","required":["name","id","slug","created_at","updated_at"],"title":"AssetOut","description":"`AssetRecord` plus the server-only fields. `files` is the record's\nmap of attachments by role; `stored_files` lists the same files with\npresigned download URLs."},"AssetResolveIn":{"properties":{"ids":{"items":{"type":"string","format":"uuid"},"type":"array","maxItems":100,"minItems":1,"title":"Ids","description":"Asset ids."},"roles":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Roles","description":"Only these roles (`albedo`, `normal`, `ao`, …); all when omitted."}},"type":"object","required":["ids"],"title":"AssetResolveIn","description":"The assets a renderer needs to draw a scene that references them."},"AssetResolveOut":{"properties":{"items":{"items":{"$ref":"#/components/schemas/ResolvedAssetOut"},"type":"array","title":"Items"}},"type":"object","required":["items"],"title":"AssetResolveOut","description":"The assets in request order."},"Attachment":{"properties":{"media_type":{"type":"string","minLength":1,"title":"Media Type","description":"Media type of the raw bytes (e.g. image/png)"},"sha256":{"type":"string","pattern":"^[0-9a-f]{64}$","title":"Sha256","description":"Lowercase hex SHA-256 of the raw (decoded, decompressed) bytes"},"uri":{"anyOf":[{"type":"string","minLength":1},{"type":"null"}],"title":"Uri","description":"Where to fetch the raw bytes from"},"data":{"anyOf":[{"type":"string","minLength":1},{"type":"null"}],"title":"Data","description":"The raw bytes, gzip-compressed then base64-encoded"}},"additionalProperties":false,"type":"object","required":["media_type","sha256"],"title":"Attachment","description":"The bytes of an asset, by URI or inline, always with their SHA-256.\n\nRecognized structurally: an object with exactly these keys. Exactly one\nof ``uri`` and ``data`` is set; ``data`` is the raw bytes gzip-compressed\nthen base64-encoded; ``sha256`` is always the digest of the raw bytes.\nInline is for small procedural inputs; meshes and large images go by URI.","examples":[{"media_type":"image/png","sha256":"a1abfd410973b0111c215baa879b9edcd739e601659ba44168269767cc2e9108","uri":"https://assets.example.invalid/noise-mask.png"}]},"Body_upload_files":{"properties":{"files":{"items":{"type":"string","contentMediaType":"application/octet-stream"},"type":"array","title":"Files","description":"One or many files: GLB, PNG, JPEG or WebP. 100 MB per request."},"project_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Project Id","description":"Optionally the project the files are meant for."}},"type":"object","required":["files"],"title":"Body_upload_files"},"CreditsOut":{"properties":{"balance":{"type":"integer","title":"Balance"},"plan":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Plan"},"period_ends_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Period Ends At"},"ledger":{"items":{"$ref":"#/components/schemas/LedgerEntryOut"},"type":"array","title":"Ledger"}},"type":"object","required":["balance","plan","period_ends_at","ledger"],"title":"CreditsOut","description":"The tenant's balance and its most recent ledger entries."},"CursorPage_AssetOut_":{"properties":{"items":{"items":{"$ref":"#/components/schemas/AssetOut"},"type":"array","title":"Items"},"next_cursor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next Cursor"},"total":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Total","description":"Size of the whole collection, when the platform knows it."}},"type":"object","required":["items"],"title":"CursorPage[AssetOut]"},"CursorPage_DesignOut_":{"properties":{"items":{"items":{"$ref":"#/components/schemas/DesignOut"},"type":"array","title":"Items"},"next_cursor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next Cursor"},"total":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Total","description":"Size of the whole collection, when the platform knows it."}},"type":"object","required":["items"],"title":"CursorPage[DesignOut]"},"CursorPage_OperationOut_":{"properties":{"items":{"items":{"$ref":"#/components/schemas/OperationOut"},"type":"array","title":"Items"},"next_cursor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next Cursor"},"total":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Total","description":"Size of the whole collection, when the platform knows it."}},"type":"object","required":["items"],"title":"CursorPage[OperationOut]"},"CursorPage_ProjectOut_":{"properties":{"items":{"items":{"$ref":"#/components/schemas/ProjectOut"},"type":"array","title":"Items"},"next_cursor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next Cursor"},"total":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Total","description":"Size of the whole collection, when the platform knows it."}},"type":"object","required":["items"],"title":"CursorPage[ProjectOut]"},"CursorPage_RecipeOut_":{"properties":{"items":{"items":{"$ref":"#/components/schemas/RecipeOut"},"type":"array","title":"Items"},"next_cursor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next Cursor"},"total":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Total","description":"Size of the whole collection, when the platform knows it."}},"type":"object","required":["items"],"title":"CursorPage[RecipeOut]"},"CursorPage_SceneOut_":{"properties":{"items":{"items":{"$ref":"#/components/schemas/SceneOut"},"type":"array","title":"Items"},"next_cursor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next Cursor"},"total":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Total","description":"Size of the whole collection, when the platform knows it."}},"type":"object","required":["items"],"title":"CursorPage[SceneOut]"},"CursorPage_SessionOut_":{"properties":{"items":{"items":{"$ref":"#/components/schemas/SessionOut"},"type":"array","title":"Items"},"next_cursor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next Cursor"},"total":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Total","description":"Size of the whole collection, when the platform knows it."}},"type":"object","required":["items"],"title":"CursorPage[SessionOut]"},"CursorPage_ThemeOut_":{"properties":{"items":{"items":{"$ref":"#/components/schemas/ThemeOut"},"type":"array","title":"Items"},"next_cursor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next Cursor"},"total":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Total","description":"Size of the whole collection, when the platform knows it."}},"type":"object","required":["items"],"title":"CursorPage[ThemeOut]"},"DesignCreateIn":{"properties":{"name":{"type":"string","maxLength":255,"minLength":1,"title":"Name"},"type":{"type":"string","maxLength":100,"minLength":1,"title":"Type","description":"A design type id (GET /v1/design-types)."},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"parameters":{"additionalProperties":true,"type":"object","title":"Parameters"},"tags":{"items":{"type":"string"},"type":"array","title":"Tags"},"metadata":{"additionalProperties":true,"type":"object","title":"Metadata","description":"Free-form. `placeholder: true` marks a placeholder that needs no assets: a surface recipe without a material draws in its `color`, a prop recipe without a mesh cooks as a box stand-in.","default":{}},"theme_ids":{"items":{"type":"string","format":"uuid"},"type":"array","maxItems":100,"title":"Theme Ids"},"recipe_ids":{"items":{"type":"string","format":"uuid"},"type":"array","maxItems":100,"title":"Recipe Ids"}},"type":"object","required":["name","type"],"title":"DesignCreateIn"},"DesignOut":{"properties":{"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"tags":{"items":{"type":"string"},"type":"array","title":"Tags","default":[]},"metadata":{"additionalProperties":true,"type":"object","title":"Metadata","default":{}},"id":{"type":"string","format":"uuid","title":"Id"},"slug":{"type":"string","title":"Slug"},"project_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Project Id"},"thumbnail_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Thumbnail Url"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Type","description":"terrain, bridge, fence, ladder, stair, wall, …"},"recipes":{"items":{"$ref":"#/components/schemas/Reference"},"type":"array","title":"Recipes","description":"Ordered recipe references.","default":[]},"parameters":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Parameters"},"recipe_ids":{"items":{"type":"string","format":"uuid"},"type":"array","title":"Recipe Ids","default":[]},"recipe_count":{"type":"integer","title":"Recipe Count","default":0}},"type":"object","required":["name","id","slug","created_at","updated_at"],"title":"DesignOut","description":"`DesignRecord` plus the server-only fields."},"DesignRecipeLinkIn":{"properties":{"recipe_id":{"type":"string","format":"uuid","title":"Recipe Id"}},"type":"object","required":["recipe_id"],"title":"DesignRecipeLinkIn"},"DesignTypeOut":{"properties":{"id":{"type":"string","title":"Id"},"category":{"type":"string","title":"Category"},"label":{"type":"string","title":"Label"},"supported_recipe_types":{"items":{"type":"string"},"type":"array","title":"Supported Recipe Types","default":[]}},"type":"object","required":["id","category","label"],"title":"DesignTypeOut"},"EmbeddedEntity":{"properties":{"kind":{"type":"string","minLength":1,"title":"Kind","description":"Entity kind: theme, design, recipe, asset, ..."},"uuid":{"type":"string","format":"uuid","title":"Uuid","description":"Identity of the entity, stable across stores"}},"additionalProperties":true,"type":"object","required":["kind","uuid"],"title":"EmbeddedEntity","description":"An entity as the envelope sees it: kind, identity, opaque payload.\n\nEvery other key is the entity type's business (library-service owns\nthose schemas) and is carried verbatim; only the references and\nattachments inside it are validated, by shape."},"EntityContainer":{"properties":{"schema_version":{"type":"string","const":"0.1.0","title":"Schema Version","description":"Container envelope version","default":"0.1.0"},"root":{"type":"string","format":"uuid","title":"Root","description":"UUID of the root entity; must be embedded"},"entities":{"additionalProperties":{"$ref":"#/components/schemas/EmbeddedEntity"},"propertyNames":{"format":"uuid"},"type":"object","title":"Entities","description":"Embedded entities keyed by their UUID; all reachable from root"}},"type":"object","required":["root","entities"],"title":"EntityContainer","description":"One root entity and the flat table of everything embedded with it.","examples":[{"entities":{"0199a1c0-0000-7000-8000-000000000001":{"designs":[{"kind":"design","uuid":"0199a1c0-0000-7000-8000-000000000002"}],"kind":"theme","name":"Default tilemap","uuid":"0199a1c0-0000-7000-8000-000000000001"},"0199a1c0-0000-7000-8000-000000000002":{"kind":"design","name":"Tilemap terrain","recipes":[{"kind":"recipe","uuid":"0199a1c0-0000-7000-8000-000000000003"}],"uuid":"0199a1c0-0000-7000-8000-000000000002"},"0199a1c0-0000-7000-8000-000000000003":{"kind":"recipe","name":"Blockout tiles","operator":"swf::terrain_blockout_tiles","parameters":{"chamfer_corners":1},"uuid":"0199a1c0-0000-7000-8000-000000000003"}},"root":"0199a1c0-0000-7000-8000-000000000001","schema_version":"0.1.0"}]},"FileOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"filename":{"type":"string","title":"Filename"},"content_type":{"type":"string","title":"Content Type"},"size_bytes":{"type":"integer","format":"int64","title":"Size Bytes"},"sha256":{"type":"string","title":"Sha256"},"status":{"type":"string","title":"Status","description":"uploaded (unreferenced, expires), referenced, or expired."},"download_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Download Url"},"download_expires_in":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Download Expires In"},"download_expires_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Download Expires At"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"expires_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Expires At"}},"type":"object","required":["id","filename","content_type","size_bytes","sha256","status","created_at","expires_at"],"title":"FileOut","description":"An uploaded file, referenced by id from scenes, assets and messages."},"FilesOut":{"properties":{"items":{"items":{"$ref":"#/components/schemas/FileOut"},"type":"array","title":"Items"}},"type":"object","required":["items"],"title":"FilesOut"},"GenerationCreateIn":{"properties":{"kind":{"type":"string","enum":["theme","design","recipe","asset"],"title":"Kind"},"brief":{"type":"string","maxLength":2000,"minLength":3,"title":"Brief"},"model":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Model","description":"Required for assets; see GET /v1/models."},"name":{"anyOf":[{"type":"string","maxLength":255,"minLength":1},{"type":"null"}],"title":"Name"},"category":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Category"},"tags":{"items":{"type":"string"},"type":"array","title":"Tags"},"reference_file_ids":{"items":{"type":"string","format":"uuid"},"type":"array","maxItems":8,"title":"Reference File Ids","description":"Uploaded reference images for guided prop generation.","default":[]},"params":{"additionalProperties":true,"type":"object","title":"Params","description":"Generator-specific parameters.","default":{}},"theme_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Theme Id"},"design_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Design Id"},"recipe_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Recipe Type"}},"type":"object","required":["kind","brief"],"title":"GenerationCreateIn","description":"Ask the AI for a library entity. One contract for all four kinds; the\n`model` decides where inference runs and who is billed. Today `asset`\nruns (a material or prop generator, GET /v1/models); theme, design and\nrecipe answer 501 until available."},"GridValues":{"properties":{"cell_size":{"type":"number","exclusiveMinimum":0.0,"title":"Cell Size","description":"Grid cell size in world units."},"snap":{"type":"string","enum":["cell-center","cell-corner"],"title":"Snap","description":"What a position snaps to on the grid.","default":"cell-center"}},"type":"object","required":["cell_size"],"title":"GridValues"},"HeightValues":{"properties":{"range":{"prefixItems":[{"type":"number"},{"type":"number"}],"type":"array","maxItems":2,"minItems":2,"title":"Range","description":"[min, max] walkable height in world units."},"max_step":{"type":"number","exclusiveMinimum":0.0,"title":"Max Step","description":"Largest walkable height difference in world units."}},"type":"object","required":["range","max_step"],"title":"HeightValues"},"LedgerEntryOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"amount":{"type":"integer","title":"Amount"},"type":{"type":"string","title":"Type"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"project_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Project Id"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"balance_after":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Balance After"}},"type":"object","required":["id","amount","type","description","project_id","created_at"],"title":"LedgerEntryOut"},"LevelValues":{"properties":{"height":{"type":"number","exclusiveMinimum":0.0,"title":"Height","description":"Height of one level in world units."},"count":{"type":"integer","minimum":1.0,"title":"Count","description":"Number of levels above the base."}},"type":"object","required":["height","count"],"title":"LevelValues"},"LibraryUpdateIn":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":255,"minLength":1},{"type":"null"}],"title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"parameters":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Parameters"},"world":{"anyOf":[{"$ref":"#/components/schemas/World"},{"type":"null"}]},"scene_parameters":{"anyOf":[{"additionalProperties":{"additionalProperties":true,"type":"object"},"type":"object"},{"type":"null"}],"title":"Scene Parameters"},"operator_version":{"anyOf":[{"type":"string","pattern":"^\\d+\\.\\d+\\.\\d+$"},{"type":"null"}],"title":"Operator Version"},"tags":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Tags"},"category":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Category"},"texture_refs":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Texture Refs"},"shader_parameters":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Shader Parameters"},"fallback_color":{"anyOf":[{"type":"string","pattern":"^#[0-9a-f]{6}$"},{"type":"null"}],"title":"Fallback Color","description":"Corrects a material's fallback colour (sRGB `#rrggbb`)."},"normal_convention":{"anyOf":[{"type":"string","enum":["opengl","directx"]},{"type":"null"}],"title":"Normal Convention","description":"Corrects a material's normal-map convention."},"metadata":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Metadata","description":"Merged key by key into the entity's metadata (null removes a key). A theme's `style` must match `ThemeStyle`."}},"type":"object","title":"LibraryUpdateIn","description":"Omitted fields stay as they are. `category`, `texture_refs`,\n`shader_parameters`, `fallback_color` and `normal_convention` apply to\nassets; `parameters` to the other three;\n`world` and `scene_parameters` to themes; `operator_version` to recipes."},"MaterialTextureRef":{"properties":{"semantic":{"type":"string","title":"Semantic","description":"BASE_COLOR, NORMAL, ROUGHNESS, HEIGHT, …"},"file":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"File","description":"Role in `files` (albedo, normal, …)."},"asset":{"anyOf":[{"$ref":"#/components/schemas/Reference"},{"type":"null"}]},"resolution":{"anyOf":[{"items":{"type":"integer"},"type":"array"},{"type":"null"}],"title":"Resolution"}},"type":"object","required":["semantic"],"title":"MaterialTextureRef","description":"A material's channel binding: to one of its own maps (`file` names the\nrole) or to a standalone texture asset (`asset`)."},"MeResponse":{"properties":{"tenant":{"$ref":"#/components/schemas/TenantOut"},"user":{"$ref":"#/components/schemas/UserOut"},"key":{"$ref":"#/components/schemas/ApiKeyOut"},"scopes":{"items":{"type":"string"},"type":"array","title":"Scopes"},"plan":{"type":"string","title":"Plan"}},"type":"object","required":["tenant","user","key","scopes","plan"],"title":"MeResponse","description":"The principal behind the presented API key."},"MeshSlotRecord":{"properties":{"slot":{"type":"integer","title":"Slot"},"name":{"type":"string","title":"Name"},"file":{"type":"string","title":"File","description":"Role in `files` (mesh, mesh1, …)."},"material":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Material","description":"Bundled material name."},"material_asset":{"anyOf":[{"$ref":"#/components/schemas/Reference"},{"type":"null"}],"description":"A standalone material asset instead."},"metadata":{"additionalProperties":true,"type":"object","title":"Metadata","default":{}}},"type":"object","required":["slot","name","file"],"title":"MeshSlotRecord","description":"One mesh of a mesh asset: slot 0 is the main mesh."},"MessageCreateIn":{"properties":{"text":{"type":"string","maxLength":20000,"minLength":1,"title":"Text"},"file_ids":{"items":{"type":"string","format":"uuid"},"type":"array","maxItems":20,"title":"File Ids"}},"type":"object","required":["text"],"title":"MessageCreateIn","description":"A message to post to the session; the agent answers it in one turn."},"MessageOut":{"properties":{"id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Id"},"role":{"type":"string","enum":["user","assistant"],"title":"Role"},"content":{"type":"string","title":"Content"},"timestamp":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Timestamp"},"operation_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Operation Id","description":"The turn that posted or answered it, when known."}},"type":"object","required":["role","content"],"title":"MessageOut"},"ModelOut":{"properties":{"id":{"type":"string","title":"Id"},"provider":{"type":"string","title":"Provider"},"hosting":{"type":"string","enum":["scenebrew","external"],"title":"Hosting","description":"Where inference runs: Scenebrew's own infrastructure or an external vendor."},"billing":{"type":"string","enum":["credits","byok"],"title":"Billing","description":"Who is billed: Scenebrew credits, or the tenant's own vendor key."},"capabilities":{"items":{"type":"string","enum":["chat","sdd","peg","theme","design","recipe","asset"]},"type":"array","title":"Capabilities"},"default":{"type":"boolean","title":"Default","default":false},"label":{"type":"string","title":"Label"}},"type":"object","required":["id","provider","hosting","billing","capabilities","label"],"title":"ModelOut","description":"One model the tenant may pick — the same list the web UI offers."},"ModelsOut":{"properties":{"items":{"items":{"$ref":"#/components/schemas/ModelOut"},"type":"array","title":"Items"}},"type":"object","required":["items"],"title":"ModelsOut"},"OperationErrorOut":{"properties":{"code":{"type":"string","title":"Code","description":"Machine-readable failure class: insufficient_credits, missing_brief, missing_sdd, missing_peg, missing_blueprint, missing_theme, sdd_issues, layout_failed, brew_failed, runner_unavailable, agent_unavailable, unknown_session, generation_failed, generation_lost, canceled, step_failed."},"message":{"type":"string","title":"Message"},"retryable":{"type":"boolean","title":"Retryable","default":false}},"type":"object","required":["code","message"],"title":"OperationErrorOut"},"OperationModelOut":{"properties":{"id":{"type":"string","title":"Id"},"hosting":{"type":"string","enum":["scenebrew","external"],"title":"Hosting"},"billing":{"type":"string","enum":["credits","byok"],"title":"Billing"}},"type":"object","required":["id","hosting","billing"],"title":"OperationModelOut"},"OperationOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"kind":{"type":"string","enum":["scene_step","session_turn","generation"],"title":"Kind"},"status":{"type":"string","enum":["queued","running","canceling","succeeded","failed","canceled"],"title":"Status"},"target":{"$ref":"#/components/schemas/OperationTargetOut"},"input":{"additionalProperties":true,"type":"object","title":"Input"},"progress":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Progress"},"result":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Result"},"error":{"anyOf":[{"$ref":"#/components/schemas/OperationErrorOut"},{"type":"null"}]},"credits_charged":{"type":"integer","title":"Credits Charged","default":0},"model":{"anyOf":[{"$ref":"#/components/schemas/OperationModelOut"},{"type":"null"}]},"created_by":{"type":"string","format":"uuid","title":"Created By"},"created_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Created At"},"started_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Started At"},"finished_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Finished At"},"cancel_requested_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Cancel Requested At"}},"type":"object","required":["id","kind","status","target","created_by","created_at","started_at","finished_at"],"title":"OperationOut","description":"One unit of long-running work: a scene step, a session turn or a\nlibrary generation. Poll it, list it, cancel it — the same way for all\nthree. `result` is set once `status` is terminal: `{step, artifacts}` for\na scene step, `{reply, partial, tools_executed, artifacts}` for a turn,\n`{entity: {kind, id, name}}` for a generation."},"OperationTargetOut":{"properties":{"type":{"type":"string","enum":["scene","session","project"],"title":"Type"},"id":{"type":"string","format":"uuid","title":"Id"}},"type":"object","required":["type","id"],"title":"OperationTargetOut"},"PreviewOut":{"properties":{"download_url":{"type":"string","title":"Download Url"},"download_expires_in":{"type":"integer","title":"Download Expires In"},"download_expires_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Download Expires At"},"content_type":{"type":"string","title":"Content Type"},"size_bytes":{"type":"integer","format":"int64","title":"Size Bytes"}},"type":"object","required":["download_url","download_expires_in","content_type","size_bytes"],"title":"PreviewOut","description":"A short-lived URL of the sample GLB."},"ProjectCreateIn":{"properties":{"name":{"type":"string","maxLength":50,"minLength":1,"title":"Name"},"description":{"anyOf":[{"type":"string","maxLength":1000},{"type":"null"}],"title":"Description"}},"type":"object","required":["name"],"title":"ProjectCreateIn"},"ProjectDetailOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"slug":{"type":"string","title":"Slug"},"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"status":{"type":"string","title":"Status"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"access_level":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Access Level"},"scene_count":{"type":"integer","title":"Scene Count","default":0},"asset_count":{"type":"integer","title":"Asset Count","default":0}},"type":"object","required":["id","slug","name","description","status","created_at","updated_at"],"title":"ProjectDetailOut"},"ProjectOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"slug":{"type":"string","title":"Slug"},"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"status":{"type":"string","title":"Status"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","slug","name","description","status","created_at","updated_at"],"title":"ProjectOut"},"ProjectUpdateIn":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":50,"minLength":1},{"type":"null"}],"title":"Name"},"description":{"anyOf":[{"type":"string","maxLength":1000},{"type":"null"}],"title":"Description"},"status":{"anyOf":[{"type":"string","enum":["active","archived"]},{"type":"null"}],"title":"Status"}},"type":"object","title":"ProjectUpdateIn","description":"Omitted fields stay as they are; `status: archived` archives, `active` unarchives."},"RecipeAssetLinkIn":{"properties":{"asset_id":{"type":"string","format":"uuid","title":"Asset Id"},"slot":{"type":"string","maxLength":100,"minLength":1,"title":"Slot","description":"The operator's asset slot the asset fills — the link's identity. A slot holds one asset; one asset may fill several slots (mesh:tree_a and mesh:tree_b)."}},"type":"object","required":["asset_id","slot"],"title":"RecipeAssetLinkIn"},"RecipeCreateIn":{"properties":{"name":{"type":"string","maxLength":255,"minLength":1,"title":"Name"},"type":{"type":"string","maxLength":100,"minLength":1,"title":"Type","description":"A recipe type id (GET /v1/recipe-types)."},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"operator_version":{"anyOf":[{"type":"string","pattern":"^\\d+\\.\\d+\\.\\d+$"},{"type":"null"}],"title":"Operator Version","description":"Semver of the operator schema `parameters` were written against."},"parameters":{"additionalProperties":true,"type":"object","title":"Parameters"},"tags":{"items":{"type":"string"},"type":"array","title":"Tags"},"metadata":{"additionalProperties":true,"type":"object","title":"Metadata","description":"Free-form. `placeholder: true` marks a placeholder that needs no assets: a surface recipe without a material draws in its `color`, a prop recipe without a mesh cooks as a box stand-in.","default":{}},"design_ids":{"items":{"type":"string","format":"uuid"},"type":"array","maxItems":100,"title":"Design Ids"},"assets":{"additionalProperties":{"type":"string","format":"uuid"},"type":"object","maxProperties":100,"title":"Assets","description":"Operator slot → asset id, linked right after creation. Slots are the operator's vocabulary (material:ground, mesh:tree_a); one asset may fill several slots.","default":{}}},"type":"object","required":["name","type"],"title":"RecipeCreateIn"},"RecipeOut":{"properties":{"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"tags":{"items":{"type":"string"},"type":"array","title":"Tags","default":[]},"metadata":{"additionalProperties":true,"type":"object","title":"Metadata","default":{}},"id":{"type":"string","format":"uuid","title":"Id"},"slug":{"type":"string","title":"Slug"},"project_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Project Id"},"thumbnail_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Thumbnail Url"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"operator":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Operator","description":"Brewer node type (e.g. swf::terrain_blockout_tiles); null while the recipe type's operator is not ported."},"operator_version":{"anyOf":[{"type":"string","pattern":"^\\d+\\.\\d+\\.\\d+$"},{"type":"null"}],"title":"Operator Version","description":"Semver of the operator schema the parameters were written against."},"parameters":{"additionalProperties":true,"type":"object","title":"Parameters","default":{}},"assets":{"additionalProperties":{"$ref":"#/components/schemas/Reference"},"type":"object","title":"Assets","description":"Asset references keyed by operator slot.","default":{}},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Type"},"asset_ids":{"items":{"type":"string","format":"uuid"},"type":"array","title":"Asset Ids","default":[]},"asset_count":{"type":"integer","title":"Asset Count","default":0}},"type":"object","required":["name","id","slug","created_at","updated_at"],"title":"RecipeOut","description":"`RecipeRecord` plus the server-only fields. `type` is the recipe type\nid of the catalogue (GET /v1/recipe-types); `operator` is the brewer node\ntype it maps to."},"RecipePreviewIn":{"properties":{"parameters":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Parameters","description":"Parameter overrides for this preview; the recipe's own when omitted."}},"type":"object","title":"RecipePreviewIn"},"RecipeTypeOut":{"properties":{"id":{"type":"string","title":"Id"},"category":{"type":"string","title":"Category"},"label":{"type":"string","title":"Label"},"node_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Node Type"},"params_schema":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Params Schema","description":"The type's parameter JSON Schema, when requested with with_schema."}},"type":"object","required":["id","category","label"],"title":"RecipeTypeOut"},"Reference":{"properties":{"uuid":{"type":"string","format":"uuid","title":"Uuid","description":"UUID of the referenced entity"},"kind":{"type":"string","minLength":1,"title":"Kind","description":"Kind the referenced entity must have"},"slug":{"anyOf":[{"type":"string","pattern":"^(?:[a-z]{2,5}_[0-9a-z]{13,16}|[0-9A-Za-z]{10})$"},{"type":"null"}],"title":"Slug","description":"Optional slug of the referenced entity, for humans and logs"}},"additionalProperties":false,"type":"object","required":["uuid","kind"],"title":"Reference","description":"A pointer to an entity: UUID, the kind it must be, an optional slug.\n\nRecognized structurally: an object with exactly these keys. Resolution\norder at the consumer: the containing document's own table, then\ncontainers passed alongside, then the environment's lookup.","examples":[{"kind":"recipe","slug":"rcp_4p8q1r5t7g3k9x2m","uuid":"0199a1c0-0000-7000-8000-000000000013"}]},"ResolvedAssetFileOut":{"properties":{"asset_id":{"type":"string","format":"uuid","title":"Asset Id"},"role":{"type":"string","title":"Role"},"sha256":{"type":"string","title":"Sha256"},"media_type":{"type":"string","title":"Media Type"},"size_bytes":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Size Bytes"},"url":{"type":"string","title":"Url"}},"type":"object","required":["asset_id","role","sha256","media_type","url"],"title":"ResolvedAssetFileOut","description":"One file a resolved asset draws on. `url` is the digest route\n`/v1/assets/{asset_id}/files/{role}?sha256=…`: the bytes behind it never\nchange, so a client caches them by `sha256` for good. A material channel\nbound to a standalone texture points at that texture (role `texture`)."},"ResolvedAssetOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"status":{"type":"string","enum":["ok","not_found"],"title":"Status"},"type":{"anyOf":[{"type":"string","enum":["mesh","material","texture"]},{"type":"null"}],"title":"Type"},"fallback_color":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Fallback Color"},"normal_convention":{"anyOf":[{"type":"string","enum":["opengl","directx"]},{"type":"null"}],"title":"Normal Convention"},"maps":{"additionalProperties":{"$ref":"#/components/schemas/ResolvedAssetFileOut"},"type":"object","title":"Maps","default":{}}},"type":"object","required":["id","status"],"title":"ResolvedAssetOut","description":"One asset of a resolve call: `ok` with its attributes and files by\nrole, or `not_found` — unknown, or not an asset of this project."},"SceneArtifactDetailOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"kind":{"type":"string","title":"Kind","description":"The artifact's role: sdd, peg, blueprint, model (the GLB), layout_preview, thumbnail."},"version":{"type":"integer","title":"Version"},"is_current":{"type":"boolean","title":"Is Current"},"content_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Content Type"},"size_bytes":{"anyOf":[{"type":"integer","format":"int64"},{"type":"null"}],"title":"Size Bytes"},"content_hash":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Content Hash"},"created_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Created At"},"download_url":{"type":"string","title":"Download Url","description":"Short-lived presigned URL for the artifact bytes. Fetch it promptly; re-list to obtain a fresh one after expiry."},"download_expires_in":{"type":"integer","title":"Download Expires In","description":"Seconds until download_url stops working."},"download_expires_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Download Expires At","description":"Absolute expiry (RFC 3339) of download_url — the same instant."},"materials":{"anyOf":[{"type":"string","enum":["reference","embed"]},{"type":"null"}],"title":"Materials","description":"The model only: whether the materials of the GLB `download_url` serves are `embed`ded with their maps or by `reference` (thin materials whose `extras.scenebrew.asset` names the library material — resolve them with POST /v1/projects/{project_id}/assets/resolve). Null for other kinds."},"meshes":{"anyOf":[{"type":"string","enum":["reference","embed"]},{"type":"null"}],"title":"Meshes","description":"The model only: whether its library meshes are `embed`ded or by `reference` (instance nodes whose `extras.scenebrew.mesh` names the mesh asset). Null for other kinds."},"content":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Content"}},"type":"object","required":["id","kind","version","is_current","content_type","size_bytes","content_hash","created_at","download_url","download_expires_in"],"title":"SceneArtifactDetailOut","description":"One artifact version; `content` carries the SDD or PEG text when asked for."},"SceneArtifactOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"kind":{"type":"string","title":"Kind","description":"The artifact's role: sdd, peg, blueprint, model (the GLB), layout_preview, thumbnail."},"version":{"type":"integer","title":"Version"},"is_current":{"type":"boolean","title":"Is Current"},"content_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Content Type"},"size_bytes":{"anyOf":[{"type":"integer","format":"int64"},{"type":"null"}],"title":"Size Bytes"},"content_hash":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Content Hash"},"created_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Created At"},"download_url":{"type":"string","title":"Download Url","description":"Short-lived presigned URL for the artifact bytes. Fetch it promptly; re-list to obtain a fresh one after expiry."},"download_expires_in":{"type":"integer","title":"Download Expires In","description":"Seconds until download_url stops working."},"download_expires_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Download Expires At","description":"Absolute expiry (RFC 3339) of download_url — the same instant."},"materials":{"anyOf":[{"type":"string","enum":["reference","embed"]},{"type":"null"}],"title":"Materials","description":"The model only: whether the materials of the GLB `download_url` serves are `embed`ded with their maps or by `reference` (thin materials whose `extras.scenebrew.asset` names the library material — resolve them with POST /v1/projects/{project_id}/assets/resolve). Null for other kinds."},"meshes":{"anyOf":[{"type":"string","enum":["reference","embed"]},{"type":"null"}],"title":"Meshes","description":"The model only: whether its library meshes are `embed`ded or by `reference` (instance nodes whose `extras.scenebrew.mesh` names the mesh asset). Null for other kinds."}},"type":"object","required":["id","kind","version","is_current","content_type","size_bytes","content_hash","created_at","download_url","download_expires_in"],"title":"SceneArtifactOut"},"SceneArtifactsResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/SceneArtifactOut"},"type":"array","title":"Items"}},"type":"object","required":["items"],"title":"SceneArtifactsResponse"},"SceneCreateIn":{"properties":{"name":{"type":"string","maxLength":120,"minLength":1,"title":"Name"},"workflow":{"type":"string","enum":["t2s","i2s","s2s"],"title":"Workflow","description":"Pipeline family. t2s (text-to-scene) is what the API steps drive.","default":"t2s"},"description":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Description"},"theme_id":{"type":"string","format":"uuid","title":"Theme Id","description":"A library theme of the project (404 theme_not_found otherwise). Every scene has one, whatever its workflow."},"source_file_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Source File Id","description":"An uploaded GLB (POST /v1/files) recorded as the scene's first model version — the starting point of an s2s scene."}},"type":"object","required":["name","theme_id"],"title":"SceneCreateIn","description":"A new scene — the container everything the pipeline produces lives in."},"SceneDetailOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"slug":{"type":"string","title":"Slug"},"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"workflow":{"type":"string","title":"Workflow"},"status":{"type":"string","title":"Status"},"theme_id":{"type":"string","format":"uuid","title":"Theme Id","description":"The scene's library theme, which every layout is built with."},"triangle_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Triangle Count"},"asset_count":{"type":"integer","title":"Asset Count"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"project_id":{"type":"string","format":"uuid","title":"Project Id"},"artifacts":{"items":{"$ref":"#/components/schemas/SceneArtifactOut"},"type":"array","title":"Artifacts","default":[]}},"type":"object","required":["id","slug","name","description","workflow","status","theme_id","triangle_count","asset_count","created_at","updated_at","project_id"],"title":"SceneDetailOut","description":"A scene with the project that contains it and its current artifacts."},"SceneOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"slug":{"type":"string","title":"Slug"},"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"workflow":{"type":"string","title":"Workflow"},"status":{"type":"string","title":"Status"},"theme_id":{"type":"string","format":"uuid","title":"Theme Id","description":"The scene's library theme, which every layout is built with."},"triangle_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Triangle Count"},"asset_count":{"type":"integer","title":"Asset Count"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","slug","name","description","workflow","status","theme_id","triangle_count","asset_count","created_at","updated_at"],"title":"SceneOut"},"SceneSessionOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"slug":{"type":"string","title":"Slug"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title"},"last_activity_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Activity At"}},"type":"object","required":["id","slug","title","last_activity_at"],"title":"SceneSessionOut","description":"A conversation that refers to the scene."},"SceneStepCreateIn":{"properties":{"step":{"type":"string","enum":["generate_scene_sdd","revise_scene_sdd","generate_scene_peg","revise_scene_peg","generate_scene_blueprint","generate_scene_model","analyze_scene_image","decorate_scene"],"title":"Step","description":"generate_scene_sdd and generate_scene_peg are AI steps and cost credits; generate_scene_blueprint and generate_scene_model are procedural and free. revise_scene_sdd, revise_scene_peg, analyze_scene_image and decorate_scene are declared and answer 501 until available."},"brief":{"anyOf":[{"type":"string","maxLength":20000,"minLength":1},{"type":"null"}],"title":"Brief","description":"The design brief. Required for generate_scene_sdd."},"instructions":{"anyOf":[{"type":"string","maxLength":20000,"minLength":1},{"type":"null"}],"title":"Instructions","description":"Edit instructions for the revise_* steps and decorate_scene."},"file_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"File Id","description":"The uploaded reference image for analyze_scene_image."},"model":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Model","description":"The model an AI step runs on (GET /v1/models); the default when omitted."}},"type":"object","required":["step"],"title":"SceneStepCreateIn","description":"One step to run against the scene. The value of `step` is the name of\nthe tool that runs it."},"SceneUpdateIn":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":120,"minLength":1},{"type":"null"}],"title":"Name"},"description":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Description"},"theme_id":{"type":"string","format":"uuid","title":"Theme Id","description":"Re-themes the scene with another library theme of its project."}},"type":"object","title":"SceneUpdateIn","description":"What may be changed about a scene. Omitted fields stay as they are; a\nscene keeps a theme, so ``theme_id: null`` is a 400 theme_required."},"SessionContextItemOut":{"properties":{"kind":{"type":"string","title":"Kind"},"role":{"type":"string","title":"Role"},"id":{"type":"string","format":"uuid","title":"Id"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"}},"type":"object","required":["kind","role","id"],"title":"SessionContextItemOut","description":"An entity the session refers to — a scene, theme, design, recipe or\nasset — with its role in the conversation. Scene artifacts are read from\nthe scene, never from the session."},"SessionContextRefIn":{"properties":{"kind":{"type":"string","enum":["scene","theme","design","recipe","asset"],"title":"Kind"},"id":{"type":"string","format":"uuid","title":"Id"},"role":{"type":"string","enum":["referenced","created","modified"],"title":"Role","default":"referenced"}},"type":"object","required":["kind","id"],"title":"SessionContextRefIn"},"SessionCreateIn":{"properties":{"text":{"type":"string","maxLength":20000,"minLength":1,"title":"Text"},"title":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Title"},"context":{"items":{"$ref":"#/components/schemas/SessionContextRefIn"},"type":"array","maxItems":20,"title":"Context"},"file_ids":{"items":{"type":"string","format":"uuid"},"type":"array","maxItems":20,"title":"File Ids","description":"Uploaded files the first message refers to.","default":[]},"model":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Model"}},"type":"object","required":["text"],"title":"SessionCreateIn","description":"A session is created by its first message; there is no empty session.\nThe reply arrives on the returned `initial_turn` operation."},"SessionCreatedOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"slug":{"type":"string","title":"Slug"},"project_id":{"type":"string","format":"uuid","title":"Project Id"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title"},"status":{"type":"string","title":"Status"},"pinned":{"type":"boolean","title":"Pinned","default":false},"model":{"type":"string","title":"Model"},"turn_count":{"type":"integer","title":"Turn Count"},"last_message_preview":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Message Preview"},"context":{"items":{"$ref":"#/components/schemas/SessionContextItemOut"},"type":"array","title":"Context","default":[]},"created_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Created At"},"updated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Updated At"},"last_activity_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Activity At"},"initial_turn":{"$ref":"#/components/schemas/OperationOut"}},"type":"object","required":["id","slug","project_id","title","status","model","turn_count","created_at","updated_at","last_activity_at","initial_turn"],"title":"SessionCreatedOut","description":"The new session with the turn its first message started."},"SessionMessagesOut":{"properties":{"session_id":{"type":"string","format":"uuid","title":"Session Id"},"items":{"items":{"$ref":"#/components/schemas/MessageOut"},"type":"array","title":"Items"},"next_cursor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next Cursor"}},"type":"object","required":["session_id","items"],"title":"SessionMessagesOut","description":"A page of the conversation, newest first."},"SessionOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"slug":{"type":"string","title":"Slug"},"project_id":{"type":"string","format":"uuid","title":"Project Id"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title"},"status":{"type":"string","title":"Status"},"pinned":{"type":"boolean","title":"Pinned","default":false},"model":{"type":"string","title":"Model"},"turn_count":{"type":"integer","title":"Turn Count"},"last_message_preview":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Message Preview"},"context":{"items":{"$ref":"#/components/schemas/SessionContextItemOut"},"type":"array","title":"Context","default":[]},"created_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Created At"},"updated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Updated At"},"last_activity_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Activity At"}},"type":"object","required":["id","slug","project_id","title","status","model","turn_count","created_at","updated_at","last_activity_at"],"title":"SessionOut"},"SessionUpdateIn":{"properties":{"title":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Title"},"pinned":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Pinned"},"model":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Model"},"status":{"anyOf":[{"type":"string","enum":["active","archived"]},{"type":"null"}],"title":"Status"}},"type":"object","title":"SessionUpdateIn","description":"Omitted fields stay as they are. `model` is a session setting, as in the web UI."},"StyleEvidence":{"properties":{"claim":{"type":"string","minLength":1,"title":"Claim"},"source":{"type":"string","minLength":1,"title":"Source","description":"A reference image, crop path, brief passage or analysis id."},"note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note"}},"additionalProperties":false,"type":"object","required":["claim","source"],"title":"StyleEvidence","description":"Why a style choice was made: the claim and what it was read from."},"StyleReferenceImage":{"properties":{"uri":{"type":"string","minLength":1,"title":"Uri"},"sha256":{"anyOf":[{"type":"string","pattern":"^[0-9a-f]{64}$"},{"type":"null"}],"title":"Sha256"},"role":{"type":"string","enum":["concept","mood","surface","prop","other"],"title":"Role","default":"concept"},"note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note"}},"additionalProperties":false,"type":"object","required":["uri"],"title":"StyleReferenceImage"},"TenantOut":{"properties":{"slug":{"type":"string","title":"Slug"},"name":{"type":"string","title":"Name"}},"type":"object","required":["slug","name"],"title":"TenantOut"},"ThemeCreateIn":{"properties":{"name":{"type":"string","maxLength":255,"minLength":1,"title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"parameters":{"additionalProperties":true,"type":"object","title":"Parameters"},"world":{"anyOf":[{"$ref":"#/components/schemas/World"},{"type":"null"}]},"scene_parameters":{"additionalProperties":{"additionalProperties":true,"type":"object"},"type":"object","title":"Scene Parameters"},"tags":{"items":{"type":"string"},"type":"array","title":"Tags"},"design_ids":{"items":{"type":"string","format":"uuid"},"type":"array","maxItems":100,"title":"Design Ids","description":"Designs to link at create.","default":[]}},"type":"object","required":["name"],"title":"ThemeCreateIn"},"ThemeDesignLinkIn":{"properties":{"design_id":{"type":"string","format":"uuid","title":"Design Id"}},"type":"object","required":["design_id"],"title":"ThemeDesignLinkIn"},"ThemeMetadata":{"properties":{"style":{"anyOf":[{"$ref":"#/components/schemas/ThemeStyle"},{"type":"null"}]}},"additionalProperties":true,"type":"object","title":"ThemeMetadata","description":"A theme's free-form metadata; `style` is the one key with a schema."},"ThemeOut":{"properties":{"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"tags":{"items":{"type":"string"},"type":"array","title":"Tags","default":[]},"metadata":{"$ref":"#/components/schemas/ThemeMetadata","default":{}},"id":{"type":"string","format":"uuid","title":"Id"},"slug":{"type":"string","title":"Slug"},"project_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Project Id"},"thumbnail_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Thumbnail Url"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"world":{"anyOf":[{"$ref":"#/components/schemas/World"},{"type":"null"}]},"scene_parameters":{"additionalProperties":{"additionalProperties":true,"type":"object"},"type":"object","title":"Scene Parameters","default":{}},"designs":{"items":{"$ref":"#/components/schemas/Reference"},"type":"array","title":"Designs","description":"Ordered design references.","default":[]},"parameters":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Parameters"},"design_ids":{"items":{"type":"string","format":"uuid"},"type":"array","title":"Design Ids","default":[]},"design_count":{"type":"integer","title":"Design Count","default":0}},"type":"object","required":["name","id","slug","created_at","updated_at"],"title":"ThemeOut","description":"`ThemeRecord` plus the server-only fields."},"ThemeStyle":{"properties":{"version":{"type":"string","const":"1","title":"Version","default":"1"},"palette":{"additionalProperties":{"type":"string"},"type":"object","title":"Palette","description":"Colour by palette role (rock_cool, lava, …), #rrggbb.","default":{}},"shape_language":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Shape Language"},"edge_treatment":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Edge Treatment"},"material_families":{"additionalProperties":{"type":"string"},"type":"object","title":"Material Families","description":"Surface role (ground, wall, path, surface, prop) → material family.","default":{}},"detail_scale":{"anyOf":[{"type":"string","enum":["low","medium","high"]},{"type":"null"}],"title":"Detail Scale"},"texture_scale_units":{"anyOf":[{"type":"number","exclusiveMinimum":0.0},{"type":"null"}],"title":"Texture Scale Units","description":"World units one texture tile covers."},"rendering":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Rendering"},"lighting":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lighting"},"reference_images":{"items":{"$ref":"#/components/schemas/StyleReferenceImage"},"type":"array","title":"Reference Images","default":[]},"evidence":{"items":{"$ref":"#/components/schemas/StyleEvidence"},"type":"array","title":"Evidence","default":[]}},"additionalProperties":false,"type":"object","title":"ThemeStyle","description":"The structured style profile a theme carries under `metadata.style`\n(SCBR-678): what it looks like, for planners to read and write. No column\nbehind it; the library validates the block on write."},"UserOut":{"properties":{"email":{"type":"string","title":"Email"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"}},"type":"object","required":["email","name"],"title":"UserOut"},"World":{"properties":{"constraints":{"$ref":"#/components/schemas/WorldConstraints"},"unit_scale":{"type":"number","exclusiveMinimum":0.0,"title":"Unit Scale","description":"Metres per world unit.","default":1.0},"padding":{"type":"number","minimum":0.0,"title":"Padding","description":"Clear space around the layout."},"min_path_width":{"type":"number","exclusiveMinimum":0.0,"title":"Min Path Width","description":"Narrowest walkable path."},"grid":{"anyOf":[{"$ref":"#/components/schemas/GridValues"},{"type":"null"}],"description":"Present iff horizontal is grid."},"levels":{"anyOf":[{"$ref":"#/components/schemas/LevelValues"},{"type":"null"}],"description":"Present iff vertical is quantized."},"heights":{"anyOf":[{"$ref":"#/components/schemas/HeightValues"},{"type":"null"}],"description":"Present iff vertical is continuous."}},"type":"object","required":["constraints","padding","min_path_width"],"title":"World","description":"Constraints first, then the values they unlock, then the unconditional\nones. A block is required when its constraint unlocks it and must be\nabsent otherwise. Walkable surfaces are flat under either vertical\nconstraint; `quantized` only says their heights are multiples of a level."},"WorldConstraints":{"properties":{"horizontal":{"type":"string","enum":["grid","organic"],"title":"Horizontal","description":"grid unlocks `grid`; organic unlocks nothing."},"vertical":{"type":"string","enum":["quantized","continuous"],"title":"Vertical","description":"quantized unlocks `levels`; continuous unlocks `heights`."}},"type":"object","required":["horizontal","vertical"],"title":"WorldConstraints","description":"The constraint block; each value unlocks a block of world values."},"ValidationIssue":{"description":"One field-level failure inside a 422 problem's ``errors`` extension.","properties":{"type":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Type"},"loc":{"default":[],"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"title":"Loc","type":"array"},"msg":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Msg"},"input":{"default":null,"title":"Input"},"ctx":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"default":null,"title":"Ctx"}},"title":"ValidationIssue","type":"object"},"Problem":{"additionalProperties":true,"description":"RFC 9457 problem document.\n\n``code`` is the machine-readable error code that also derives ``type``;\n``errors`` carries field-level validation failures on 422s. Problem types\nmay add further extension members, hence ``extra=\"allow\"``.","properties":{"type":{"default":"about:blank","title":"Type","type":"string"},"title":{"title":"Title","type":"string"},"status":{"title":"Status","type":"integer"},"detail":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Detail"},"instance":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Instance"},"code":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Code"},"errors":{"anyOf":[{"items":{"$ref":"#/components/schemas/ValidationIssue"},"type":"array"},{"type":"null"}],"default":null,"title":"Errors"}},"required":["title","status"],"title":"Problem","type":"object"},"ThemeRecord":{"description":"A theme as a container payload: what can be built. `world` is null\nwhile the theme has not declared its constraints (Architect refuses such\na theme); `scene_parameters` are defaults keyed by planning module;\n`metadata.style` is the style profile (`ThemeStyle`).","properties":{"name":{"title":"Name","type":"string"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Description"},"tags":{"default":[],"items":{"type":"string"},"title":"Tags","type":"array"},"metadata":{"$ref":"#/components/schemas/ThemeMetadata","default":{"style":null}},"world":{"anyOf":[{"$ref":"#/components/schemas/World"},{"type":"null"}],"default":null},"scene_parameters":{"additionalProperties":{"additionalProperties":true,"type":"object"},"default":{},"title":"Scene Parameters","type":"object"},"designs":{"default":[],"description":"Ordered design references.","items":{"$ref":"#/components/schemas/Reference"},"title":"Designs","type":"array"}},"required":["name"],"title":"ThemeRecord","type":"object"},"DesignRecord":{"description":"A design as a container payload: an ordered operator chain, one recipe\nper node.","properties":{"name":{"title":"Name","type":"string"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Description"},"tags":{"default":[],"items":{"type":"string"},"title":"Tags","type":"array"},"metadata":{"additionalProperties":true,"default":{},"title":"Metadata","type":"object"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"terrain, bridge, fence, ladder, stair, wall, …","title":"Type"},"recipes":{"default":[],"description":"Ordered recipe references.","items":{"$ref":"#/components/schemas/Reference"},"title":"Recipes","type":"array"}},"required":["name"],"title":"DesignRecord","type":"object"},"RecipeRecord":{"description":"A recipe as a container payload: one operator's slot values. The\nbrewer validates `parameters`; nothing here does.","properties":{"name":{"title":"Name","type":"string"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Description"},"tags":{"default":[],"items":{"type":"string"},"title":"Tags","type":"array"},"metadata":{"additionalProperties":true,"default":{},"title":"Metadata","type":"object"},"operator":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"Brewer node type (e.g. swf::terrain_blockout_tiles); null while the recipe type's operator is not ported.","title":"Operator"},"operator_version":{"anyOf":[{"pattern":"^\\d+\\.\\d+\\.\\d+$","type":"string"},{"type":"null"}],"default":null,"description":"Semver of the operator schema the parameters were written against.","title":"Operator Version"},"parameters":{"additionalProperties":true,"default":{},"title":"Parameters","type":"object"},"assets":{"additionalProperties":{"$ref":"#/components/schemas/Reference"},"default":{},"description":"Asset references keyed by operator slot.","title":"Assets","type":"object"}},"required":["name"],"title":"RecipeRecord","type":"object"},"AssetRecord":{"description":"An asset as a container payload: type, category, and its stored bytes\nby role (SCBR-678) — `mesh` for a mesh asset, one map per channel for a\nmaterial (`albedo`, `normal`, `roughness`, `height`, `metallic`, …),\n`texture` for a texture asset. Each attachment is inline or by the\ndigest-addressed route `/v1/assets/{id}/files/{role}?sha256=…`, which\nserves those bytes while they are retained, not the current binding.\nMesh assets carry `metadata.fit` (height, footprint, pivot, tier);\nmaterial assets own their maps and may reference standalone textures.","properties":{"name":{"title":"Name","type":"string"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Description"},"tags":{"default":[],"items":{"type":"string"},"title":"Tags","type":"array"},"metadata":{"additionalProperties":true,"default":{},"title":"Metadata","type":"object"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"mesh, material, texture, …","title":"Type"},"category":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Category"},"files":{"additionalProperties":{"$ref":"#/components/schemas/Attachment"},"default":{},"description":"The stored bytes by role.","title":"Files","type":"object"},"attachment":{"anyOf":[{"$ref":"#/components/schemas/Attachment"},{"type":"null"}],"default":null,"deprecated":true,"description":"A texture's image, as exports before SCBR-678 carried it; `files.texture` now."},"format":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Format"},"resolution":{"anyOf":[{"items":{"type":"integer"},"type":"array"},{"type":"null"}],"default":null,"title":"Resolution"},"shader_name":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Shader Name"},"shader_parameters":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"default":null,"title":"Shader Parameters"},"texture_refs":{"anyOf":[{"items":{"$ref":"#/components/schemas/MaterialTextureRef"},"type":"array"},{"type":"null"}],"default":null,"title":"Texture Refs"},"meshes":{"anyOf":[{"items":{"$ref":"#/components/schemas/MeshSlotRecord"},"type":"array"},{"type":"null"}],"default":null,"title":"Meshes"},"materials":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"default":null,"title":"Materials"},"textures":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"default":null,"title":"Textures"},"fallback_color":{"anyOf":[{"pattern":"^#[0-9a-f]{6}$","type":"string"},{"type":"null"}],"default":null,"description":"A material's colour where its maps are not drawn: the mean of its albedo map, sRGB `#rrggbb`. Read from the maps when they are stored; null while unknown.","title":"Fallback Color"},"normal_convention":{"anyOf":[{"enum":["opengl","directx"],"type":"string"},{"type":"null"}],"default":null,"description":"The green-channel convention of a material's normal map, read when it is stored. glTF expects `opengl`; a renderer flips a `directx` map's green channel. Null while unknown (no normal map, or an undecidable one).","title":"Normal Convention"}},"required":["name"],"title":"AssetRecord","type":"object"}},"securitySchemes":{"apiKey":{"type":"http","description":"First-party API key (sbk_live_…), presented as a Bearer token.","scheme":"bearer"}},"responses":{"Problem":{"description":"Any error: an RFC 9457 problem document.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}}