{
    "openapi": "3.1.0",
    "info": {
        "title": "Gavana Canvas API",
        "version": "1.0.0",
        "description": "The stable V1 API used by the Gavana browser, CLI, and MCP adapter to read canvases, apply revision-safe edits, manage durable assets, run Recipes and deterministic Image Actions, generate images and videos, and observe asynchronous work.",
        "x-craftboard-stability": "stable"
    },
    "servers": [
        {
            "url": "/api/canvas-agent/v1",
            "description": "Current Gavana origin"
        }
    ],
    "security": [
        {
            "agentToken": []
        }
    ],
    "tags": [
        {
            "name": "Authentication",
            "description": "Verify an Agent Access token without requiring an unrelated product scope."
        },
        {
            "name": "Canvases",
            "description": "Read canvases and apply revision-safe graph operations."
        },
        {
            "name": "Recipes",
            "description": "Discover, fork, and explicitly run approved or private Recipe workflows."
        },
        {
            "name": "Assets",
            "description": "Read durable assets and upload raster references."
        },
        {
            "name": "Actions",
            "description": "Discover and run deterministic, credit-free image transformations."
        },
        {
            "name": "Images",
            "description": "Queue image generation, editing, and variation jobs."
        },
        {
            "name": "Videos",
            "description": "Queue video generation from prompts, first and last frames, or reference images."
        },
        {
            "name": "Jobs",
            "description": "Observe or cancel image, Action, and video jobs and download completed video output."
        },
        {
            "name": "Runs",
            "description": "Read, resume, or cancel Recipe, image, and Action execution through one shared resource."
        },
        {
            "name": "Models",
            "description": "Discover runnable image and video models, capabilities, parameter schemas, and duration estimates."
        },
        {
            "name": "Providers",
            "description": "Discover saved image and video provider connections."
        },
        {
            "name": "Legacy campaigns",
            "description": "Deprecated compatibility endpoints. New integrations should use Recipes plus explicit canvas and image operations."
        }
    ],
    "paths": {
        "/auth/status": {
            "get": {
                "operationId": "getAuthStatus",
                "tags": ["Authentication"],
                "summary": "Verify the current Agent Access token",
                "description": "Authenticates the token and reports its granted scopes without requiring canvas, asset, image, or job access.",
                "x-craftboard-required-scopes": [],
                "x-craftboard-cli-command": "gavana auth status",
                "responses": {
                    "200": {
                        "$ref": "#/components/responses/AuthStatus"
                    },
                    "default": {
                        "$ref": "#/components/responses/Error"
                    }
                }
            }
        },
        "/actions": {
            "get": {
                "operationId": "listImageActions",
                "tags": ["Actions"],
                "summary": "List deterministic Image Actions",
                "description": "Returns typed schemas for the eight deterministic, credit-free raster transformations available in the browser, CLI, API, and MCP adapter.",
                "x-craftboard-required-scopes": ["canvas:read"],
                "x-craftboard-cli-command": "gavana action list",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/ActionQuery"
                    },
                    {
                        "$ref": "#/components/parameters/ListLimit100"
                    },
                    {
                        "$ref": "#/components/parameters/ListCursor"
                    }
                ],
                "responses": {
                    "200": {
                        "$ref": "#/components/responses/ActionList"
                    },
                    "default": {
                        "$ref": "#/components/responses/Error"
                    }
                }
            }
        },
        "/actions/{actionKey}": {
            "get": {
                "operationId": "getImageAction",
                "tags": ["Actions"],
                "summary": "Read one Image Action schema",
                "description": "Returns the exact ordered image inputs, typed parameters, defaults, limits, output contract, and cost behavior for one Action.",
                "x-craftboard-required-scopes": ["canvas:read"],
                "x-craftboard-cli-command": "gavana action get",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/ActionKey"
                    }
                ],
                "responses": {
                    "200": {
                        "$ref": "#/components/responses/Action"
                    },
                    "default": {
                        "$ref": "#/components/responses/Error"
                    }
                }
            }
        },
        "/actions/{actionKey}/runs": {
            "post": {
                "operationId": "startImageAction",
                "tags": ["Actions"],
                "summary": "Run a deterministic Image Action",
                "description": "Queues a credit-free raster transform against one or two durable node or asset handles. The result is stored as a durable asset and materialized in the selected target image node.",
                "x-craftboard-required-scopes": ["canvas:read", "canvas:write", "asset:read"],
                "x-craftboard-cli-command": "gavana action run",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/ActionKey"
                    }
                ],
                "requestBody": {
                    "$ref": "#/components/requestBodies/ImageActionRun"
                },
                "callbacks": {
                    "imageJobTerminal": {
                        "$ref": "#/components/callbacks/ImageJobTerminal"
                    }
                },
                "responses": {
                    "202": {
                        "$ref": "#/components/responses/Job"
                    },
                    "default": {
                        "$ref": "#/components/responses/Error"
                    }
                }
            }
        },
        "/assets": {
            "get": {
                "operationId": "listAssets",
                "tags": ["Assets"],
                "summary": "List accessible assets",
                "description": "Assets are ordered by updatedAt descending, then handle descending.",
                "x-craftboard-required-scopes": ["asset:read"],
                "x-craftboard-cli-command": "gavana asset list",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/CanvasIdQuery"
                    },
                    {
                        "$ref": "#/components/parameters/OwnerUidQuery"
                    },
                    {
                        "$ref": "#/components/parameters/ListLimit200"
                    },
                    {
                        "$ref": "#/components/parameters/ListCursor"
                    }
                ],
                "responses": {
                    "200": {
                        "$ref": "#/components/responses/AssetList"
                    },
                    "default": {
                        "$ref": "#/components/responses/Error"
                    }
                }
            },
            "post": {
                "operationId": "uploadAsset",
                "tags": ["Assets"],
                "summary": "Upload a durable raster reference",
                "description": "Uploads a private raster reference for image or video generation. When canvasId is supplied, canvas read/write scopes are also required and the upload is stored inside that canvas.",
                "x-craftboard-required-scopes": ["asset:read"],
                "x-craftboard-any-of-scopes": ["image:generate", "video:generate"],
                "x-craftboard-conditional-scopes": [
                    {
                        "when": "canvasId query parameter is present",
                        "scopes": ["canvas:read", "canvas:write"]
                    }
                ],
                "x-craftboard-cli-command": "gavana asset upload",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/CanvasIdQuery"
                    },
                    {
                        "$ref": "#/components/parameters/OwnerUidQuery"
                    },
                    {
                        "$ref": "#/components/parameters/FileNameHeader"
                    },
                    {
                        "$ref": "#/components/parameters/LegacyFileNameHeader"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/octet-stream": {
                            "schema": {
                                "type": "string",
                                "format": "binary"
                            }
                        },
                        "image/png": {
                            "schema": {
                                "type": "string",
                                "format": "binary"
                            }
                        },
                        "image/jpeg": {
                            "schema": {
                                "type": "string",
                                "format": "binary"
                            }
                        },
                        "image/webp": {
                            "schema": {
                                "type": "string",
                                "format": "binary"
                            }
                        },
                        "image/gif": {
                            "schema": {
                                "type": "string",
                                "format": "binary"
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "$ref": "#/components/responses/Asset"
                    },
                    "default": {
                        "$ref": "#/components/responses/Error"
                    }
                }
            }
        },
        "/assets/{assetId}": {
            "get": {
                "operationId": "getAsset",
                "tags": ["Assets"],
                "summary": "Get an accessible asset",
                "description": "For a shared asset, pass the ownerUid encoded in its owner-qualified handle. The CLI does this automatically.",
                "x-craftboard-required-scopes": ["asset:read"],
                "x-craftboard-cli-command": "gavana asset get",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/AssetId"
                    },
                    {
                        "$ref": "#/components/parameters/OwnerUidQuery"
                    }
                ],
                "responses": {
                    "200": {
                        "$ref": "#/components/responses/Asset"
                    },
                    "default": {
                        "$ref": "#/components/responses/Error"
                    }
                }
            }
        },
        "/assets/preview": {
            "get": {
                "operationId": "previewAsset",
                "tags": ["Assets"],
                "summary": "Read a short-lived scoped image preview",
                "description": "The encrypted preview token is the authorization grant for this endpoint. Agent bearer tokens are not accepted or required.",
                "security": [],
                "x-craftboard-required-scopes": [],
                "parameters": [
                    {
                        "$ref": "#/components/parameters/PreviewToken"
                    }
                ],
                "responses": {
                    "200": {
                        "$ref": "#/components/responses/BinaryImage"
                    },
                    "default": {
                        "$ref": "#/components/responses/Error"
                    }
                }
            }
        },
        "/campaigns": {
            "get": {
                "operationId": "listLegacyCampaignRuns",
                "tags": ["Legacy campaigns"],
                "summary": "List legacy campaign runs",
                "deprecated": true,
                "x-craftboard-required-scopes": ["canvas:read", "canvas:write", "asset:read", "image:generate", "job:manage"],
                "parameters": [
                    {
                        "$ref": "#/components/parameters/CanvasIdQuery"
                    }
                ],
                "responses": {
                    "200": {
                        "$ref": "#/components/responses/CampaignList"
                    },
                    "default": {
                        "$ref": "#/components/responses/Error"
                    }
                }
            }
        },
        "/campaigns/{runId}": {
            "get": {
                "operationId": "getLegacyCampaignRun",
                "tags": ["Legacy campaigns"],
                "summary": "Get a legacy campaign run",
                "deprecated": true,
                "x-craftboard-required-scopes": ["canvas:read", "canvas:write", "asset:read", "image:generate", "job:manage"],
                "parameters": [
                    {
                        "$ref": "#/components/parameters/RunId"
                    }
                ],
                "responses": {
                    "200": {
                        "$ref": "#/components/responses/Campaign"
                    },
                    "default": {
                        "$ref": "#/components/responses/Error"
                    }
                }
            },
            "delete": {
                "operationId": "cancelLegacyCampaignRun",
                "tags": ["Legacy campaigns"],
                "summary": "Cancel a legacy campaign run",
                "description": "Retired mutation surface. Returns 410 unless legacy compatibility is explicitly enabled by the server operator.",
                "deprecated": true,
                "x-craftboard-runtime": "legacy-compatibility",
                "x-craftboard-required-scopes": ["canvas:read", "canvas:write", "asset:read", "image:generate", "job:manage"],
                "parameters": [
                    {
                        "$ref": "#/components/parameters/RunId"
                    }
                ],
                "responses": {
                    "200": {
                        "$ref": "#/components/responses/Campaign"
                    },
                    "410": {
                        "$ref": "#/components/responses/Error"
                    },
                    "default": {
                        "$ref": "#/components/responses/Error"
                    }
                }
            }
        },
        "/campaigns/{runId}/review": {
            "post": {
                "operationId": "reviewLegacyCampaignRun",
                "tags": ["Legacy campaigns"],
                "summary": "Review a legacy campaign run",
                "description": "Retired mutation surface. Returns 410 unless legacy compatibility is explicitly enabled by the server operator.",
                "deprecated": true,
                "x-craftboard-runtime": "legacy-compatibility",
                "x-craftboard-required-scopes": ["canvas:read", "canvas:write", "asset:read", "image:generate", "job:manage"],
                "parameters": [
                    {
                        "$ref": "#/components/parameters/RunId"
                    }
                ],
                "requestBody": {
                    "$ref": "#/components/requestBodies/LegacyCampaign"
                },
                "responses": {
                    "200": {
                        "$ref": "#/components/responses/Campaign"
                    },
                    "202": {
                        "$ref": "#/components/responses/Campaign"
                    },
                    "410": {
                        "$ref": "#/components/responses/Error"
                    },
                    "default": {
                        "$ref": "#/components/responses/Error"
                    }
                }
            }
        },
        "/campaigns/plan": {
            "post": {
                "operationId": "planLegacyCampaign",
                "tags": ["Legacy campaigns"],
                "summary": "Plan a legacy campaign",
                "description": "Retired mutation surface. Returns 410 unless legacy compatibility is explicitly enabled by the server operator.",
                "deprecated": true,
                "x-craftboard-runtime": "legacy-compatibility",
                "x-craftboard-required-scopes": ["canvas:read", "canvas:write", "asset:read"],
                "requestBody": {
                    "$ref": "#/components/requestBodies/LegacyCampaign"
                },
                "responses": {
                    "200": {
                        "$ref": "#/components/responses/Campaign"
                    },
                    "201": {
                        "$ref": "#/components/responses/Campaign"
                    },
                    "410": {
                        "$ref": "#/components/responses/Error"
                    },
                    "default": {
                        "$ref": "#/components/responses/Error"
                    }
                }
            }
        },
        "/campaigns/start": {
            "post": {
                "operationId": "startLegacyCampaign",
                "tags": ["Legacy campaigns"],
                "summary": "Start a legacy campaign",
                "description": "Retired mutation surface. Returns 410 unless legacy compatibility is explicitly enabled by the server operator.",
                "deprecated": true,
                "x-craftboard-runtime": "legacy-compatibility",
                "x-craftboard-required-scopes": ["canvas:read", "canvas:write", "asset:read", "image:generate", "job:manage"],
                "requestBody": {
                    "$ref": "#/components/requestBodies/LegacyCampaign"
                },
                "responses": {
                    "200": {
                        "$ref": "#/components/responses/Campaign"
                    },
                    "202": {
                        "$ref": "#/components/responses/Campaign"
                    },
                    "410": {
                        "$ref": "#/components/responses/Error"
                    },
                    "default": {
                        "$ref": "#/components/responses/Error"
                    }
                }
            }
        },
        "/canvases": {
            "get": {
                "operationId": "listCanvases",
                "tags": ["Canvases"],
                "summary": "List accessible canvases",
                "description": "Owned and shared canvases are merged and ordered by updatedAt descending, then handle descending.",
                "x-craftboard-required-scopes": ["canvas:read"],
                "x-craftboard-cli-command": "gavana canvas list",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/ListLimit25"
                    },
                    {
                        "$ref": "#/components/parameters/ListCursor"
                    }
                ],
                "responses": {
                    "200": {
                        "$ref": "#/components/responses/CanvasList"
                    },
                    "default": {
                        "$ref": "#/components/responses/Error"
                    }
                }
            },
            "post": {
                "operationId": "createCanvas",
                "tags": ["Canvases"],
                "summary": "Create a canvas or resolve Agent Canvas",
                "x-craftboard-required-scopes": ["canvas:read", "canvas:write"],
                "x-craftboard-cli-command": "gavana canvas create",
                "requestBody": {
                    "$ref": "#/components/requestBodies/CanvasCreate"
                },
                "responses": {
                    "201": {
                        "$ref": "#/components/responses/Canvas"
                    },
                    "default": {
                        "$ref": "#/components/responses/Error"
                    }
                }
            }
        },
        "/canvases/{canvasId}": {
            "get": {
                "operationId": "getCanvas",
                "tags": ["Canvases"],
                "summary": "Get a complete canvas and its current revision",
                "x-craftboard-required-scopes": ["canvas:read"],
                "x-craftboard-cli-command": "gavana canvas get",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/CanvasId"
                    },
                    {
                        "$ref": "#/components/parameters/OwnerUidQuery"
                    }
                ],
                "responses": {
                    "200": {
                        "$ref": "#/components/responses/Canvas"
                    },
                    "default": {
                        "$ref": "#/components/responses/Error"
                    }
                }
            }
        },
        "/canvases/{canvasId}/nodes/{nodeId}": {
            "get": {
                "operationId": "getCanvasNode",
                "tags": ["Canvases"],
                "summary": "Get one node with incoming and outgoing connections",
                "x-craftboard-required-scopes": ["canvas:read"],
                "x-craftboard-cli-command": "gavana node get",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/CanvasId"
                    },
                    {
                        "$ref": "#/components/parameters/NodeId"
                    },
                    {
                        "$ref": "#/components/parameters/OwnerUidQuery"
                    }
                ],
                "responses": {
                    "200": {
                        "$ref": "#/components/responses/GenericObject"
                    },
                    "default": {
                        "$ref": "#/components/responses/Error"
                    }
                }
            }
        },
        "/canvases/{canvasId}/operations": {
            "post": {
                "operationId": "applyCanvasOperations",
                "tags": ["Canvases"],
                "summary": "Validate or apply one revision-safe operation batch",
                "description": "Set validateOnly to true to run the canonical operation engine and graph validator without writing, consuming an idempotency key, or requiring canvas:write. For mutation, read the canvas first, pass its revision as baseRevision, and provide an idempotencyKey. A 409 response includes the current revision when another actor changed the canvas.",
                "x-craftboard-required-scopes": ["canvas:read"],
                "x-craftboard-conditional-scopes": [
                    {
                        "when": "validateOnly is not true",
                        "scopes": ["canvas:write"]
                    }
                ],
                "x-craftboard-cli-command": "gavana canvas apply",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/CanvasId"
                    },
                    {
                        "$ref": "#/components/parameters/OwnerUidQuery"
                    }
                ],
                "requestBody": {
                    "$ref": "#/components/requestBodies/CanvasOperations"
                },
                "responses": {
                    "200": {
                        "$ref": "#/components/responses/CanvasOperationsResult"
                    },
                    "409": {
                        "$ref": "#/components/responses/Error"
                    },
                    "default": {
                        "$ref": "#/components/responses/Error"
                    }
                }
            }
        },
        "/canvases/{canvasId}/workflows": {
            "post": {
                "operationId": "createCanvasWorkflow",
                "tags": ["Recipes"],
                "summary": "Create a private reusable workflow without running it",
                "description": "Creates the workflow graph, a private Recipe draft, and a compact runnable Recipe instance. Inputs marked useAsDefault reuse their saved source on later runs, so callers only need to provide changing inputs. This operation does not start generation or consume provider credits.",
                "x-craftboard-required-scopes": ["canvas:read", "canvas:write"],
                "parameters": [
                    {
                        "$ref": "#/components/parameters/CanvasId"
                    },
                    {
                        "$ref": "#/components/parameters/OwnerUidQuery"
                    }
                ],
                "requestBody": {
                    "$ref": "#/components/requestBodies/CanvasWorkflowCreate"
                },
                "responses": {
                    "200": {
                        "$ref": "#/components/responses/WorkflowMutation"
                    },
                    "201": {
                        "$ref": "#/components/responses/WorkflowMutation"
                    },
                    "default": {
                        "$ref": "#/components/responses/Error"
                    }
                }
            }
        },
        "/canvases/{canvasId}/render": {
            "get": {
                "operationId": "renderCanvasSvg",
                "tags": ["Canvases"],
                "summary": "Render a canvas as SVG",
                "x-craftboard-required-scopes": ["canvas:read"],
                "x-craftboard-cli-command": "gavana canvas render",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/CanvasId"
                    },
                    {
                        "$ref": "#/components/parameters/OwnerUidQuery"
                    }
                ],
                "responses": {
                    "200": {
                        "$ref": "#/components/responses/Svg"
                    },
                    "default": {
                        "$ref": "#/components/responses/Error"
                    }
                }
            }
        },
        "/images/edit": {
            "post": {
                "operationId": "startImageEdit",
                "tags": ["Images"],
                "summary": "Queue an image edit",
                "x-craftboard-required-scopes": ["canvas:read", "canvas:write", "asset:read", "image:generate"],
                "x-craftboard-cli-command": "gavana image edit",
                "requestBody": {
                    "$ref": "#/components/requestBodies/ImageEdit"
                },
                "callbacks": {
                    "imageJobTerminal": {
                        "$ref": "#/components/callbacks/ImageJobTerminal"
                    }
                },
                "responses": {
                    "202": {
                        "$ref": "#/components/responses/Job"
                    },
                    "default": {
                        "$ref": "#/components/responses/Error"
                    }
                }
            }
        },
        "/images/generate": {
            "post": {
                "operationId": "startImageGeneration",
                "tags": ["Images"],
                "summary": "Queue image generation",
                "x-craftboard-required-scopes": ["canvas:read", "canvas:write", "asset:read", "image:generate"],
                "x-craftboard-cli-command": "gavana image generate",
                "requestBody": {
                    "$ref": "#/components/requestBodies/ImageGeneration"
                },
                "callbacks": {
                    "imageJobTerminal": {
                        "$ref": "#/components/callbacks/ImageJobTerminal"
                    }
                },
                "responses": {
                    "202": {
                        "$ref": "#/components/responses/Job"
                    },
                    "default": {
                        "$ref": "#/components/responses/Error"
                    }
                }
            }
        },
        "/images/import": {
            "post": {
                "operationId": "importImageToCanvas",
                "tags": ["Images"],
                "summary": "Import a public HTTPS image as a durable canvas node",
                "description": "Downloads a bounded raster image through Gavana's SSRF-safe fetcher, stores it as a canvas-scoped asset, and adds one deterministic image node. Reuse the idempotency key only for the exact same import.",
                "x-craftboard-required-scopes": ["canvas:read", "canvas:write", "asset:read", "image:generate"],
                "requestBody": {
                    "$ref": "#/components/requestBodies/ImageImport"
                },
                "responses": {
                    "200": {
                        "$ref": "#/components/responses/ImageImport"
                    },
                    "default": {
                        "$ref": "#/components/responses/Error"
                    }
                }
            }
        },
        "/images/variations": {
            "post": {
                "operationId": "startImageVariations",
                "tags": ["Images"],
                "summary": "Queue image variations",
                "x-craftboard-required-scopes": ["canvas:read", "canvas:write", "asset:read", "image:generate"],
                "x-craftboard-cli-command": "gavana image variations",
                "requestBody": {
                    "$ref": "#/components/requestBodies/ImageVariations"
                },
                "callbacks": {
                    "imageJobTerminal": {
                        "$ref": "#/components/callbacks/ImageJobTerminal"
                    }
                },
                "responses": {
                    "202": {
                        "$ref": "#/components/responses/Job"
                    },
                    "default": {
                        "$ref": "#/components/responses/Error"
                    }
                }
            }
        },
        "/videos/generate": {
            "post": {
                "operationId": "startVideoGeneration",
                "tags": ["Videos"],
                "summary": "Queue video generation",
                "description": "Starts a retry-safe video job using a connected video model. First, last, and reference frames may be stable image node or asset handles, or public HTTPS image URLs.",
                "x-craftboard-required-scopes": ["canvas:read", "asset:read", "video:generate"],
                "x-craftboard-cli-command": "gavana video generate",
                "requestBody": {
                    "$ref": "#/components/requestBodies/VideoGeneration"
                },
                "responses": {
                    "202": {
                        "$ref": "#/components/responses/Job"
                    },
                    "default": {
                        "$ref": "#/components/responses/Error"
                    }
                }
            }
        },
        "/jobs/{jobId}": {
            "get": {
                "operationId": "getJob",
                "tags": ["Jobs"],
                "summary": "Read or finalize an image, Action, or video job",
                "x-craftboard-required-scopes": ["job:manage"],
                "x-craftboard-cli-command": "gavana job get",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/JobId"
                    }
                ],
                "responses": {
                    "200": {
                        "$ref": "#/components/responses/Job"
                    },
                    "202": {
                        "$ref": "#/components/responses/Job"
                    },
                    "default": {
                        "$ref": "#/components/responses/Error"
                    }
                }
            },
            "delete": {
                "operationId": "cancelJob",
                "tags": ["Jobs"],
                "summary": "Cancel an image, Action, or video job",
                "x-craftboard-required-scopes": ["job:manage"],
                "x-craftboard-cli-command": "gavana job cancel",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/JobId"
                    }
                ],
                "responses": {
                    "200": {
                        "$ref": "#/components/responses/Job"
                    },
                    "202": {
                        "$ref": "#/components/responses/Job"
                    },
                    "default": {
                        "$ref": "#/components/responses/Error"
                    }
                }
            }
        },
        "/jobs/{jobId}/output": {
            "get": {
                "operationId": "downloadVideoJobOutput",
                "tags": ["Jobs", "Videos"],
                "summary": "Download completed video output",
                "x-craftboard-required-scopes": ["job:manage"],
                "x-craftboard-cli-command": "gavana video download",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/JobId"
                    }
                ],
                "responses": {
                    "200": {
                        "$ref": "#/components/responses/VideoOutput"
                    },
                    "default": {
                        "$ref": "#/components/responses/Error"
                    }
                }
            }
        },
        "/models": {
            "get": {
                "operationId": "listModels",
                "tags": ["Models"],
                "summary": "List runnable image and video models",
                "description": "Returns models Gavana can invoke through the managed runtime or the actor's saved connections.",
                "x-craftboard-required-scopes": [],
                "x-craftboard-any-of-scopes": ["image:generate", "video:generate"],
                "x-craftboard-cli-command": "gavana model list",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/ModelQuery"
                    },
                    {
                        "$ref": "#/components/parameters/ModelProviderQuery"
                    },
                    {
                        "$ref": "#/components/parameters/ModelCapabilityQuery"
                    },
                    {
                        "$ref": "#/components/parameters/ListLimit100"
                    },
                    {
                        "$ref": "#/components/parameters/ListCursor"
                    }
                ],
                "responses": {
                    "200": {
                        "$ref": "#/components/responses/ModelList"
                    },
                    "default": {
                        "$ref": "#/components/responses/Error"
                    }
                }
            }
        },
        "/models/{modelKey}": {
            "get": {
                "operationId": "getModel",
                "tags": ["Models"],
                "summary": "Read an image or video model schema",
                "x-craftboard-required-scopes": [],
                "x-craftboard-any-of-scopes": ["image:generate", "video:generate"],
                "x-craftboard-cli-command": "gavana model get",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/ModelKey"
                    }
                ],
                "responses": {
                    "200": {
                        "$ref": "#/components/responses/Model"
                    },
                    "default": {
                        "$ref": "#/components/responses/Error"
                    }
                }
            }
        },
        "/providers": {
            "get": {
                "operationId": "listProviders",
                "tags": ["Providers"],
                "summary": "List saved image and video provider connections",
                "x-craftboard-required-scopes": [],
                "x-craftboard-any-of-scopes": ["image:generate", "video:generate"],
                "x-craftboard-cli-command": "gavana provider list",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/ListLimit100"
                    },
                    {
                        "$ref": "#/components/parameters/ListCursor"
                    }
                ],
                "responses": {
                    "200": {
                        "$ref": "#/components/responses/ProviderList"
                    },
                    "default": {
                        "$ref": "#/components/responses/Error"
                    }
                }
            }
        },
        "/recipes": {
            "get": {
                "operationId": "searchRecipes",
                "tags": ["Recipes"],
                "summary": "Search approved Recipes",
                "x-craftboard-required-scopes": ["canvas:read"],
                "x-craftboard-cli-command": "gavana recipe search",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/RecipeQuery"
                    },
                    {
                        "$ref": "#/components/parameters/ListLimit100"
                    },
                    {
                        "$ref": "#/components/parameters/ListCursor"
                    }
                ],
                "responses": {
                    "200": {
                        "$ref": "#/components/responses/RecipeList"
                    },
                    "default": {
                        "$ref": "#/components/responses/Error"
                    }
                }
            }
        },
        "/recipes/{recipeId}": {
            "get": {
                "operationId": "getRecipe",
                "tags": ["Recipes"],
                "summary": "Get an approved Recipe",
                "x-craftboard-required-scopes": ["canvas:read"],
                "x-craftboard-cli-command": "gavana recipe get",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/RecipeId"
                    },
                    {
                        "$ref": "#/components/parameters/RecipeVersionQuery"
                    }
                ],
                "responses": {
                    "200": {
                        "$ref": "#/components/responses/Recipe"
                    },
                    "default": {
                        "$ref": "#/components/responses/Error"
                    }
                }
            }
        },
        "/recipes/{recipeId}/fork": {
            "post": {
                "operationId": "forkRecipe",
                "tags": ["Recipes"],
                "summary": "Fork a Recipe into a canvas without running it",
                "x-craftboard-required-scopes": ["canvas:read", "canvas:write"],
                "x-craftboard-cli-command": "gavana recipe fork",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/RecipeId"
                    }
                ],
                "requestBody": {
                    "$ref": "#/components/requestBodies/RecipeFork"
                },
                "responses": {
                    "200": {
                        "$ref": "#/components/responses/Mutation"
                    },
                    "201": {
                        "$ref": "#/components/responses/Mutation"
                    },
                    "default": {
                        "$ref": "#/components/responses/Error"
                    }
                }
            }
        },
        "/recipes/{recipeId}/runs": {
            "post": {
                "operationId": "startRecipeRun",
                "tags": ["Recipes", "Runs"],
                "summary": "Run a Recipe explicitly",
                "description": "Creates or reuses a private Recipe instance, binds typed inputs, materializes declared output nodes, and queues sequential text or image work. Forking a Recipe never calls this operation automatically.",
                "x-craftboard-required-scopes": ["canvas:read", "canvas:write", "asset:read", "image:generate"],
                "x-craftboard-cli-command": "gavana recipe run",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/RecipeId"
                    }
                ],
                "requestBody": {
                    "$ref": "#/components/requestBodies/RecipeRun"
                },
                "callbacks": {
                    "recipeRunTerminal": {
                        "$ref": "#/components/callbacks/RecipeRunTerminal"
                    }
                },
                "responses": {
                    "202": {
                        "$ref": "#/components/responses/RecipeRun"
                    },
                    "default": {
                        "$ref": "#/components/responses/Error"
                    }
                }
            }
        },
        "/runs/{runId}": {
            "get": {
                "operationId": "getRun",
                "tags": ["Runs"],
                "summary": "Read or advance a shared Run",
                "description": "Returns Recipe, image, or Action Run state. Reading a completed image child also finalizes its durable asset and canvas node.",
                "x-craftboard-required-scopes": ["job:manage"],
                "x-craftboard-cli-command": "gavana run get",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/RunId"
                    }
                ],
                "responses": {
                    "200": {
                        "$ref": "#/components/responses/Run"
                    },
                    "202": {
                        "$ref": "#/components/responses/Run"
                    },
                    "default": {
                        "$ref": "#/components/responses/Error"
                    }
                }
            },
            "delete": {
                "operationId": "cancelRun",
                "tags": ["Runs"],
                "summary": "Cancel a shared Run",
                "x-craftboard-required-scopes": ["job:manage"],
                "x-craftboard-cli-command": "gavana run cancel",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/RunId"
                    }
                ],
                "responses": {
                    "200": {
                        "$ref": "#/components/responses/Run"
                    },
                    "202": {
                        "$ref": "#/components/responses/Run"
                    },
                    "default": {
                        "$ref": "#/components/responses/Error"
                    }
                }
            }
        }
    },
    "components": {
        "securitySchemes": {
            "agentToken": {
                "type": "http",
                "scheme": "bearer",
                "bearerFormat": "cba_<token-id>.<secret>",
                "description": "Create a scoped Agent Access Token in Gavana settings. Never place the token in a URL or support message."
            }
        },
        "parameters": {
            "ActionKey": {
                "name": "actionKey",
                "in": "path",
                "required": true,
                "description": "An Action slug or action:<slug> handle returned by GET /actions.",
                "schema": {
                    "type": "string",
                    "pattern": "^(?:action:)?(?:resize|crop|change-aspect-ratio|side-by-side-composite|add-text-to-image|overlay-image|color-grade|rotate)$"
                }
            },
            "ActionQuery": {
                "name": "q",
                "in": "query",
                "required": false,
                "description": "Free-text Action slug, title, or summary search.",
                "schema": {
                    "type": "string",
                    "maxLength": 240
                }
            },
            "AssetId": {
                "name": "assetId",
                "in": "path",
                "required": true,
                "schema": {
                    "type": "string",
                    "pattern": "^(?:asset:)?[A-Za-z0-9_-]{1,180}$"
                }
            },
            "CanvasId": {
                "name": "canvasId",
                "in": "path",
                "required": true,
                "schema": {
                    "$ref": "#/components/schemas/StableId"
                }
            },
            "CanvasIdQuery": {
                "name": "canvasId",
                "in": "query",
                "required": false,
                "description": "Optional plain canvas id used to filter or scope the request.",
                "schema": {
                    "$ref": "#/components/schemas/StableId"
                }
            },
            "FileNameHeader": {
                "name": "X-Gavana-File-Name",
                "in": "header",
                "required": false,
                "schema": {
                    "type": "string",
                    "maxLength": 255
                }
            },
            "LegacyFileNameHeader": {
                "name": "X-Craftboard-File-Name",
                "in": "header",
                "required": false,
                "deprecated": true,
                "description": "Legacy alias for X-Gavana-File-Name.",
                "schema": {
                    "type": "string",
                    "maxLength": 255
                }
            },
            "JobId": {
                "name": "jobId",
                "in": "path",
                "required": true,
                "schema": {
                    "type": "string",
                    "pattern": "^(?:job:)?[0-9a-fA-F-]{36}$"
                }
            },
            "ListCursor": {
                "name": "cursor",
                "in": "query",
                "required": false,
                "description": "Opaque continuation cursor from page.nextCursor. Reuse it with the same list filters.",
                "schema": {
                    "type": "string",
                    "maxLength": 8192
                }
            },
            "ListLimit100": {
                "name": "limit",
                "in": "query",
                "required": false,
                "description": "Maximum number of items in this page.",
                "schema": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 100
                }
            },
            "ListLimit25": {
                "name": "limit",
                "in": "query",
                "required": false,
                "description": "Maximum number of canvases in this page. Canvas pages are capped at 25 because summaries are derived from complete graph documents.",
                "schema": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 25,
                    "default": 25
                }
            },
            "ListLimit200": {
                "name": "limit",
                "in": "query",
                "required": false,
                "description": "Maximum number of items in this page.",
                "schema": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 200
                }
            },
            "ModelCapabilityQuery": {
                "name": "capability",
                "in": "query",
                "required": false,
                "schema": {
                    "type": "string",
                    "enum": ["image.generate", "image.edit", "image.variations", "video.generate", "video.generate.fromImage", "video.generate.fromFrames", "video.generate.fromReferences"]
                }
            },
            "ModelKey": {
                "name": "modelKey",
                "in": "path",
                "required": true,
                "description": "Opaque key from a model:<key> handle.",
                "schema": {
                    "type": "string",
                    "pattern": "^[A-Za-z0-9_-]{8,600}$"
                }
            },
            "ModelProviderQuery": {
                "name": "provider",
                "in": "query",
                "required": false,
                "schema": {
                    "type": "string",
                    "maxLength": 80
                }
            },
            "ModelQuery": {
                "name": "q",
                "in": "query",
                "required": false,
                "description": "Free-text model, provider, connection, or capability search.",
                "schema": {
                    "type": "string",
                    "maxLength": 240
                }
            },
            "NodeId": {
                "name": "nodeId",
                "in": "path",
                "required": true,
                "schema": {
                    "type": "string",
                    "pattern": "^(?:node:)?[A-Za-z0-9_-]{1,180}$"
                }
            },
            "OwnerUidQuery": {
                "name": "ownerUid",
                "in": "query",
                "required": false,
                "description": "Identifies the owner of a shared canvas or asset. Owner-qualified handles let the CLI supply it automatically.",
                "schema": {
                    "$ref": "#/components/schemas/StableId"
                }
            },
            "PreviewToken": {
                "name": "token",
                "in": "query",
                "required": true,
                "schema": {
                    "type": "string",
                    "minLength": 1
                }
            },
            "RecipeId": {
                "name": "recipeId",
                "in": "path",
                "required": true,
                "schema": {
                    "$ref": "#/components/schemas/StableId"
                }
            },
            "RecipeQuery": {
                "name": "q",
                "in": "query",
                "required": false,
                "description": "Free-text Recipe Library search.",
                "schema": {
                    "type": "string",
                    "maxLength": 500
                }
            },
            "RecipeVersionQuery": {
                "name": "version",
                "in": "query",
                "required": false,
                "description": "Optional immutable Recipe version.",
                "schema": {
                    "type": "string",
                    "maxLength": 80
                }
            },
            "RunId": {
                "name": "runId",
                "in": "path",
                "required": true,
                "schema": {
                    "type": "string",
                    "pattern": "^(?:run:)?[A-Za-z0-9_-]{1,180}$"
                }
            }
        },
        "headers": {
            "RequestId": {
                "description": "Safe correlation id for support and server logs.",
                "schema": {
                    "type": "string",
                    "format": "uuid"
                }
            }
        },
        "callbacks": {
            "ImageJobTerminal": {
                "{$request.body#/webhook/url}": {
                    "post": {
                        "summary": "Receive a signed terminal image-job event",
                        "description": "Gavana signs `${timestamp}.${rawBody}` with HMAC-SHA256 and the caller-owned secret. Return any 2xx response to acknowledge delivery. Delivery uses four total attempts. Retryable network failures and 408, 425, 429, or 5xx responses back off for 10 seconds, 60 seconds, then 5 minutes; redirects and other 4xx responses stop delivery. Successful Image and Action callbacks already contain durable asset and node handles in `data.run.images`, so callback-only clients do not need a follow-up GET. A caller with `job:manage` may read the shared Run later for inspection. Successful image and Action results retain their temporary observation record for 24 hours before the first successful server finalization and 15 minutes after it; an authenticated Run GET or pre-callback worker finalization both count. Failed and canceled records keep the normal 24-hour window.",
                        "parameters": [
                            {
                                "in": "header",
                                "name": "Gavana-Webhook-Id",
                                "required": true,
                                "schema": {
                                    "type": "string",
                                    "pattern": "^webhook:"
                                }
                            },
                            {
                                "in": "header",
                                "name": "Gavana-Webhook-Timestamp",
                                "required": true,
                                "schema": {
                                    "type": "string",
                                    "pattern": "^\\d{10,13}$"
                                }
                            },
                            {
                                "in": "header",
                                "name": "Gavana-Webhook-Signature",
                                "required": true,
                                "schema": {
                                    "type": "string",
                                    "pattern": "^t=\\d{10,13},v1=[0-9a-f]{64}$"
                                }
                            }
                        ],
                        "requestBody": {
                            "required": true,
                            "content": {
                                "application/json": {
                                    "schema": {
                                        "$ref": "#/components/schemas/ImageJobWebhookEvent"
                                    }
                                }
                            }
                        },
                        "responses": {
                            "2XX": {
                                "description": "The event was accepted. Any 2xx response acknowledges delivery."
                            }
                        }
                    }
                }
            },
            "RecipeRunTerminal": {
                "{$request.body#/webhook/url}": {
                    "post": {
                        "summary": "Receive a signed terminal Recipe Run event",
                        "description": "Gavana signs `${timestamp}.${rawBody}` with HMAC-SHA256 and the caller-owned secret. Return any 2xx response to acknowledge delivery. Delivery uses four total attempts. Retryable network failures and 408, 425, 429, or 5xx responses back off for 10 seconds, 60 seconds, then 5 minutes; redirects and other 4xx responses stop delivery. Private-network destinations are blocked.",
                        "parameters": [
                            {
                                "in": "header",
                                "name": "Gavana-Webhook-Id",
                                "required": true,
                                "schema": {
                                    "type": "string",
                                    "pattern": "^webhook:"
                                }
                            },
                            {
                                "in": "header",
                                "name": "Gavana-Webhook-Timestamp",
                                "required": true,
                                "schema": {
                                    "type": "string",
                                    "pattern": "^\\d{10,13}$"
                                }
                            },
                            {
                                "in": "header",
                                "name": "Gavana-Webhook-Signature",
                                "required": true,
                                "schema": {
                                    "type": "string",
                                    "pattern": "^t=\\d{10,13},v1=[0-9a-f]{64}$"
                                }
                            }
                        ],
                        "requestBody": {
                            "required": true,
                            "content": {
                                "application/json": {
                                    "schema": {
                                        "$ref": "#/components/schemas/RecipeRunWebhookEvent"
                                    }
                                }
                            }
                        },
                        "responses": {
                            "2XX": {
                                "description": "The event was accepted. Any 2xx response acknowledges delivery."
                            }
                        }
                    }
                }
            }
        },
        "requestBodies": {
            "CanvasCreate": {
                "required": true,
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/CanvasCreateInput"
                        }
                    }
                }
            },
            "CanvasOperations": {
                "required": true,
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/CanvasOperationsInput"
                        }
                    }
                }
            },
            "CanvasWorkflowCreate": {
                "required": true,
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/CanvasWorkflowCreateInput"
                        }
                    }
                }
            },
            "ImageActionRun": {
                "required": true,
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/ImageActionRunInput"
                        }
                    }
                }
            },
            "ImageEdit": {
                "required": true,
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/ImageEditInput"
                        }
                    }
                }
            },
            "ImageGeneration": {
                "required": true,
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/ImageGenerationInput"
                        }
                    }
                }
            },
            "ImageImport": {
                "required": true,
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/ImageImportInput"
                        }
                    }
                }
            },
            "ImageVariations": {
                "required": true,
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/ImageVariationsInput"
                        }
                    }
                }
            },
            "VideoGeneration": {
                "required": true,
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/VideoGenerationInput"
                        }
                    }
                }
            },
            "LegacyCampaign": {
                "required": true,
                "content": {
                    "application/json": {
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    }
                }
            },
            "RecipeFork": {
                "required": true,
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/RecipeForkInput"
                        }
                    }
                }
            },
            "RecipeRun": {
                "required": true,
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/RecipeRunInput"
                        }
                    }
                }
            }
        },
        "responses": {
            "Action": {
                "description": "One deterministic Image Action with its typed input and parameter schema.",
                "headers": {
                    "X-Request-ID": {
                        "$ref": "#/components/headers/RequestId"
                    }
                },
                "content": {
                    "application/json": {
                        "schema": {
                            "type": "object",
                            "required": ["action"],
                            "properties": {
                                "action": {
                                    "$ref": "#/components/schemas/ImageAction"
                                }
                            },
                            "additionalProperties": false
                        }
                    }
                }
            },
            "ActionList": {
                "description": "Deterministic Image Actions with typed schemas and pagination.",
                "headers": {
                    "X-Request-ID": {
                        "$ref": "#/components/headers/RequestId"
                    }
                },
                "content": {
                    "application/json": {
                        "schema": {
                            "type": "object",
                            "required": ["actions", "page"],
                            "properties": {
                                "actions": {
                                    "type": "array",
                                    "items": {
                                        "$ref": "#/components/schemas/ImageAction"
                                    }
                                },
                                "page": {
                                    "$ref": "#/components/schemas/CursorPage"
                                }
                            },
                            "additionalProperties": false
                        }
                    }
                }
            },
            "AuthStatus": {
                "description": "The authenticated identity and Agent Access scopes. No token secret is returned.",
                "headers": {
                    "X-Request-ID": {
                        "$ref": "#/components/headers/RequestId"
                    }
                },
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/AuthStatus"
                        }
                    }
                }
            },
            "Asset": {
                "description": "A durable asset.",
                "headers": {
                    "X-Request-ID": {
                        "$ref": "#/components/headers/RequestId"
                    }
                },
                "content": {
                    "application/json": {
                        "schema": {
                            "type": "object",
                            "required": ["asset"],
                            "properties": {
                                "asset": {
                                    "$ref": "#/components/schemas/Asset"
                                }
                            }
                        }
                    }
                }
            },
            "AssetList": {
                "description": "Accessible durable assets.",
                "headers": {
                    "X-Request-ID": {
                        "$ref": "#/components/headers/RequestId"
                    }
                },
                "content": {
                    "application/json": {
                        "schema": {
                            "type": "object",
                            "required": ["assets", "page"],
                            "properties": {
                                "assets": {
                                    "type": "array",
                                    "items": {
                                        "$ref": "#/components/schemas/Asset"
                                    }
                                },
                                "page": {
                                    "$ref": "#/components/schemas/CursorPage"
                                }
                            }
                        }
                    }
                }
            },
            "BinaryImage": {
                "description": "A proxied PNG, JPEG, WebP, or GIF image.",
                "headers": {
                    "X-Request-ID": {
                        "$ref": "#/components/headers/RequestId"
                    }
                },
                "content": {
                    "image/png": {
                        "schema": {
                            "type": "string",
                            "format": "binary"
                        }
                    },
                    "image/jpeg": {
                        "schema": {
                            "type": "string",
                            "format": "binary"
                        }
                    },
                    "image/webp": {
                        "schema": {
                            "type": "string",
                            "format": "binary"
                        }
                    },
                    "image/gif": {
                        "schema": {
                            "type": "string",
                            "format": "binary"
                        }
                    }
                }
            },
            "Campaign": {
                "description": "A deprecated campaign compatibility result.",
                "headers": {
                    "X-Request-ID": {
                        "$ref": "#/components/headers/RequestId"
                    }
                },
                "content": {
                    "application/json": {
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    }
                }
            },
            "CampaignList": {
                "description": "Deprecated campaign compatibility results.",
                "headers": {
                    "X-Request-ID": {
                        "$ref": "#/components/headers/RequestId"
                    }
                },
                "content": {
                    "application/json": {
                        "schema": {
                            "type": "object",
                            "required": ["runs"],
                            "properties": {
                                "runs": {
                                    "type": "array",
                                    "items": {
                                        "type": "object",
                                        "additionalProperties": true
                                    }
                                }
                            }
                        }
                    }
                }
            },
            "Canvas": {
                "description": "A complete canvas with its current revision.",
                "headers": {
                    "X-Request-ID": {
                        "$ref": "#/components/headers/RequestId"
                    }
                },
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/CanvasResponse"
                        }
                    }
                }
            },
            "CanvasList": {
                "description": "Accessible canvas summaries.",
                "headers": {
                    "X-Request-ID": {
                        "$ref": "#/components/headers/RequestId"
                    }
                },
                "content": {
                    "application/json": {
                        "schema": {
                            "type": "object",
                            "required": ["canvases", "page"],
                            "properties": {
                                "canvases": {
                                    "type": "array",
                                    "items": {
                                        "$ref": "#/components/schemas/CanvasSummary"
                                    }
                                },
                                "page": {
                                    "$ref": "#/components/schemas/CursorPage"
                                }
                            }
                        }
                    }
                }
            },
            "Error": {
                "description": "A stable machine-readable error. The response always includes X-Request-ID.",
                "headers": {
                    "X-Request-ID": {
                        "$ref": "#/components/headers/RequestId"
                    }
                },
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/ErrorResponse"
                        }
                    }
                }
            },
            "GenericObject": {
                "description": "A successful JSON response.",
                "headers": {
                    "X-Request-ID": {
                        "$ref": "#/components/headers/RequestId"
                    }
                },
                "content": {
                    "application/json": {
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    }
                }
            },
            "ImageImport": {
                "description": "A durable canvas image import result.",
                "headers": {
                    "X-Request-ID": {
                        "$ref": "#/components/headers/RequestId"
                    }
                },
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/ImageImportResponse"
                        }
                    }
                }
            },
            "Job": {
                "description": "An image, Action, or video job state or finalized result. Image and Action results follow the documented Run retention policy. Video records are retained for 30 days and expose a protected download URL after completion.",
                "headers": {
                    "X-Request-ID": {
                        "$ref": "#/components/headers/RequestId"
                    }
                },
                "content": {
                    "application/json": {
                        "schema": {
                            "oneOf": [
                                {
                                    "$ref": "#/components/schemas/ImageJob"
                                },
                                {
                                    "$ref": "#/components/schemas/VideoJob"
                                }
                            ]
                        }
                    }
                }
            },
            "Model": {
                "description": "One runnable image or video model with its connection-specific schema.",
                "headers": {
                    "X-Request-ID": {
                        "$ref": "#/components/headers/RequestId"
                    }
                },
                "content": {
                    "application/json": {
                        "schema": {
                            "type": "object",
                            "required": ["model"],
                            "properties": {
                                "model": {
                                    "$ref": "#/components/schemas/ImageModel"
                                }
                            },
                            "additionalProperties": false
                        }
                    }
                }
            },
            "ModelList": {
                "description": "Runnable image and video models with typed schemas and pagination.",
                "headers": {
                    "X-Request-ID": {
                        "$ref": "#/components/headers/RequestId"
                    }
                },
                "content": {
                    "application/json": {
                        "schema": {
                            "type": "object",
                            "required": ["models", "page"],
                            "properties": {
                                "models": {
                                    "type": "array",
                                    "items": {
                                        "$ref": "#/components/schemas/ImageModel"
                                    }
                                },
                                "page": {
                                    "$ref": "#/components/schemas/CursorPage"
                                }
                            },
                            "additionalProperties": false
                        }
                    }
                }
            },
            "Mutation": {
                "description": "A revision-safe canvas mutation result.",
                "headers": {
                    "X-Request-ID": {
                        "$ref": "#/components/headers/RequestId"
                    }
                },
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/MutationResponse"
                        }
                    }
                }
            },
            "CanvasOperationsResult": {
                "description": "A canonical read-only validation result when validateOnly is true, otherwise a revision-safe mutation result.",
                "headers": {
                    "X-Request-ID": {
                        "$ref": "#/components/headers/RequestId"
                    }
                },
                "content": {
                    "application/json": {
                        "schema": {
                            "anyOf": [
                                {
                                    "$ref": "#/components/schemas/CanvasValidationResponse"
                                },
                                {
                                    "$ref": "#/components/schemas/MutationResponse"
                                }
                            ]
                        }
                    }
                }
            },
            "WorkflowMutation": {
                "description": "A private reusable workflow creation or idempotent replay result.",
                "headers": {
                    "X-Request-ID": {
                        "$ref": "#/components/headers/RequestId"
                    }
                },
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/CanvasWorkflowMutationResponse"
                        }
                    }
                }
            },
            "ProviderList": {
                "description": "Saved image-provider connections with masked credentials.",
                "headers": {
                    "X-Request-ID": {
                        "$ref": "#/components/headers/RequestId"
                    }
                },
                "content": {
                    "application/json": {
                        "schema": {
                            "type": "object",
                            "required": ["connections", "page"],
                            "properties": {
                                "connections": {
                                    "type": "array",
                                    "items": {
                                        "$ref": "#/components/schemas/ProviderConnection"
                                    }
                                },
                                "page": {
                                    "$ref": "#/components/schemas/CursorPage"
                                }
                            }
                        }
                    }
                }
            },
            "Recipe": {
                "description": "An approved Recipe Library workflow.",
                "headers": {
                    "X-Request-ID": {
                        "$ref": "#/components/headers/RequestId"
                    }
                },
                "content": {
                    "application/json": {
                        "schema": {
                            "type": "object",
                            "required": ["recipe"],
                            "properties": {
                                "recipe": {
                                    "$ref": "#/components/schemas/Recipe"
                                }
                            }
                        }
                    }
                }
            },
            "RecipeList": {
                "description": "Approved Recipe Library search results.",
                "headers": {
                    "X-Request-ID": {
                        "$ref": "#/components/headers/RequestId"
                    }
                },
                "content": {
                    "application/json": {
                        "schema": {
                            "type": "object",
                            "required": ["recipes", "page"],
                            "properties": {
                                "recipes": {
                                    "type": "array",
                                    "items": {
                                        "$ref": "#/components/schemas/Recipe"
                                    }
                                },
                                "page": {
                                    "$ref": "#/components/schemas/CursorPage"
                                }
                            }
                        }
                    }
                }
            },
            "RecipeRun": {
                "description": "A durable Recipe Run with typed input bindings and declared output state.",
                "headers": {
                    "X-Request-ID": {
                        "$ref": "#/components/headers/RequestId"
                    }
                },
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/RecipeRun"
                        }
                    }
                }
            },
            "Run": {
                "description": "A shared Recipe, image, or Action Run.",
                "headers": {
                    "X-Request-ID": {
                        "$ref": "#/components/headers/RequestId"
                    }
                },
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/Run"
                        }
                    }
                }
            },
            "Svg": {
                "description": "An SVG rendering of the canvas.",
                "headers": {
                    "X-Request-ID": {
                        "$ref": "#/components/headers/RequestId"
                    }
                },
                "content": {
                    "image/svg+xml": {
                        "schema": {
                            "type": "string"
                        }
                    }
                }
            },
            "VideoOutput": {
                "description": "The generated video stream. The concrete Content-Type is the provider result, such as video/mp4 or video/webm.",
                "headers": {
                    "X-Request-ID": {
                        "$ref": "#/components/headers/RequestId"
                    }
                },
                "content": {
                    "video/mp4": {
                        "schema": {
                            "type": "string",
                            "format": "binary"
                        }
                    }
                }
            }
        },
        "schemas": {
            "AuthStatus": {
                "type": "object",
                "required": ["authenticated", "authType", "email", "scopes"],
                "properties": {
                    "authenticated": {
                        "const": true
                    },
                    "authType": {
                        "type": "string",
                        "enum": ["agent", "firebase"]
                    },
                    "email": {
                        "type": "string",
                        "format": "email"
                    },
                    "scopes": {
                        "anyOf": [
                            {
                                "type": "array",
                                "uniqueItems": true,
                                "items": {
                                    "type": "string",
                                    "enum": ["canvas:read", "canvas:write", "asset:read", "image:generate", "video:generate", "job:manage"]
                                }
                            },
                            {
                                "type": "null"
                            }
                        ]
                    },
                    "agentTokenId": {
                        "type": "string",
                        "format": "uuid"
                    },
                    "agentLabel": {
                        "type": "string",
                        "maxLength": 80
                    }
                },
                "additionalProperties": false
            },
            "CursorPage": {
                "type": "object",
                "required": ["limit", "hasMore", "nextCursor"],
                "properties": {
                    "limit": {
                        "type": "integer",
                        "minimum": 1,
                        "maximum": 200
                    },
                    "hasMore": {
                        "type": "boolean"
                    },
                    "nextCursor": {
                        "type": ["string", "null"],
                        "maxLength": 8192
                    }
                },
                "additionalProperties": false
            },
            "Asset": {
                "type": "object",
                "required": ["id", "handle", "name"],
                "properties": {
                    "id": {
                        "$ref": "#/components/schemas/StableId"
                    },
                    "handle": {
                        "type": "string",
                        "description": "Shared assets include their owner: asset:<ownerUid>:<id>.",
                        "pattern": "^asset:(?:[A-Za-z0-9_-]{1,180}:)?[A-Za-z0-9_-]{1,180}$"
                    },
                    "ownerUid": {
                        "$ref": "#/components/schemas/StableId"
                    },
                    "kind": {
                        "type": "string",
                        "enum": ["image", "prompt"]
                    },
                    "name": {
                        "type": "string"
                    },
                    "mimeType": {
                        "type": "string"
                    },
                    "width": {
                        "type": "integer",
                        "minimum": 0
                    },
                    "height": {
                        "type": "integer",
                        "minimum": 0
                    },
                    "bytes": {
                        "type": "integer",
                        "minimum": 0
                    },
                    "previewUrl": {
                        "type": "string",
                        "format": "uri"
                    },
                    "previewExpiresInSeconds": {
                        "type": "integer",
                        "minimum": 1
                    },
                    "node": {
                        "type": "string",
                        "pattern": "^node:"
                    }
                },
                "additionalProperties": true
            },
            "Canvas": {
                "type": "object",
                "required": ["id", "handle", "ownerUid", "title", "createdAt", "updatedAt", "revision", "nodes", "connections"],
                "properties": {
                    "id": {
                        "$ref": "#/components/schemas/StableId"
                    },
                    "canvasType": {
                        "type": "string",
                        "enum": ["agent"]
                    },
                    "handle": {
                        "type": "string",
                        "pattern": "^canvas:[A-Za-z0-9_-]+:[A-Za-z0-9_-]+$"
                    },
                    "ownerUid": {
                        "$ref": "#/components/schemas/StableId"
                    },
                    "title": {
                        "type": "string",
                        "maxLength": 160
                    },
                    "createdAt": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "updatedAt": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "revision": {
                        "type": "string",
                        "minLength": 1
                    },
                    "nodes": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/CanvasNode"
                        }
                    },
                    "connections": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/CanvasConnection"
                        }
                    }
                },
                "additionalProperties": true
            },
            "CanvasConnection": {
                "type": "object",
                "required": ["id", "handle", "fromNodeId", "toNodeId", "from", "to"],
                "properties": {
                    "id": {
                        "$ref": "#/components/schemas/StableId"
                    },
                    "handle": {
                        "type": "string",
                        "pattern": "^connection:"
                    },
                    "fromNodeId": {
                        "$ref": "#/components/schemas/StableId"
                    },
                    "toNodeId": {
                        "$ref": "#/components/schemas/StableId"
                    },
                    "from": {
                        "type": "string",
                        "pattern": "^node:"
                    },
                    "to": {
                        "type": "string",
                        "pattern": "^node:"
                    }
                },
                "additionalProperties": true
            },
            "CanvasCreateInput": {
                "type": "object",
                "properties": {
                    "id": {
                        "$ref": "#/components/schemas/StableId"
                    },
                    "title": {
                        "type": "string",
                        "maxLength": 160
                    },
                    "canvasType": {
                        "type": "string",
                        "enum": ["agent"]
                    },
                    "destination": {
                        "type": "string",
                        "enum": ["agent-canvas"]
                    }
                },
                "additionalProperties": false
            },
            "CanvasNode": {
                "type": "object",
                "required": ["id", "handle", "type", "title", "position", "width", "height"],
                "properties": {
                    "id": {
                        "$ref": "#/components/schemas/StableId"
                    },
                    "handle": {
                        "type": "string",
                        "pattern": "^node:"
                    },
                    "type": {
                        "type": "string",
                        "enum": ["image", "video", "text", "sticky"]
                    },
                    "title": {
                        "type": "string"
                    },
                    "position": {
                        "$ref": "#/components/schemas/Position"
                    },
                    "width": {
                        "type": "number",
                        "exclusiveMinimum": 0
                    },
                    "height": {
                        "type": "number",
                        "exclusiveMinimum": 0
                    },
                    "metadata": {
                        "type": "object",
                        "additionalProperties": true
                    },
                    "asset": {
                        "type": "string",
                        "pattern": "^asset:"
                    }
                },
                "additionalProperties": true
            },
            "BatchNodeReference": {
                "type": "string",
                "pattern": "^(?:(?:node|client):)?[A-Za-z0-9_-]{1,180}$"
            },
            "CanvasConnectionInput": {
                "type": "object",
                "required": ["fromNodeId", "toNodeId"],
                "properties": {
                    "id": {
                        "$ref": "#/components/schemas/StableId"
                    },
                    "fromNodeId": {
                        "$ref": "#/components/schemas/BatchNodeReference"
                    },
                    "toNodeId": {
                        "$ref": "#/components/schemas/BatchNodeReference"
                    },
                    "mode": {
                        "type": "string",
                        "enum": ["list", "reference", "first-frame", "last-frame"]
                    }
                },
                "additionalProperties": false
            },
            "PublicNodeMetadata": {
                "type": "object",
                "description": "Publicly writable node metadata. Null removes a field during update. The serialized metadata object must be no larger than 64 KiB. Server-owned provenance, upload, storage, and generation-job fields are intentionally excluded.",
                "properties": {
                    "content": {
                        "type": ["string", "null"],
                        "description": "Text and sticky nodes only. A non-empty value is rejected when the target node is an image or video; use a generation or asset operation instead.",
                        "maxLength": 8000
                    },
                    "composerContent": {
                        "type": ["string", "null"],
                        "maxLength": 8000
                    },
                    "assetName": {
                        "type": ["string", "null"],
                        "maxLength": 600
                    },
                    "prompt": {
                        "type": ["string", "null"],
                        "maxLength": 8000
                    },
                    "errorDetails": {
                        "type": ["string", "null"],
                        "maxLength": 600
                    },
                    "model": {
                        "type": ["string", "null"],
                        "maxLength": 600
                    },
                    "size": {
                        "type": ["string", "null"],
                        "maxLength": 600
                    },
                    "quality": {
                        "type": ["string", "null"],
                        "maxLength": 600
                    },
                    "aspectRatio": {
                        "type": ["string", "null"],
                        "maxLength": 600
                    },
                    "resolution": {
                        "type": ["string", "null"],
                        "maxLength": 600
                    },
                    "posterUrl": {
                        "type": ["string", "null"],
                        "maxLength": 8000
                    },
                    "variationSourceId": {
                        "type": ["string", "null"],
                        "maxLength": 600
                    },
                    "primaryImageId": {
                        "type": ["string", "null"],
                        "maxLength": 600
                    },
                    "stickyColor": {
                        "type": ["string", "null"],
                        "maxLength": 600
                    },
                    "sceneRole": {
                        "type": ["string", "null"],
                        "maxLength": 600
                    },
                    "videoPrompt": {
                        "type": ["string", "null"],
                        "maxLength": 600
                    },
                    "fontSize": {
                        "type": ["number", "null"]
                    },
                    "count": {
                        "type": ["number", "null"]
                    },
                    "variationIndex": {
                        "type": ["number", "null"]
                    },
                    "generationBatchIndex": {
                        "type": ["number", "null"]
                    },
                    "sceneIndex": {
                        "type": ["number", "null"]
                    },
                    "durationSeconds": {
                        "type": ["number", "null"]
                    },
                    "freeResize": {
                        "type": ["boolean", "null"]
                    },
                    "isList": {
                        "type": ["boolean", "null"]
                    },
                    "isGeneratedOutputList": {
                        "type": ["boolean", "null"]
                    },
                    "isBatchRoot": {
                        "type": ["boolean", "null"]
                    },
                    "batchUsesReferenceImages": {
                        "type": ["boolean", "null"]
                    },
                    "imageBatchExpanded": {
                        "type": ["boolean", "null"]
                    },
                    "isSection": {
                        "type": ["boolean", "null"]
                    },
                    "generateAudio": {
                        "type": ["boolean", "null"]
                    },
                    "status": {
                        "type": ["string", "null"],
                        "enum": ["idle", "success", "loading", "error", null]
                    },
                    "generationMode": {
                        "type": ["string", "null"],
                        "enum": ["text", "image", "video", null]
                    },
                    "generationType": {
                        "type": ["string", "null"],
                        "enum": ["generation", "edit", null]
                    },
                    "videoGenerationType": {
                        "type": ["string", "null"],
                        "enum": ["text-to-video", "image-to-video", "frames-to-video", null]
                    },
                    "listType": {
                        "type": ["string", "null"],
                        "enum": ["prompt", "image", null]
                    },
                    "listViewMode": {
                        "type": ["string", "null"],
                        "enum": ["grid", "list", null]
                    },
                    "listExecutionMode": {
                        "type": ["string", "null"],
                        "enum": ["batch", "reference-set", null]
                    },
                    "listRunStatus": {
                        "type": ["string", "null"],
                        "enum": ["idle", "running", "complete", null]
                    },
                    "generatedOutputSourceListType": {
                        "type": ["string", "null"],
                        "enum": ["prompt", "image", null]
                    },
                    "listSourceId": {
                        "type": ["string", "null"],
                        "pattern": "^(?:node:)?[A-Za-z0-9_-]{1,180}$"
                    },
                    "listGeneratorId": {
                        "type": ["string", "null"],
                        "pattern": "^(?:node:)?[A-Za-z0-9_-]{1,180}$"
                    },
                    "listRunId": {
                        "type": ["string", "null"],
                        "pattern": "^(?:node:)?[A-Za-z0-9_-]{1,180}$"
                    },
                    "listItemId": {
                        "type": ["string", "null"],
                        "pattern": "^(?:node:)?[A-Za-z0-9_-]{1,180}$"
                    },
                    "listOutputId": {
                        "type": ["string", "null"],
                        "pattern": "^(?:node:)?[A-Za-z0-9_-]{1,180}$"
                    },
                    "batchRootId": {
                        "type": ["string", "null"],
                        "pattern": "^(?:node:)?[A-Za-z0-9_-]{1,180}$"
                    },
                    "firstFrameNodeId": {
                        "type": ["string", "null"],
                        "pattern": "^(?:node:)?[A-Za-z0-9_-]{1,180}$"
                    },
                    "lastFrameNodeId": {
                        "type": ["string", "null"],
                        "pattern": "^(?:node:)?[A-Za-z0-9_-]{1,180}$"
                    },
                    "listRunTargetIds": {
                        "anyOf": [
                            {
                                "type": "array",
                                "maxItems": 200,
                                "items": {
                                    "type": "string",
                                    "pattern": "^(?:node:)?[A-Za-z0-9_-]{1,180}$"
                                }
                            },
                            {
                                "type": "null"
                            }
                        ]
                    },
                    "generatedOutputChildIds": {
                        "anyOf": [
                            {
                                "type": "array",
                                "maxItems": 200,
                                "items": {
                                    "type": "string",
                                    "pattern": "^(?:node:)?[A-Za-z0-9_-]{1,180}$"
                                }
                            },
                            {
                                "type": "null"
                            }
                        ]
                    },
                    "batchChildIds": {
                        "anyOf": [
                            {
                                "type": "array",
                                "maxItems": 200,
                                "items": {
                                    "type": "string",
                                    "pattern": "^(?:node:)?[A-Za-z0-9_-]{1,180}$"
                                }
                            },
                            {
                                "type": "null"
                            }
                        ]
                    },
                    "references": {
                        "anyOf": [
                            {
                                "type": "array",
                                "maxItems": 32,
                                "items": {
                                    "type": "string",
                                    "pattern": "^(?:node|asset):[A-Za-z0-9_-]{1,180}$"
                                }
                            },
                            {
                                "type": "null"
                            }
                        ]
                    },
                    "crop": {
                        "anyOf": [
                            {
                                "type": "object",
                                "required": ["offsetX", "offsetY", "scale"],
                                "properties": {
                                    "offsetX": {
                                        "type": "number"
                                    },
                                    "offsetY": {
                                        "type": "number"
                                    },
                                    "scale": {
                                        "type": "number"
                                    }
                                },
                                "additionalProperties": false
                            },
                            {
                                "type": "null"
                            }
                        ]
                    },
                    "promptHistory": {
                        "anyOf": [
                            {
                                "type": "array",
                                "maxItems": 20,
                                "items": {
                                    "type": "object",
                                    "required": ["prompt"],
                                    "properties": {
                                        "id": {
                                            "type": "string",
                                            "maxLength": 180
                                        },
                                        "prompt": {
                                            "type": "string",
                                            "maxLength": 8000
                                        },
                                        "createdAt": {
                                            "type": "string",
                                            "maxLength": 80
                                        },
                                        "source": {
                                            "type": "string",
                                            "enum": ["agent", "manual"]
                                        },
                                        "instruction": {
                                            "type": "string",
                                            "maxLength": 1200
                                        }
                                    },
                                    "additionalProperties": false
                                }
                            },
                            {
                                "type": "null"
                            }
                        ]
                    },
                    "listItems": {
                        "anyOf": [
                            {
                                "type": "array",
                                "maxItems": 200,
                                "items": {
                                    "type": "object",
                                    "required": ["value"],
                                    "properties": {
                                        "id": {
                                            "type": "string",
                                            "maxLength": 180
                                        },
                                        "value": {
                                            "type": "string",
                                            "maxLength": 8000
                                        },
                                        "checked": {
                                            "type": "boolean"
                                        },
                                        "sourceNodeId": {
                                            "type": "string",
                                            "pattern": "^[A-Za-z0-9_-]{1,180}$"
                                        },
                                        "referenceBindings": {
                                            "type": "array",
                                            "maxItems": 16,
                                            "items": {
                                                "type": "object",
                                                "required": ["nodeId", "role"],
                                                "properties": {
                                                    "nodeId": {
                                                        "type": "string",
                                                        "pattern": "^(?:node:)?[A-Za-z0-9_-]{1,180}$"
                                                    },
                                                    "role": {
                                                        "type": "string",
                                                        "enum": ["product", "style"]
                                                    }
                                                },
                                                "additionalProperties": false
                                            }
                                        }
                                    },
                                    "additionalProperties": false
                                }
                            },
                            {
                                "type": "null"
                            }
                        ]
                    }
                },
                "x-craftboard-node-type-rules": {
                    "content": "Non-empty content is writable only on text and sticky nodes."
                },
                "additionalProperties": false
            },
            "CanvasNodeInput": {
                "type": "object",
                "properties": {
                    "id": {
                        "$ref": "#/components/schemas/StableId"
                    },
                    "type": {
                        "type": "string",
                        "enum": ["image", "video", "text", "sticky"]
                    },
                    "title": {
                        "type": "string",
                        "maxLength": 160
                    },
                    "position": {
                        "$ref": "#/components/schemas/Position"
                    },
                    "width": {
                        "type": "number",
                        "minimum": 40,
                        "maximum": 10000
                    },
                    "height": {
                        "type": "number",
                        "minimum": 40,
                        "maximum": 10000
                    },
                    "metadata": {
                        "$ref": "#/components/schemas/PublicNodeMetadata"
                    }
                },
                "allOf": [
                    {
                        "if": {
                            "required": ["type"],
                            "properties": {
                                "type": {
                                    "const": "image"
                                }
                            }
                        },
                        "then": {
                            "properties": {
                                "metadata": {
                                    "properties": {
                                        "content": {
                                            "anyOf": [
                                                {
                                                    "type": "string",
                                                    "maxLength": 0
                                                },
                                                {
                                                    "type": "null"
                                                }
                                            ]
                                        }
                                    }
                                }
                            }
                        }
                    }
                ],
                "additionalProperties": false
            },
            "CanvasNodePatch": {
                "type": "object",
                "description": "Patch for an existing node. A non-empty metadata.content value is rejected when the existing node is an image or video, even when type is omitted.",
                "properties": {
                    "type": {
                        "type": "string",
                        "enum": ["image", "video", "text", "sticky"]
                    },
                    "title": {
                        "type": "string",
                        "maxLength": 160
                    },
                    "position": {
                        "$ref": "#/components/schemas/Position"
                    },
                    "width": {
                        "type": "number",
                        "minimum": 40,
                        "maximum": 10000
                    },
                    "height": {
                        "type": "number",
                        "minimum": 40,
                        "maximum": 10000
                    },
                    "metadata": {
                        "$ref": "#/components/schemas/PublicNodeMetadata"
                    }
                },
                "allOf": [
                    {
                        "if": {
                            "required": ["type"],
                            "properties": {
                                "type": {
                                    "const": "image"
                                }
                            }
                        },
                        "then": {
                            "properties": {
                                "metadata": {
                                    "properties": {
                                        "content": {
                                            "anyOf": [
                                                {
                                                    "type": "string",
                                                    "maxLength": 0
                                                },
                                                {
                                                    "type": "null"
                                                }
                                            ]
                                        }
                                    }
                                }
                            }
                        }
                    }
                ],
                "additionalProperties": false
            },
            "CanvasUpdateOperation": {
                "type": "object",
                "required": ["type"],
                "properties": {
                    "type": {
                        "const": "canvas.update"
                    },
                    "title": {
                        "type": "string",
                        "maxLength": 160
                    },
                    "backgroundMode": {
                        "type": "string",
                        "enum": ["dots", "lines", "blank"]
                    },
                    "showImageInfo": {
                        "type": "boolean"
                    },
                    "viewport": {
                        "$ref": "#/components/schemas/Viewport"
                    }
                },
                "additionalProperties": false
            },
            "NodeCreateOperation": {
                "type": "object",
                "required": ["type", "node"],
                "properties": {
                    "type": {
                        "const": "node.create"
                    },
                    "clientId": {
                        "type": "string",
                        "pattern": "^(?:client:)?[A-Za-z0-9_-]{1,100}$"
                    },
                    "node": {
                        "$ref": "#/components/schemas/CanvasNodeInput"
                    }
                },
                "additionalProperties": false
            },
            "NodeUpdateOperation": {
                "type": "object",
                "required": ["type", "nodeId", "patch"],
                "properties": {
                    "type": {
                        "const": "node.update"
                    },
                    "nodeId": {
                        "$ref": "#/components/schemas/BatchNodeReference"
                    },
                    "patch": {
                        "$ref": "#/components/schemas/CanvasNodePatch"
                    }
                },
                "additionalProperties": false
            },
            "NodeMoveOperation": {
                "type": "object",
                "required": ["type", "nodeId", "position"],
                "properties": {
                    "type": {
                        "const": "node.move"
                    },
                    "nodeId": {
                        "$ref": "#/components/schemas/BatchNodeReference"
                    },
                    "position": {
                        "$ref": "#/components/schemas/Position"
                    }
                },
                "additionalProperties": false
            },
            "NodeResizeOperation": {
                "type": "object",
                "required": ["type", "nodeId", "width", "height"],
                "properties": {
                    "type": {
                        "const": "node.resize"
                    },
                    "nodeId": {
                        "$ref": "#/components/schemas/BatchNodeReference"
                    },
                    "width": {
                        "type": "number",
                        "minimum": 40,
                        "maximum": 10000
                    },
                    "height": {
                        "type": "number",
                        "minimum": 40,
                        "maximum": 10000
                    }
                },
                "additionalProperties": false
            },
            "NodeDeleteOperation": {
                "type": "object",
                "required": ["type", "nodeId"],
                "properties": {
                    "type": {
                        "const": "node.delete"
                    },
                    "nodeId": {
                        "$ref": "#/components/schemas/BatchNodeReference"
                    }
                },
                "additionalProperties": false
            },
            "ConnectionCreateOperation": {
                "type": "object",
                "required": ["type"],
                "properties": {
                    "type": {
                        "const": "connection.create"
                    },
                    "clientId": {
                        "type": "string",
                        "pattern": "^(?:client:)?[A-Za-z0-9_-]{1,100}$"
                    },
                    "connection": {
                        "$ref": "#/components/schemas/CanvasConnectionInput"
                    },
                    "from": {
                        "$ref": "#/components/schemas/BatchNodeReference"
                    },
                    "to": {
                        "$ref": "#/components/schemas/BatchNodeReference"
                    },
                    "mode": {
                        "type": "string",
                        "enum": ["list", "reference", "first-frame", "last-frame"]
                    }
                },
                "anyOf": [
                    {
                        "required": ["connection"]
                    },
                    {
                        "required": ["from", "to"]
                    }
                ],
                "additionalProperties": false
            },
            "ConnectionDeleteOperation": {
                "type": "object",
                "required": ["type", "connectionId"],
                "properties": {
                    "type": {
                        "const": "connection.delete"
                    },
                    "connectionId": {
                        "type": "string",
                        "pattern": "^(?:connection:)?[A-Za-z0-9_-]{1,180}$"
                    }
                },
                "additionalProperties": false
            },
            "CanvasOperation": {
                "oneOf": [
                    {
                        "$ref": "#/components/schemas/CanvasUpdateOperation"
                    },
                    {
                        "$ref": "#/components/schemas/NodeCreateOperation"
                    },
                    {
                        "$ref": "#/components/schemas/NodeUpdateOperation"
                    },
                    {
                        "$ref": "#/components/schemas/NodeMoveOperation"
                    },
                    {
                        "$ref": "#/components/schemas/NodeResizeOperation"
                    },
                    {
                        "$ref": "#/components/schemas/NodeDeleteOperation"
                    },
                    {
                        "$ref": "#/components/schemas/ConnectionCreateOperation"
                    },
                    {
                        "$ref": "#/components/schemas/ConnectionDeleteOperation"
                    }
                ],
                "discriminator": {
                    "propertyName": "type",
                    "mapping": {
                        "canvas.update": "#/components/schemas/CanvasUpdateOperation",
                        "node.create": "#/components/schemas/NodeCreateOperation",
                        "node.update": "#/components/schemas/NodeUpdateOperation",
                        "node.move": "#/components/schemas/NodeMoveOperation",
                        "node.resize": "#/components/schemas/NodeResizeOperation",
                        "node.delete": "#/components/schemas/NodeDeleteOperation",
                        "connection.create": "#/components/schemas/ConnectionCreateOperation",
                        "connection.delete": "#/components/schemas/ConnectionDeleteOperation"
                    }
                }
            },
            "CanvasOperationsInput": {
                "type": "object",
                "required": ["operations"],
                "properties": {
                    "baseRevision": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 200
                    },
                    "idempotencyKey": {
                        "type": "string",
                        "minLength": 8,
                        "maxLength": 200,
                        "description": "Required for mutation. Ignored and not consumed when validateOnly is true."
                    },
                    "validateOnly": {
                        "type": "boolean",
                        "default": false,
                        "description": "Run the canonical operation engine and graph validator without persisting any change."
                    },
                    "operations": {
                        "type": "array",
                        "minItems": 1,
                        "maxItems": 200,
                        "items": {
                            "$ref": "#/components/schemas/CanvasOperation"
                        }
                    }
                },
                "allOf": [
                    {
                        "if": {
                            "properties": {
                                "validateOnly": {
                                    "const": true
                                }
                            },
                            "required": ["validateOnly"]
                        },
                        "else": {
                            "required": ["baseRevision", "idempotencyKey"]
                        }
                    }
                ],
                "additionalProperties": false
            },
            "CanvasValidationResponse": {
                "type": "object",
                "required": ["canvas", "proposal", "destructiveImpact", "validation"],
                "properties": {
                    "canvas": {
                        "$ref": "#/components/schemas/CanvasSummary"
                    },
                    "proposal": {
                        "type": "object",
                        "required": ["clientReferences", "changedNodeReferences", "deletedNodeReferences", "changedConnectionReferences", "deletedConnectionReferences"],
                        "additionalProperties": true
                    },
                    "destructiveImpact": {
                        "type": "object",
                        "required": ["deletedNodeHandles", "deletedConnectionHandles", "mediaNodeHandles", "generatedNodeHandles"],
                        "additionalProperties": true
                    },
                    "validation": {
                        "type": "object",
                        "required": ["guideVersion", "scope", "canvas", "summary", "findings"],
                        "additionalProperties": true
                    }
                },
                "additionalProperties": false
            },
            "CanvasWorkflowInput": {
                "type": "object",
                "required": ["key", "label", "type", "useAsDefault"],
                "properties": {
                    "key": {
                        "type": "string",
                        "pattern": "^[A-Za-z0-9_-]{1,80}$"
                    },
                    "label": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 80
                    },
                    "description": {
                        "type": "string",
                        "maxLength": 200
                    },
                    "type": {
                        "type": "string",
                        "enum": ["image", "text", "sticky"]
                    },
                    "sourceNodeId": {
                        "type": "string",
                        "pattern": "^(?:node:)?[A-Za-z0-9_-]{1,180}$"
                    },
                    "value": {
                        "type": "string",
                        "maxLength": 8000
                    },
                    "useAsDefault": {
                        "type": "boolean",
                        "description": "When true, preserve this durable source or text value as the input used when a later run omits the port."
                    }
                },
                "additionalProperties": false
            },
            "CanvasWorkflowOutput": {
                "type": "object",
                "required": ["key", "label", "type", "prompt", "inputKeys"],
                "properties": {
                    "key": {
                        "type": "string",
                        "pattern": "^[A-Za-z0-9_-]{1,80}$"
                    },
                    "label": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 80
                    },
                    "description": {
                        "type": "string",
                        "maxLength": 200
                    },
                    "type": {
                        "type": "string",
                        "enum": ["image", "text"]
                    },
                    "prompt": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 8000
                    },
                    "inputKeys": {
                        "type": "array",
                        "minItems": 1,
                        "maxItems": 16,
                        "items": {
                            "type": "string",
                            "pattern": "^[A-Za-z0-9_-]{1,80}$"
                        }
                    },
                    "model": {
                        "type": "string",
                        "maxLength": 650
                    },
                    "size": {
                        "type": "string",
                        "maxLength": 80
                    },
                    "quality": {
                        "type": "string",
                        "maxLength": 80
                    }
                },
                "additionalProperties": false
            },
            "CanvasWorkflowCreateInput": {
                "type": "object",
                "required": ["name", "idempotencyKey", "inputs", "outputs"],
                "properties": {
                    "name": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 160
                    },
                    "description": {
                        "type": "string",
                        "maxLength": 1200
                    },
                    "category": {
                        "type": "string",
                        "enum": ["Brand & Visual Design", "Product Visualization", "Marketing & Ads", "Content Package"],
                        "default": "Product Visualization"
                    },
                    "tags": {
                        "type": "array",
                        "maxItems": 12,
                        "items": {
                            "type": "string",
                            "minLength": 1,
                            "maxLength": 80
                        }
                    },
                    "inputs": {
                        "type": "array",
                        "minItems": 1,
                        "maxItems": 16,
                        "items": {
                            "$ref": "#/components/schemas/CanvasWorkflowInput"
                        }
                    },
                    "outputs": {
                        "type": "array",
                        "minItems": 1,
                        "maxItems": 8,
                        "items": {
                            "$ref": "#/components/schemas/CanvasWorkflowOutput"
                        }
                    },
                    "idempotencyKey": {
                        "type": "string",
                        "minLength": 8,
                        "maxLength": 200
                    },
                    "x": {
                        "type": "number",
                        "minimum": -100000,
                        "maximum": 100000
                    },
                    "y": {
                        "type": "number",
                        "minimum": -100000,
                        "maximum": 100000
                    }
                },
                "additionalProperties": false
            },
            "CanvasWorkflowInputResponse": {
                "type": "object",
                "required": ["key", "portNodeId", "nodeId", "label", "useAsDefault"],
                "properties": {
                    "key": {
                        "type": "string",
                        "pattern": "^[A-Za-z0-9_-]{1,80}$"
                    },
                    "portNodeId": {
                        "type": "string",
                        "pattern": "^node:"
                    },
                    "nodeId": {
                        "type": "string",
                        "pattern": "^node:"
                    },
                    "label": {
                        "type": "string"
                    },
                    "useAsDefault": {
                        "type": "boolean"
                    }
                },
                "additionalProperties": false
            },
            "CanvasWorkflowOutputResponse": {
                "type": "object",
                "required": ["key", "portNodeId", "templateNodeId", "label"],
                "properties": {
                    "key": {
                        "type": "string",
                        "pattern": "^[A-Za-z0-9_-]{1,80}$"
                    },
                    "portNodeId": {
                        "type": "string",
                        "pattern": "^node:"
                    },
                    "templateNodeId": {
                        "type": "string",
                        "pattern": "^node:"
                    },
                    "label": {
                        "type": "string"
                    }
                },
                "additionalProperties": false
            },
            "CanvasWorkflowResponse": {
                "type": "object",
                "required": ["id", "handle", "version", "name", "visibility", "recipeNodeId", "workflowNodeId", "inputs", "outputs", "createdWithoutRunning"],
                "properties": {
                    "id": {
                        "$ref": "#/components/schemas/StableId"
                    },
                    "handle": {
                        "type": "string",
                        "pattern": "^recipe:"
                    },
                    "version": {
                        "type": "string"
                    },
                    "name": {
                        "type": "string"
                    },
                    "visibility": {
                        "const": "private"
                    },
                    "recipeNodeId": {
                        "type": "string",
                        "pattern": "^node:"
                    },
                    "workflowNodeId": {
                        "type": "string",
                        "pattern": "^node:"
                    },
                    "inputs": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/CanvasWorkflowInputResponse"
                        }
                    },
                    "outputs": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/CanvasWorkflowOutputResponse"
                        }
                    },
                    "createdWithoutRunning": {
                        "const": true
                    }
                },
                "additionalProperties": false
            },
            "CanvasWorkflowMutationResponse": {
                "allOf": [
                    {
                        "$ref": "#/components/schemas/MutationResponse"
                    },
                    {
                        "type": "object",
                        "required": ["workflow"],
                        "properties": {
                            "workflow": {
                                "$ref": "#/components/schemas/CanvasWorkflowResponse"
                            }
                        }
                    }
                ]
            },
            "CanvasResponse": {
                "type": "object",
                "required": ["canvas", "activity"],
                "properties": {
                    "canvas": {
                        "$ref": "#/components/schemas/Canvas"
                    },
                    "activity": {
                        "type": "array",
                        "items": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    }
                },
                "additionalProperties": true
            },
            "CanvasSummary": {
                "type": "object",
                "required": ["id", "handle", "ownerUid", "title", "createdAt", "updatedAt", "revision", "nodeCount", "connectionCount"],
                "properties": {
                    "id": {
                        "$ref": "#/components/schemas/StableId"
                    },
                    "canvasType": {
                        "type": "string",
                        "enum": ["agent"]
                    },
                    "handle": {
                        "type": "string",
                        "pattern": "^canvas:"
                    },
                    "ownerUid": {
                        "$ref": "#/components/schemas/StableId"
                    },
                    "title": {
                        "type": "string"
                    },
                    "createdAt": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "updatedAt": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "revision": {
                        "type": "string"
                    },
                    "accessRole": {
                        "type": "string",
                        "enum": ["owner", "editor", "viewer"]
                    },
                    "nodeCount": {
                        "type": "integer",
                        "minimum": 0
                    },
                    "connectionCount": {
                        "type": "integer",
                        "minimum": 0
                    }
                },
                "additionalProperties": false
            },
            "Error": {
                "type": "object",
                "required": ["code", "message"],
                "properties": {
                    "code": {
                        "type": "string",
                        "enum": [
                            "input_validation_error",
                            "invalid_json",
                            "unauthorized",
                            "payment_required",
                            "forbidden",
                            "not_found",
                            "conflict",
                            "gone",
                            "payload_too_large",
                            "unsupported_media_type",
                            "unprocessable_entity",
                            "rate_limited",
                            "internal_error",
                            "upstream_error",
                            "service_unavailable",
                            "upstream_timeout",
                            "request_failed"
                        ]
                    },
                    "message": {
                        "type": "string",
                        "minLength": 1
                    },
                    "fields": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/ErrorField"
                        }
                    },
                    "details": {
                        "type": "object",
                        "additionalProperties": true
                    }
                },
                "additionalProperties": false
            },
            "ErrorField": {
                "type": "object",
                "required": ["field", "message"],
                "properties": {
                    "field": {
                        "type": "string",
                        "minLength": 1
                    },
                    "message": {
                        "type": "string",
                        "minLength": 1
                    }
                },
                "additionalProperties": false
            },
            "ErrorResponse": {
                "type": "object",
                "required": ["error"],
                "properties": {
                    "error": {
                        "$ref": "#/components/schemas/Error"
                    }
                },
                "additionalProperties": false
            },
            "ImageAction": {
                "type": "object",
                "required": ["id", "slug", "version", "title", "summary", "deterministic", "chargedCost", "estimatedSeconds", "inputs", "output", "parameters"],
                "properties": {
                    "id": {
                        "type": "string",
                        "pattern": "^action:"
                    },
                    "slug": {
                        "type": "string",
                        "enum": ["resize", "crop", "change-aspect-ratio", "side-by-side-composite", "add-text-to-image", "overlay-image", "color-grade", "rotate"]
                    },
                    "version": {
                        "type": "string",
                        "const": "1.0.0"
                    },
                    "title": {
                        "type": "string",
                        "minLength": 1
                    },
                    "summary": {
                        "type": "string",
                        "minLength": 1
                    },
                    "deterministic": {
                        "const": true
                    },
                    "chargedCost": {
                        "const": 0,
                        "description": "These transformations do not spend AI-generation credits."
                    },
                    "estimatedSeconds": {
                        "type": "integer",
                        "minimum": 1
                    },
                    "inputs": {
                        "type": "array",
                        "minItems": 1,
                        "maxItems": 2,
                        "items": {
                            "$ref": "#/components/schemas/ImageActionInput"
                        }
                    },
                    "output": {
                        "$ref": "#/components/schemas/ImageActionOutput"
                    },
                    "parameters": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/ImageActionParameter"
                        }
                    }
                },
                "additionalProperties": false
            },
            "ImageActionInput": {
                "type": "object",
                "required": ["id", "title", "description", "type", "required"],
                "properties": {
                    "id": {
                        "type": "string",
                        "pattern": "^[A-Za-z][A-Za-z0-9_-]{0,79}$"
                    },
                    "title": {
                        "type": "string"
                    },
                    "description": {
                        "type": "string"
                    },
                    "type": {
                        "const": "image"
                    },
                    "required": {
                        "const": true
                    }
                },
                "additionalProperties": false
            },
            "ImageActionOutput": {
                "type": "object",
                "required": ["id", "title", "description", "type"],
                "properties": {
                    "id": {
                        "const": "image"
                    },
                    "title": {
                        "type": "string"
                    },
                    "description": {
                        "type": "string"
                    },
                    "type": {
                        "const": "image"
                    }
                },
                "additionalProperties": false
            },
            "ImageActionParameter": {
                "type": "object",
                "required": ["id", "title", "type", "required"],
                "properties": {
                    "id": {
                        "type": "string",
                        "pattern": "^[A-Za-z][A-Za-z0-9_-]{0,79}$"
                    },
                    "title": {
                        "type": "string"
                    },
                    "description": {
                        "type": "string"
                    },
                    "type": {
                        "type": "string",
                        "enum": ["number", "select", "text", "color"]
                    },
                    "required": {
                        "type": "boolean"
                    },
                    "default": {},
                    "integer": {
                        "type": "boolean"
                    },
                    "min": {
                        "type": "number"
                    },
                    "max": {
                        "type": "number"
                    },
                    "step": {
                        "type": "number",
                        "exclusiveMinimum": 0
                    },
                    "maxLength": {
                        "type": "integer",
                        "minimum": 1
                    },
                    "valueType": {
                        "const": "number"
                    },
                    "options": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/ImageActionParameterOption"
                        }
                    }
                },
                "additionalProperties": false
            },
            "ImageActionParameterOption": {
                "type": "object",
                "required": ["value", "label"],
                "properties": {
                    "value": {
                        "oneOf": [
                            {
                                "type": "string"
                            },
                            {
                                "type": "number"
                            }
                        ]
                    },
                    "label": {
                        "type": "string"
                    }
                },
                "additionalProperties": false
            },
            "ImageActionRunInput": {
                "type": "object",
                "required": ["canvasId", "baseRevision", "idempotencyKey", "targetNodeId", "inputs", "params"],
                "properties": {
                    "canvasId": {
                        "type": "string",
                        "description": "A plain id, canvas:<id>, or canvas:<ownerUid>:<id> handle."
                    },
                    "baseRevision": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 200
                    },
                    "idempotencyKey": {
                        "type": "string",
                        "minLength": 8,
                        "maxLength": 200
                    },
                    "targetNodeId": {
                        "type": "string",
                        "description": "A new, empty image node reserved for this Action result. It must not also appear in inputs, and it must have no content, asset binding, or active Run.",
                        "pattern": "^(?:node:)?[A-Za-z0-9_-]{1,180}$"
                    },
                    "inputs": {
                        "type": "array",
                        "description": "One or two durable images in the exact order declared by the selected Action.",
                        "minItems": 1,
                        "maxItems": 2,
                        "items": {
                            "type": "string",
                            "pattern": "^(?:node:[A-Za-z0-9_-]{1,180}|asset:(?:[A-Za-z0-9_-]{1,180}:)?[A-Za-z0-9_-]{1,180})$"
                        }
                    },
                    "params": {
                        "$ref": "#/components/schemas/ImageActionParameters"
                    },
                    "webhook": {
                        "$ref": "#/components/schemas/ImageJobWebhookInput"
                    }
                },
                "additionalProperties": false,
                "x-craftboard-cross-field-rules": ["targetNodeId must not identify any node supplied in inputs", "targetNodeId must identify an empty, unbound image node"]
            },
            "ImageActionParameters": {
                "description": "Use the parameter object declared by GET /actions/{actionKey}. Unknown fields are rejected.",
                "anyOf": [
                    {
                        "$ref": "#/components/schemas/ResizeActionParameters"
                    },
                    {
                        "$ref": "#/components/schemas/CropActionParameters"
                    },
                    {
                        "$ref": "#/components/schemas/ChangeAspectRatioActionParameters"
                    },
                    {
                        "$ref": "#/components/schemas/SideBySideActionParameters"
                    },
                    {
                        "$ref": "#/components/schemas/AddTextActionParameters"
                    },
                    {
                        "$ref": "#/components/schemas/OverlayImageActionParameters"
                    },
                    {
                        "$ref": "#/components/schemas/ColorGradeActionParameters"
                    },
                    {
                        "$ref": "#/components/schemas/RotateActionParameters"
                    }
                ]
            },
            "ResizeActionParameters": {
                "type": "object",
                "required": ["width", "height"],
                "properties": {
                    "width": {
                        "type": "integer",
                        "minimum": 1,
                        "maximum": 8192
                    },
                    "height": {
                        "type": "integer",
                        "minimum": 1,
                        "maximum": 8192
                    },
                    "fit": {
                        "type": "string",
                        "enum": ["cover", "contain", "fill", "inside", "outside"],
                        "default": "cover"
                    },
                    "background": {
                        "$ref": "#/components/schemas/ImageActionColor"
                    }
                },
                "additionalProperties": false
            },
            "CropActionParameters": {
                "type": "object",
                "required": ["width", "height"],
                "properties": {
                    "x": {
                        "type": "integer",
                        "minimum": 0,
                        "maximum": 8191,
                        "default": 0
                    },
                    "y": {
                        "type": "integer",
                        "minimum": 0,
                        "maximum": 8191,
                        "default": 0
                    },
                    "width": {
                        "type": "integer",
                        "minimum": 1,
                        "maximum": 8192
                    },
                    "height": {
                        "type": "integer",
                        "minimum": 1,
                        "maximum": 8192
                    }
                },
                "additionalProperties": false
            },
            "ChangeAspectRatioActionParameters": {
                "type": "object",
                "properties": {
                    "ratio": {
                        "type": "string",
                        "enum": ["1:1", "4:5", "3:4", "16:9", "9:16"],
                        "default": "4:5"
                    },
                    "mode": {
                        "type": "string",
                        "enum": ["crop", "pad"],
                        "default": "crop"
                    },
                    "background": {
                        "$ref": "#/components/schemas/ImageActionColor"
                    }
                },
                "additionalProperties": false
            },
            "SideBySideActionParameters": {
                "type": "object",
                "properties": {
                    "direction": {
                        "type": "string",
                        "enum": ["horizontal", "vertical"],
                        "default": "horizontal"
                    },
                    "gap": {
                        "type": "integer",
                        "minimum": 0,
                        "maximum": 512,
                        "default": 0
                    },
                    "background": {
                        "$ref": "#/components/schemas/ImageActionColor"
                    }
                },
                "additionalProperties": false
            },
            "AddTextActionParameters": {
                "type": "object",
                "required": ["text"],
                "properties": {
                    "text": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 500
                    },
                    "fontSize": {
                        "type": "integer",
                        "minimum": 8,
                        "maximum": 512,
                        "default": 64
                    },
                    "position": {
                        "type": "string",
                        "enum": ["top", "center", "bottom"],
                        "default": "bottom"
                    },
                    "color": {
                        "$ref": "#/components/schemas/ImageActionColor"
                    },
                    "background": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/ImageActionColor"
                            }
                        ],
                        "default": "#00000099"
                    },
                    "padding": {
                        "type": "integer",
                        "minimum": 0,
                        "maximum": 512,
                        "default": 32
                    }
                },
                "additionalProperties": false
            },
            "OverlayImageActionParameters": {
                "type": "object",
                "properties": {
                    "position": {
                        "type": "string",
                        "enum": ["top-left", "top-right", "center", "bottom-left", "bottom-right"],
                        "default": "center"
                    },
                    "scale": {
                        "type": "number",
                        "minimum": 0.05,
                        "maximum": 1,
                        "multipleOf": 0.05,
                        "default": 0.25
                    },
                    "opacity": {
                        "type": "number",
                        "minimum": 0.05,
                        "maximum": 1,
                        "multipleOf": 0.05,
                        "default": 1
                    },
                    "margin": {
                        "type": "integer",
                        "minimum": 0,
                        "maximum": 1024,
                        "default": 24
                    }
                },
                "additionalProperties": false
            },
            "ColorGradeActionParameters": {
                "type": "object",
                "properties": {
                    "brightness": {
                        "type": "number",
                        "minimum": 0.1,
                        "maximum": 3,
                        "multipleOf": 0.05,
                        "default": 1
                    },
                    "saturation": {
                        "type": "number",
                        "minimum": 0,
                        "maximum": 3,
                        "multipleOf": 0.05,
                        "default": 1
                    },
                    "hue": {
                        "type": "number",
                        "minimum": -180,
                        "maximum": 180,
                        "multipleOf": 1,
                        "default": 0
                    },
                    "contrast": {
                        "type": "number",
                        "minimum": 0.1,
                        "maximum": 3,
                        "multipleOf": 0.05,
                        "default": 1
                    }
                },
                "additionalProperties": false
            },
            "RotateActionParameters": {
                "type": "object",
                "properties": {
                    "angle": {
                        "type": "number",
                        "enum": [90, 180, 270],
                        "default": 90
                    },
                    "background": {
                        "$ref": "#/components/schemas/ImageActionColor"
                    }
                },
                "additionalProperties": false
            },
            "ImageActionColor": {
                "type": "string",
                "pattern": "^(?:transparent|#[0-9A-Fa-f]{6}(?:[0-9A-Fa-f]{2})?)$",
                "default": "#ffffff"
            },
            "ImageJob": {
                "type": "object",
                "required": ["id", "run", "kind", "pollUrl", "status"],
                "properties": {
                    "id": {
                        "type": "string",
                        "pattern": "^job:"
                    },
                    "run": {
                        "type": "string",
                        "pattern": "^run:"
                    },
                    "kind": {
                        "type": "string",
                        "enum": ["image", "action"]
                    },
                    "pollUrl": {
                        "type": "string",
                        "pattern": "^/api/canvas-agent/v1/runs/"
                    },
                    "rawId": {
                        "type": "string",
                        "format": "uuid"
                    },
                    "status": {
                        "type": "string",
                        "enum": ["preparing", "queued", "running", "finalizing", "canceling", "succeeded", "failed", "canceled", "expired"],
                        "description": "Current temporary job state. Successful results retain the observation record for 24 hours before the first successful server finalization and 15 minutes after it; an authenticated Run GET or pre-callback worker finalization both count. Failed and canceled records keep the normal 24-hour window. Expired tombstones remain seven days."
                    },
                    "estimatedSeconds": {
                        "type": "integer",
                        "minimum": 1,
                        "description": "Typical provider runtime for the selected model. This is guidance, not a deadline."
                    },
                    "durationMs": {
                        "type": "integer",
                        "minimum": 0,
                        "description": "Total observed duration once the job is terminal."
                    },
                    "timing": {
                        "$ref": "#/components/schemas/ImageJobTiming"
                    },
                    "failure": {
                        "$ref": "#/components/schemas/ImageJobFailure"
                    },
                    "webhook": {
                        "$ref": "#/components/schemas/ImageJobWebhookDelivery"
                    },
                    "replayed": {
                        "type": "boolean"
                    },
                    "operation": {
                        "type": "string",
                        "enum": ["generate", "edit", "variations", "action"]
                    },
                    "actionId": {
                        "type": "string",
                        "pattern": "^action:"
                    },
                    "actionVersion": {
                        "type": "string"
                    },
                    "canvasId": {
                        "type": "string",
                        "pattern": "^canvas:"
                    },
                    "canvasRevision": {
                        "type": "string"
                    },
                    "canvasUrl": {
                        "type": "string",
                        "format": "uri"
                    },
                    "canceledAt": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "cancelReason": {
                        "type": "string",
                        "enum": ["stale_preparing", "user_requested", "setup_failed"]
                    },
                    "targets": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "pattern": "^node:"
                        }
                    },
                    "references": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        }
                    },
                    "images": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/ImageJobResultImage"
                        }
                    }
                },
                "additionalProperties": true
            },
            "VideoJob": {
                "type": "object",
                "required": ["id", "rawId", "kind", "operation", "pollUrl", "status", "model", "progress", "estimatedSeconds", "createdAt", "updatedAt"],
                "properties": {
                    "id": {
                        "type": "string",
                        "pattern": "^job:"
                    },
                    "rawId": {
                        "type": "string",
                        "format": "uuid"
                    },
                    "kind": {
                        "const": "video"
                    },
                    "operation": {
                        "const": "generate"
                    },
                    "pollUrl": {
                        "type": "string",
                        "pattern": "^/api/canvas-agent/v1/jobs/"
                    },
                    "status": {
                        "type": "string",
                        "enum": ["queued", "running", "succeeded", "failed", "canceled"]
                    },
                    "model": {
                        "type": "object",
                        "required": ["id", "name"],
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "name": {
                                "type": "string"
                            }
                        },
                        "additionalProperties": false
                    },
                    "progress": {
                        "type": "number",
                        "minimum": 0,
                        "maximum": 100
                    },
                    "estimatedSeconds": {
                        "type": "integer",
                        "minimum": 1
                    },
                    "providerRunId": {
                        "type": "string"
                    },
                    "failure": {
                        "$ref": "#/components/schemas/VideoJobFailure"
                    },
                    "video": {
                        "type": "object",
                        "required": ["downloadUrl"],
                        "properties": {
                            "downloadUrl": {
                                "type": "string",
                                "pattern": "^/api/canvas-agent/v1/jobs/.+/output$"
                            }
                        },
                        "additionalProperties": false
                    },
                    "replayed": {
                        "type": "boolean"
                    },
                    "createdAt": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "updatedAt": {
                        "type": "string",
                        "format": "date-time"
                    }
                },
                "additionalProperties": false
            },
            "VideoJobFailure": {
                "type": "object",
                "required": ["code", "message", "retryable"],
                "properties": {
                    "code": {
                        "type": "string",
                        "enum": ["video_generation_failed", "canceled"]
                    },
                    "message": {
                        "type": "string"
                    },
                    "retryable": {
                        "type": "boolean"
                    }
                },
                "additionalProperties": false
            },
            "ImageJobFailure": {
                "type": "object",
                "required": ["code", "message", "retryable"],
                "properties": {
                    "code": {
                        "type": "string",
                        "enum": ["provider_authentication_failed", "provider_timeout", "provider_rate_limited", "provider_rejected", "provider_unavailable", "runtime_failed", "action_input_invalid", "result_expired"]
                    },
                    "message": {
                        "type": "string"
                    },
                    "retryable": {
                        "type": "boolean"
                    },
                    "providerStatus": {
                        "type": "integer",
                        "minimum": 400,
                        "maximum": 599
                    }
                },
                "additionalProperties": false
            },
            "ImageJobTiming": {
                "type": "object",
                "properties": {
                    "createdAt": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "queuedAt": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "startedAt": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "completedAt": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "queueDurationMs": {
                        "type": "integer",
                        "minimum": 0
                    },
                    "executionDurationMs": {
                        "type": "integer",
                        "minimum": 0
                    },
                    "totalDurationMs": {
                        "type": "integer",
                        "minimum": 0
                    }
                },
                "additionalProperties": false
            },
            "ImageJobWebhookDelivery": {
                "description": "Durable delivery state. Gavana makes four total attempts. Retryable network failures and 408, 425, 429, or 5xx responses back off for 10 seconds, 60 seconds, then 5 minutes; redirects and other 4xx responses stop delivery.",
                "type": "object",
                "required": ["id", "status", "attempts"],
                "properties": {
                    "id": {
                        "type": "string",
                        "pattern": "^webhook:"
                    },
                    "status": {
                        "type": "string",
                        "enum": ["pending", "delivering", "delivered", "failed"]
                    },
                    "attempts": {
                        "type": "integer",
                        "minimum": 0
                    },
                    "nextAttemptAt": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "lastAttemptAt": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "deliveredAt": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "lastStatus": {
                        "type": "integer",
                        "minimum": 100,
                        "maximum": 599
                    },
                    "errorCode": {
                        "type": "string",
                        "enum": ["invalid_destination", "delivery_failed", "redirect_not_allowed", "endpoint_rejected", "secret_unavailable", "finalization_unavailable", "finalization_auth_unavailable", "finalization_auth_expired", "finalization_failed"]
                    }
                },
                "additionalProperties": false
            },
            "ImageJobResultImage": {
                "type": "object",
                "required": ["assetId", "nodeId", "previewUrl"],
                "properties": {
                    "assetId": {
                        "type": "string",
                        "pattern": "^asset:"
                    },
                    "nodeId": {
                        "type": "string",
                        "pattern": "^node:"
                    },
                    "mediaType": {
                        "type": "string",
                        "pattern": "^image/"
                    },
                    "width": {
                        "type": "integer",
                        "minimum": 1
                    },
                    "height": {
                        "type": "integer",
                        "minimum": 1
                    },
                    "bytes": {
                        "type": "integer",
                        "minimum": 1
                    },
                    "previewUrl": {
                        "type": "string",
                        "format": "uri"
                    },
                    "markdown": {
                        "type": "string"
                    }
                },
                "additionalProperties": false
            },
            "ImageJobWebhookPayload": {
                "type": "object",
                "required": ["id", "run", "status", "targets"],
                "properties": {
                    "id": {
                        "type": "string",
                        "pattern": "^(?:run|job):"
                    },
                    "run": {
                        "type": "string",
                        "pattern": "^run:"
                    },
                    "kind": {
                        "type": "string",
                        "enum": ["image", "action"]
                    },
                    "pollUrl": {
                        "type": "string",
                        "pattern": "^/api/canvas-agent/v1/runs/"
                    },
                    "status": {
                        "type": "string",
                        "enum": ["succeeded", "failed", "canceled", "expired"]
                    },
                    "operation": {
                        "type": "string",
                        "enum": ["generate", "edit", "variations", "action"]
                    },
                    "actionId": {
                        "type": "string",
                        "pattern": "^action:"
                    },
                    "actionVersion": {
                        "type": "string"
                    },
                    "canvasId": {
                        "type": "string",
                        "pattern": "^canvas:"
                    },
                    "canvasRevision": {
                        "type": "string"
                    },
                    "canvasUrl": {
                        "type": "string",
                        "format": "uri"
                    },
                    "finalizedAt": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "targets": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "pattern": "^node:"
                        }
                    },
                    "model": {
                        "type": "string"
                    },
                    "estimatedSeconds": {
                        "type": "integer",
                        "minimum": 1
                    },
                    "durationMs": {
                        "type": "integer",
                        "minimum": 0
                    },
                    "timing": {
                        "$ref": "#/components/schemas/ImageJobTiming"
                    },
                    "images": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/ImageJobResultImage"
                        }
                    },
                    "warnings": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        }
                    },
                    "references": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        }
                    },
                    "referenceNodes": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "pattern": "^node:"
                        }
                    },
                    "failure": {
                        "type": "object",
                        "required": ["code", "retryable"],
                        "properties": {
                            "code": {
                                "type": "string"
                            },
                            "retryable": {
                                "type": "boolean"
                            }
                        },
                        "additionalProperties": false
                    }
                },
                "additionalProperties": false
            },
            "ImageJobWebhookEvent": {
                "type": "object",
                "required": ["id", "type", "apiVersion", "createdAt", "data"],
                "properties": {
                    "id": {
                        "type": "string",
                        "pattern": "^event:"
                    },
                    "type": {
                        "type": "string",
                        "enum": ["image_job.succeeded", "image_job.failed", "image_job.canceled", "image_job.expired", "image_job.finalization_failed"]
                    },
                    "apiVersion": {
                        "type": "string",
                        "const": "v1"
                    },
                    "createdAt": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "data": {
                        "type": "object",
                        "required": ["run", "job"],
                        "properties": {
                            "run": {
                                "allOf": [
                                    {
                                        "$ref": "#/components/schemas/ImageJobWebhookPayload"
                                    },
                                    {
                                        "properties": {
                                            "id": {
                                                "pattern": "^run:"
                                            }
                                        }
                                    }
                                ]
                            },
                            "job": {
                                "allOf": [
                                    {
                                        "$ref": "#/components/schemas/ImageJobWebhookPayload"
                                    },
                                    {
                                        "properties": {
                                            "id": {
                                                "pattern": "^job:"
                                            }
                                        }
                                    }
                                ]
                            }
                        },
                        "additionalProperties": false
                    }
                },
                "additionalProperties": false
            },
            "ImageJobInputBase": {
                "type": "object",
                "required": ["canvasId", "baseRevision", "idempotencyKey"],
                "properties": {
                    "canvasId": {
                        "type": "string",
                        "description": "A plain id, canvas:<id>, or canvas:<ownerUid>:<id> handle."
                    },
                    "baseRevision": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 200
                    },
                    "idempotencyKey": {
                        "type": "string",
                        "minLength": 8,
                        "maxLength": 200
                    },
                    "targetNodeId": {
                        "type": "string",
                        "pattern": "^(?:node:)?[A-Za-z0-9_-]{1,180}$"
                    },
                    "targetNodeIds": {
                        "type": "array",
                        "minItems": 1,
                        "maxItems": 4,
                        "uniqueItems": true,
                        "items": {
                            "type": "string",
                            "pattern": "^(?:node:)?[A-Za-z0-9_-]{1,180}$"
                        }
                    },
                    "prompt": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 8000
                    },
                    "promptNodeId": {
                        "type": "string",
                        "pattern": "^(?:node:)?[A-Za-z0-9_-]{1,180}$"
                    },
                    "references": {
                        "type": "array",
                        "description": "Stable image handles. Across references and source, at most 16 handles are allowed and every handle must be unique.",
                        "minItems": 1,
                        "maxItems": 16,
                        "uniqueItems": true,
                        "items": {
                            "type": "string",
                            "pattern": "^(?:node:[A-Za-z0-9_-]{1,180}|asset:(?:[A-Za-z0-9_-]{1,180}:)?[A-Za-z0-9_-]{1,180})$"
                        }
                    },
                    "source": {
                        "type": "string",
                        "description": "A convenience reference appended to references. It must be unique across both fields, and the combined maximum is 16.",
                        "pattern": "^(?:node:[A-Za-z0-9_-]{1,180}|asset:(?:[A-Za-z0-9_-]{1,180}:)?[A-Za-z0-9_-]{1,180})$"
                    },
                    "count": {
                        "type": "integer",
                        "description": "Number of outputs. When supplied, it must equal the selected target count; when omitted, Gavana uses the selected target count.",
                        "minimum": 1,
                        "maximum": 4
                    },
                    "connectionId": {
                        "$ref": "#/components/schemas/StableId"
                    },
                    "model": {
                        "type": "string",
                        "maxLength": 650,
                        "description": "A provider model id or opaque model:<key> handle from GET /models."
                    },
                    "size": {
                        "type": "string",
                        "maxLength": 80
                    },
                    "quality": {
                        "type": "string",
                        "maxLength": 80
                    },
                    "webhook": {
                        "$ref": "#/components/schemas/ImageJobWebhookInput"
                    }
                },
                "allOf": [
                    {
                        "if": {
                            "required": ["references", "source"]
                        },
                        "then": {
                            "properties": {
                                "references": {
                                    "maxItems": 15
                                }
                            }
                        }
                    },
                    {
                        "anyOf": [
                            {
                                "required": ["targetNodeId"],
                                "not": {
                                    "required": ["targetNodeIds"]
                                },
                                "anyOf": [
                                    {
                                        "not": {
                                            "required": ["count"]
                                        }
                                    },
                                    {
                                        "properties": {
                                            "count": {
                                                "const": 1
                                            }
                                        }
                                    }
                                ]
                            },
                            {
                                "required": ["targetNodeIds"],
                                "properties": {
                                    "targetNodeIds": {
                                        "minItems": 1,
                                        "maxItems": 1
                                    }
                                },
                                "anyOf": [
                                    {
                                        "not": {
                                            "required": ["count"]
                                        }
                                    },
                                    {
                                        "properties": {
                                            "count": {
                                                "const": 1
                                            }
                                        }
                                    }
                                ]
                            },
                            {
                                "required": ["targetNodeIds"],
                                "properties": {
                                    "targetNodeIds": {
                                        "minItems": 2,
                                        "maxItems": 2
                                    }
                                },
                                "anyOf": [
                                    {
                                        "not": {
                                            "required": ["count"]
                                        }
                                    },
                                    {
                                        "properties": {
                                            "count": {
                                                "const": 2
                                            }
                                        }
                                    }
                                ]
                            },
                            {
                                "required": ["targetNodeIds"],
                                "properties": {
                                    "targetNodeIds": {
                                        "minItems": 3,
                                        "maxItems": 3
                                    }
                                },
                                "anyOf": [
                                    {
                                        "not": {
                                            "required": ["count"]
                                        }
                                    },
                                    {
                                        "properties": {
                                            "count": {
                                                "const": 3
                                            }
                                        }
                                    }
                                ]
                            },
                            {
                                "required": ["targetNodeIds"],
                                "properties": {
                                    "targetNodeIds": {
                                        "minItems": 4,
                                        "maxItems": 4
                                    }
                                },
                                "anyOf": [
                                    {
                                        "not": {
                                            "required": ["count"]
                                        }
                                    },
                                    {
                                        "properties": {
                                            "count": {
                                                "const": 4
                                            }
                                        }
                                    }
                                ]
                            }
                        ]
                    }
                ],
                "x-craftboard-cross-field-rules": ["references and source contain at most 16 handles combined", "references and source are unique when combined", "count equals the selected target count"],
                "additionalProperties": false
            },
            "VideoGenerationInput": {
                "type": "object",
                "required": ["model", "prompt", "idempotencyKey"],
                "properties": {
                    "model": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 650,
                        "description": "A provider model id or opaque model:<key> handle from GET /models?capability=video.generate."
                    },
                    "connectionId": {
                        "$ref": "#/components/schemas/StableId"
                    },
                    "prompt": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 8000
                    },
                    "idempotencyKey": {
                        "type": "string",
                        "minLength": 8,
                        "maxLength": 200,
                        "description": "A stable retry key. Reusing it with the same request returns the original job; reusing it with different inputs returns 409."
                    },
                    "canvasId": {
                        "type": "string",
                        "description": "Required when a frame or reference is a node: handle. Accepts a plain id, canvas:<id>, or canvas:<ownerUid>:<id>."
                    },
                    "ownerUid": {
                        "$ref": "#/components/schemas/StableId"
                    },
                    "aspectRatio": {
                        "type": "string",
                        "maxLength": 80
                    },
                    "durationSeconds": {
                        "type": "integer",
                        "minimum": 1,
                        "maximum": 120
                    },
                    "resolution": {
                        "type": "string",
                        "maxLength": 80
                    },
                    "generateAudio": {
                        "type": "boolean"
                    },
                    "firstFrame": {
                        "$ref": "#/components/schemas/VideoFrameReference"
                    },
                    "lastFrame": {
                        "$ref": "#/components/schemas/VideoFrameReference"
                    },
                    "references": {
                        "type": "array",
                        "maxItems": 9,
                        "uniqueItems": true,
                        "items": {
                            "$ref": "#/components/schemas/VideoFrameReference"
                        }
                    }
                },
                "allOf": [
                    {
                        "if": {
                            "required": ["lastFrame"]
                        },
                        "then": {
                            "required": ["firstFrame"]
                        }
                    }
                ],
                "x-craftboard-cross-field-rules": ["lastFrame requires firstFrame", "node: frame references require canvasId", "connectionId must match the selected model handle when both are supplied"],
                "additionalProperties": false
            },
            "VideoFrameReference": {
                "type": "string",
                "maxLength": 2048,
                "pattern": "^(?:node:[A-Za-z0-9_-]{1,180}|asset:(?:[A-Za-z0-9_-]{1,180}:)?[A-Za-z0-9_-]{1,180}|https://.+)$",
                "description": "A stable image node or asset handle, or a public HTTPS image URL."
            },
            "ImageJobWebhookInput": {
                "type": "object",
                "required": ["url", "secret"],
                "properties": {
                    "url": {
                        "type": "string",
                        "format": "uri",
                        "pattern": "^https://",
                        "maxLength": 2048,
                        "description": "A public HTTPS callback endpoint. Private, loopback, local-network, credential-bearing, and fragment-bearing URLs are rejected."
                    },
                    "secret": {
                        "type": "string",
                        "minLength": 32,
                        "maxLength": 512,
                        "writeOnly": true,
                        "description": "A caller-owned HMAC secret encrypted at rest and never returned by the API."
                    }
                },
                "additionalProperties": false
            },
            "ImageModel": {
                "type": "object",
                "required": ["id", "handle", "modelId", "name", "provider", "providerLabel", "connectionId", "connectionName", "type", "capabilities", "parameters", "estimatedSeconds", "beta"],
                "properties": {
                    "id": {
                        "type": "string",
                        "pattern": "^[A-Za-z0-9_-]{8,600}$"
                    },
                    "handle": {
                        "type": "string",
                        "pattern": "^model:[A-Za-z0-9_-]{8,600}$"
                    },
                    "modelId": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 240
                    },
                    "name": {
                        "type": "string"
                    },
                    "provider": {
                        "type": "string",
                        "enum": ["craftboard", "openai", "google/nano-banana", "black-forest-labs", "recraft", "ideogram", "qwen", "openrouter"]
                    },
                    "providerLabel": {
                        "type": "string"
                    },
                    "connectionId": {
                        "oneOf": [
                            {
                                "$ref": "#/components/schemas/StableId"
                            },
                            {
                                "type": "null"
                            }
                        ]
                    },
                    "connectionName": {
                        "type": "string"
                    },
                    "type": {
                        "type": "string",
                        "enum": ["image", "video"]
                    },
                    "capabilities": {
                        "type": "array",
                        "minItems": 1,
                        "uniqueItems": true,
                        "items": {
                            "$ref": "#/components/schemas/ImageModelCapability"
                        }
                    },
                    "parameters": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/ImageModelParameter"
                        }
                    },
                    "estimatedSeconds": {
                        "type": "integer",
                        "minimum": 1
                    },
                    "beta": {
                        "type": "boolean"
                    }
                },
                "additionalProperties": false
            },
            "ImageModelCapability": {
                "type": "string",
                "enum": ["image.generate", "image.edit", "image.variations", "video.generate", "video.generate.fromImage", "video.generate.fromFrames", "video.generate.fromReferences"]
            },
            "ImageModelParameter": {
                "type": "object",
                "required": ["name", "label", "description", "type", "required", "capabilities"],
                "properties": {
                    "name": {
                        "type": "string"
                    },
                    "label": {
                        "type": "string"
                    },
                    "description": {
                        "type": "string"
                    },
                    "type": {
                        "type": "string",
                        "enum": ["string", "integer", "number", "boolean", "string[]", "image[]"]
                    },
                    "required": {
                        "type": "boolean"
                    },
                    "default": {},
                    "min": {
                        "type": "number"
                    },
                    "max": {
                        "type": "number"
                    },
                    "options": {
                        "type": "array",
                        "items": {
                            "type": "object",
                            "required": ["label", "value"],
                            "properties": {
                                "label": {
                                    "type": "string"
                                },
                                "value": {
                                    "type": "string"
                                },
                                "description": {
                                    "type": "string"
                                }
                            },
                            "additionalProperties": false
                        }
                    },
                    "capabilities": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/ImageModelCapability"
                        }
                    }
                },
                "additionalProperties": false
            },
            "ImageGenerationInput": {
                "allOf": [
                    {
                        "$ref": "#/components/schemas/ImageJobInputBase"
                    },
                    {
                        "anyOf": [
                            {
                                "required": ["prompt"]
                            },
                            {
                                "required": ["promptNodeId"]
                            }
                        ]
                    }
                ]
            },
            "ImageImportInput": {
                "type": "object",
                "required": ["canvasId", "imageUrl", "idempotencyKey"],
                "properties": {
                    "canvasId": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 600,
                        "description": "A plain id, canvas:<id>, or canvas:<ownerUid>:<id> handle."
                    },
                    "imageUrl": {
                        "type": "string",
                        "format": "uri",
                        "pattern": "^https://",
                        "maxLength": 4096
                    },
                    "sourceId": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 1000,
                        "description": "Optional stable source identity, such as ChatGPT file_id. When present, Gavana uses it instead of the expiring download URL to match idempotent retries."
                    },
                    "title": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 160,
                        "default": "Image from ChatGPT"
                    },
                    "idempotencyKey": {
                        "type": "string",
                        "minLength": 8,
                        "maxLength": 200
                    },
                    "x": {
                        "type": "number",
                        "minimum": -100000,
                        "maximum": 100000
                    },
                    "y": {
                        "type": "number",
                        "minimum": -100000,
                        "maximum": 100000
                    }
                },
                "additionalProperties": false
            },
            "ImageImportResponse": {
                "type": "object",
                "required": ["status", "replayed", "canvasId", "canvasRevision", "canvasUrl", "image"],
                "properties": {
                    "status": {
                        "const": "succeeded"
                    },
                    "replayed": {
                        "type": "boolean"
                    },
                    "canvasId": {
                        "type": "string",
                        "pattern": "^canvas:"
                    },
                    "canvasRevision": {
                        "type": "string"
                    },
                    "canvasUrl": {
                        "type": "string",
                        "format": "uri"
                    },
                    "image": {
                        "type": "object",
                        "required": ["assetId", "nodeId", "mediaType", "width", "height", "bytes", "previewUrl", "markdown"],
                        "properties": {
                            "assetId": {
                                "type": "string",
                                "pattern": "^asset:"
                            },
                            "nodeId": {
                                "type": "string",
                                "pattern": "^node:"
                            },
                            "mediaType": {
                                "type": "string",
                                "enum": ["image/png", "image/jpeg", "image/webp", "image/gif"]
                            },
                            "width": {
                                "type": "integer",
                                "minimum": 1
                            },
                            "height": {
                                "type": "integer",
                                "minimum": 1
                            },
                            "bytes": {
                                "type": "integer",
                                "minimum": 1,
                                "maximum": 52428800
                            },
                            "previewUrl": {
                                "type": "string",
                                "format": "uri"
                            },
                            "markdown": {
                                "type": "string"
                            }
                        },
                        "additionalProperties": false
                    }
                },
                "additionalProperties": false
            },
            "ImageEditInput": {
                "allOf": [
                    {
                        "$ref": "#/components/schemas/ImageJobInputBase"
                    },
                    {
                        "allOf": [
                            {
                                "anyOf": [
                                    {
                                        "required": ["prompt"]
                                    },
                                    {
                                        "required": ["promptNodeId"]
                                    }
                                ]
                            },
                            {
                                "anyOf": [
                                    {
                                        "required": ["references"]
                                    },
                                    {
                                        "required": ["source"]
                                    }
                                ]
                            }
                        ]
                    }
                ]
            },
            "ImageVariationsInput": {
                "allOf": [
                    {
                        "$ref": "#/components/schemas/ImageJobInputBase"
                    },
                    {
                        "anyOf": [
                            {
                                "required": ["references"]
                            },
                            {
                                "required": ["source"]
                            }
                        ]
                    }
                ]
            },
            "MutationResponse": {
                "type": "object",
                "required": ["canvas"],
                "properties": {
                    "canvas": {
                        "$ref": "#/components/schemas/Canvas"
                    },
                    "replayed": {
                        "type": "boolean"
                    },
                    "resolvedIds": {
                        "type": "object",
                        "additionalProperties": {
                            "type": "string"
                        }
                    },
                    "changedNodeIds": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "pattern": "^node:"
                        }
                    },
                    "deletedNodeIds": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "pattern": "^node:"
                        }
                    },
                    "changedConnectionIds": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "pattern": "^connection:"
                        }
                    },
                    "deletedConnectionIds": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "pattern": "^connection:"
                        }
                    }
                },
                "additionalProperties": true
            },
            "Position": {
                "type": "object",
                "required": ["x", "y"],
                "properties": {
                    "x": {
                        "type": "number",
                        "minimum": -10000000,
                        "maximum": 10000000
                    },
                    "y": {
                        "type": "number",
                        "minimum": -10000000,
                        "maximum": 10000000
                    }
                },
                "additionalProperties": false
            },
            "ProviderConnection": {
                "type": "object",
                "required": ["id", "provider", "name", "maskedKey", "models"],
                "properties": {
                    "id": {
                        "$ref": "#/components/schemas/StableId"
                    },
                    "provider": {
                        "type": "string",
                        "enum": ["openai", "google/nano-banana", "black-forest-labs", "recraft", "ideogram", "qwen", "openrouter"]
                    },
                    "name": {
                        "type": "string"
                    },
                    "maskedKey": {
                        "type": "string"
                    },
                    "models": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        }
                    }
                },
                "additionalProperties": true
            },
            "Recipe": {
                "type": "object",
                "required": ["id", "handle", "version", "name", "inputs", "outputs"],
                "properties": {
                    "id": {
                        "$ref": "#/components/schemas/StableId"
                    },
                    "handle": {
                        "type": "string",
                        "pattern": "^recipe:"
                    },
                    "version": {
                        "type": "string"
                    },
                    "name": {
                        "type": "string"
                    },
                    "summary": {
                        "type": "string"
                    },
                    "description": {
                        "type": "string"
                    },
                    "tags": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        }
                    },
                    "inputs": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/RecipePort"
                        }
                    },
                    "outputs": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/RecipePort"
                        }
                    }
                },
                "additionalProperties": true
            },
            "RecipePort": {
                "description": "A named typed Recipe boundary port. Written reference ports may deliberately accept either written content or an image reference when the Recipe description declares that intent.",
                "type": "object",
                "required": ["nodeId", "label", "description", "useAsPreset", "nodeType"],
                "properties": {
                    "nodeId": {
                        "$ref": "#/components/schemas/StableId"
                    },
                    "key": {
                        "type": "string",
                        "pattern": "^[A-Za-z0-9_-]{1,80}$",
                        "description": "Optional stable caller-facing key for a high-level workflow input or output."
                    },
                    "label": {
                        "type": "string"
                    },
                    "description": {
                        "type": "string"
                    },
                    "useAsPreset": {
                        "type": "boolean"
                    },
                    "nodeType": {
                        "type": "string",
                        "enum": ["image", "text", "sticky"]
                    }
                },
                "additionalProperties": true
            },
            "RecipeForkInput": {
                "type": "object",
                "required": ["canvasId", "baseRevision", "idempotencyKey"],
                "properties": {
                    "canvasId": {
                        "type": "string",
                        "description": "A plain canvas id."
                    },
                    "ownerUid": {
                        "$ref": "#/components/schemas/StableId"
                    },
                    "version": {
                        "type": "string",
                        "maxLength": 80
                    },
                    "baseRevision": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 200
                    },
                    "idempotencyKey": {
                        "type": "string",
                        "minLength": 8,
                        "maxLength": 200
                    },
                    "x": {
                        "type": "number",
                        "minimum": -100000,
                        "maximum": 100000
                    },
                    "y": {
                        "type": "number",
                        "minimum": -100000,
                        "maximum": 100000
                    }
                },
                "additionalProperties": false
            },
            "RecipeRunInput": {
                "type": "object",
                "required": ["canvasId", "baseRevision", "idempotencyKey"],
                "properties": {
                    "canvasId": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 560,
                        "description": "Stable canvas:<id> or canvas:<ownerUid>:<id> destination."
                    },
                    "baseRevision": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 200
                    },
                    "idempotencyKey": {
                        "type": "string",
                        "minLength": 8,
                        "maxLength": 200
                    },
                    "version": {
                        "type": "string",
                        "maxLength": 80
                    },
                    "instanceNodeId": {
                        "type": "string",
                        "pattern": "^(?:node:)?[A-Za-z0-9_-]{1,180}$",
                        "description": "Optional private Recipe instance already present and connected on the destination canvas."
                    },
                    "inputs": {
                        "type": "object",
                        "maxProperties": 16,
                        "description": "Typed values keyed by the declared input node id or normalized label. Values may be node:, asset:, or plain text.",
                        "additionalProperties": {
                            "type": "string",
                            "minLength": 1,
                            "maxLength": 8000
                        }
                    },
                    "model": {
                        "type": "string",
                        "maxLength": 650,
                        "description": "Optional model handle or provider model override for image outputs."
                    },
                    "size": {
                        "type": "string",
                        "maxLength": 80,
                        "description": "Optional size override for image outputs."
                    },
                    "quality": {
                        "type": "string",
                        "maxLength": 80,
                        "description": "Optional quality override for image outputs."
                    },
                    "webhook": {
                        "$ref": "#/components/schemas/ImageJobWebhookInput"
                    }
                },
                "additionalProperties": false
            },
            "RecipeRunInputBinding": {
                "type": "object",
                "required": ["key", "label", "type", "nodeId", "nodeHandle", "summary"],
                "properties": {
                    "key": {
                        "type": "string"
                    },
                    "label": {
                        "type": "string"
                    },
                    "type": {
                        "type": "string",
                        "enum": ["image", "text", "sticky"]
                    },
                    "nodeId": {
                        "$ref": "#/components/schemas/StableId"
                    },
                    "nodeHandle": {
                        "type": "string",
                        "pattern": "^node:"
                    },
                    "sourceHandle": {
                        "type": "string",
                        "pattern": "^(?:node|asset):"
                    },
                    "summary": {
                        "type": "string"
                    }
                },
                "additionalProperties": false
            },
            "RecipeRunFailure": {
                "type": "object",
                "required": ["code", "message", "retryable"],
                "properties": {
                    "code": {
                        "type": "string",
                        "enum": ["recipe_input_invalid", "recipe_step_failed", "recipe_output_missing", "recipe_run_canceled", "delegation_revoked"]
                    },
                    "message": {
                        "type": "string"
                    },
                    "retryable": {
                        "type": "boolean"
                    },
                    "outputKey": {
                        "type": "string"
                    }
                },
                "additionalProperties": false
            },
            "RecipeRunOutput": {
                "type": "object",
                "required": ["key", "label", "type", "status", "nodeId", "nodeHandle"],
                "properties": {
                    "key": {
                        "type": "string"
                    },
                    "label": {
                        "type": "string"
                    },
                    "type": {
                        "type": "string",
                        "enum": ["image", "text", "sticky"]
                    },
                    "status": {
                        "type": "string",
                        "enum": ["pending", "running", "succeeded", "failed", "canceled"]
                    },
                    "nodeId": {
                        "$ref": "#/components/schemas/StableId"
                    },
                    "nodeHandle": {
                        "type": "string",
                        "pattern": "^node:"
                    },
                    "jobId": {
                        "type": "string",
                        "format": "uuid"
                    },
                    "runHandle": {
                        "type": "string",
                        "pattern": "^run:"
                    },
                    "assetId": {
                        "type": "string",
                        "pattern": "^asset:"
                    },
                    "value": {
                        "type": "string",
                        "maxLength": 24000
                    },
                    "startedAt": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "completedAt": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "failure": {
                        "$ref": "#/components/schemas/RecipeRunFailure"
                    }
                },
                "additionalProperties": false
            },
            "RecipeRun": {
                "type": "object",
                "required": [
                    "schemaVersion",
                    "id",
                    "rawId",
                    "handle",
                    "run",
                    "kind",
                    "operation",
                    "status",
                    "recipeId",
                    "recipeHandle",
                    "recipeVersion",
                    "recipeInstanceNodeId",
                    "recipeInstanceNodeHandle",
                    "canvasId",
                    "canvasHandle",
                    "inputs",
                    "outputs",
                    "targets",
                    "currentStep",
                    "estimatedSeconds",
                    "timing",
                    "pollUrl",
                    "createdAt",
                    "updatedAt"
                ],
                "properties": {
                    "schemaVersion": {
                        "const": 1
                    },
                    "id": {
                        "type": "string",
                        "pattern": "^recipe-"
                    },
                    "rawId": {
                        "type": "string",
                        "pattern": "^recipe-"
                    },
                    "handle": {
                        "type": "string",
                        "pattern": "^run:recipe-"
                    },
                    "run": {
                        "type": "string",
                        "pattern": "^run:recipe-"
                    },
                    "kind": {
                        "const": "recipe"
                    },
                    "operation": {
                        "const": "recipe"
                    },
                    "status": {
                        "type": "string",
                        "enum": ["queued", "running", "succeeded", "failed", "canceled"]
                    },
                    "recipeId": {
                        "$ref": "#/components/schemas/StableId"
                    },
                    "recipeHandle": {
                        "type": "string",
                        "pattern": "^recipe:"
                    },
                    "recipeVersion": {
                        "type": "string"
                    },
                    "recipeInstanceNodeId": {
                        "$ref": "#/components/schemas/StableId"
                    },
                    "recipeInstanceNodeHandle": {
                        "type": "string",
                        "pattern": "^node:"
                    },
                    "canvasId": {
                        "$ref": "#/components/schemas/StableId"
                    },
                    "canvasHandle": {
                        "type": "string",
                        "pattern": "^canvas:"
                    },
                    "canvasUrl": {
                        "type": "string",
                        "format": "uri"
                    },
                    "inputs": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/RecipeRunInputBinding"
                        }
                    },
                    "outputs": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/RecipeRunOutput"
                        }
                    },
                    "targets": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "pattern": "^node:"
                        }
                    },
                    "currentStep": {
                        "type": "string"
                    },
                    "nextStep": {
                        "type": "string"
                    },
                    "estimatedSeconds": {
                        "type": "integer",
                        "minimum": 1
                    },
                    "durationMs": {
                        "type": "integer",
                        "minimum": 0
                    },
                    "timing": {
                        "$ref": "#/components/schemas/ImageJobTiming"
                    },
                    "failure": {
                        "$ref": "#/components/schemas/RecipeRunFailure"
                    },
                    "webhook": {
                        "$ref": "#/components/schemas/ImageJobWebhookDelivery"
                    },
                    "replayed": {
                        "type": "boolean"
                    },
                    "pollUrl": {
                        "type": "string",
                        "pattern": "^/api/canvas-agent/v1/runs/"
                    },
                    "createdAt": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "updatedAt": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "startedAt": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "completedAt": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "canceledAt": {
                        "type": "string",
                        "format": "date-time"
                    }
                },
                "additionalProperties": false
            },
            "Run": {
                "oneOf": [
                    {
                        "$ref": "#/components/schemas/ImageJob"
                    },
                    {
                        "$ref": "#/components/schemas/RecipeRun"
                    }
                ]
            },
            "RecipeRunWebhookEvent": {
                "type": "object",
                "required": ["id", "type", "apiVersion", "createdAt", "data"],
                "properties": {
                    "id": {
                        "type": "string",
                        "pattern": "^event:"
                    },
                    "type": {
                        "type": "string",
                        "enum": ["recipe_run.succeeded", "recipe_run.failed", "recipe_run.canceled"]
                    },
                    "apiVersion": {
                        "const": "v1"
                    },
                    "createdAt": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "data": {
                        "type": "object",
                        "required": ["run"],
                        "properties": {
                            "run": {
                                "type": "object",
                                "required": ["id", "status", "operation", "recipeId", "recipeVersion", "canvasId", "outputs"],
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "pattern": "^run:"
                                    },
                                    "status": {
                                        "type": "string",
                                        "enum": ["succeeded", "failed", "canceled"]
                                    },
                                    "operation": {
                                        "const": "recipe"
                                    },
                                    "recipeId": {
                                        "type": "string",
                                        "pattern": "^recipe:"
                                    },
                                    "recipeVersion": {
                                        "type": "string"
                                    },
                                    "canvasId": {
                                        "type": "string",
                                        "pattern": "^canvas:"
                                    },
                                    "outputs": {
                                        "type": "array",
                                        "items": {
                                            "type": "object",
                                            "required": ["key", "status", "nodeId"],
                                            "properties": {
                                                "key": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "string",
                                                    "enum": ["succeeded", "failed", "canceled"]
                                                },
                                                "nodeId": {
                                                    "type": "string",
                                                    "pattern": "^node:"
                                                },
                                                "assetId": {
                                                    "type": "string",
                                                    "pattern": "^asset:"
                                                }
                                            },
                                            "additionalProperties": false
                                        }
                                    },
                                    "failure": {
                                        "type": "object",
                                        "required": ["code", "retryable"],
                                        "properties": {
                                            "code": {
                                                "type": "string"
                                            },
                                            "retryable": {
                                                "type": "boolean"
                                            }
                                        },
                                        "additionalProperties": false
                                    }
                                },
                                "additionalProperties": false
                            }
                        },
                        "additionalProperties": false
                    }
                },
                "additionalProperties": false
            },
            "StableId": {
                "type": "string",
                "pattern": "^[A-Za-z0-9_-]{1,180}$"
            },
            "Viewport": {
                "type": "object",
                "required": ["x", "y", "k"],
                "properties": {
                    "x": {
                        "type": "number",
                        "minimum": -10000000,
                        "maximum": 10000000
                    },
                    "y": {
                        "type": "number",
                        "minimum": -10000000,
                        "maximum": 10000000
                    },
                    "k": {
                        "type": "number",
                        "exclusiveMinimum": 0,
                        "maximum": 10
                    }
                },
                "additionalProperties": false
            }
        }
    }
}
