diff --git a/api/openapi.json b/api/openapi.json index 3de471f..e5bdc5d 100644 --- a/api/openapi.json +++ b/api/openapi.json @@ -1347,6 +1347,11 @@ "description": "Human-readable name describing what this query retrieves.", "example": "Top 5 Products by Revenue" }, + "resultId": { + "type": "string", + "description": "Stable, unique identifier for this query result within the job. Use it to reference a specific result — for example, to correlate or de-duplicate results across responses.", + "example": "928c5838-000d-4943-b305-f6242c1b4922" + }, "status": { "type": "string", "enum": [ @@ -1392,7 +1397,7 @@ "body": { "type": "string", "description": "Body / description copy shown beneath the headline on AI helper landing surfaces.", - "example": "Ask a data question to get started. I can help refine answers, adjust charts, or surface new areas to explore." + "example": "I can help answer data questions, build a Dashboard, or create an App." }, "headline": { "type": "string", @@ -1728,7 +1733,7 @@ "description": "Display-only notes about the routine, or null." }, "destination": { - "$ref": "#/components/schemas/RoutineEmailDestination" + "$ref": "#/components/schemas/RoutineDestinationResponse" }, "disabled": { "type": "boolean", @@ -1749,7 +1754,7 @@ }, "name": { "type": "string", - "description": "Customer-visible name of the routine, used as the email subject." + "description": "Customer-visible name of the routine. Used as the email subject for email destinations, and shown on Slack deliveries." }, "prompt": { "type": "string", @@ -1757,7 +1762,7 @@ }, "recipientCount": { "type": "integer", - "description": "Number of distinct deliverable recipients after expanding user groups and removing duplicates." + "description": "Number of distinct deliverable recipients. For email, user groups are expanded to members and duplicates removed; a Slack routine is always 1 (its single channel or DM)." }, "schedule": { "type": "string", @@ -1810,7 +1815,25 @@ "updatedAt" ] }, - "RoutineEmailDestination": { + "RoutineDestinationResponse": { + "oneOf": [ + { + "$ref": "#/components/schemas/RoutineEmailDestinationResponse" + }, + { + "$ref": "#/components/schemas/RoutineSlackDestination" + } + ], + "discriminator": { + "propertyName": "type", + "mapping": { + "email": "#/components/schemas/RoutineEmailDestinationResponse", + "slack": "#/components/schemas/RoutineSlackDestination" + } + }, + "description": "Delivery configuration for the routine." + }, + "RoutineEmailDestinationResponse": { "type": "object", "properties": { "recipientEmails": { @@ -1819,9 +1842,7 @@ "type": "string", "format": "email" }, - "maxItems": 100, - "default": [], - "description": "Email addresses that receive each scheduled run of the routine.", + "description": "Email addresses configured as direct recipients of each scheduled run, resolved from their current membership.", "example": [ "alice@example.com", "bob@example.com" @@ -1832,7 +1853,7 @@ "enum": [ "email" ], - "description": "Destination type. Only `email` is supported.", + "description": "Selects email delivery — each scheduled run is sent to the listed email recipients and user groups.", "example": "email" }, "userGroupIds": { @@ -1841,8 +1862,6 @@ "type": "string", "format": "uuid" }, - "maxItems": 100, - "default": [], "description": "User group IDs whose active members receive each scheduled run. Omni expands each group to the members' current email addresses when the routine runs.", "example": [ "550e8400-e29b-41d4-a716-446655440000" @@ -1850,10 +1869,45 @@ } }, "required": [ + "recipientEmails", + "type", + "userGroupIds" + ], + "additionalProperties": false + }, + "RoutineSlackDestination": { + "type": "object", + "properties": { + "recipientId": { + "type": "string", + "minLength": 1, + "description": "The Slack channel ID (e.g. \"C01234567\") or user ID (e.g. \"U01234567\") that receives each scheduled run. Exactly one recipient per Slack routine.", + "example": "C01234567" + }, + "slackRecipientType": { + "type": "string", + "enum": [ + "channel", + "users" + ], + "description": "Whether `recipientId` is a Slack channel or a user (delivered as a direct message).", + "example": "channel" + }, + "type": { + "type": "string", + "enum": [ + "slack" + ], + "description": "Selects Slack delivery — each scheduled run is posted to one Slack channel or sent as a direct message to one user.", + "example": "slack" + } + }, + "required": [ + "recipientId", + "slackRecipientType", "type" ], - "additionalProperties": false, - "description": "Email delivery configuration for the routine." + "additionalProperties": false }, "RoutineLastRun": { "type": [ @@ -1944,7 +1998,7 @@ "type": "string", "minLength": 1, "maxLength": 512, - "description": "Customer-visible name of the routine. Used as the email subject for each scheduled run.", + "description": "Customer-visible name of the routine. Used as the email subject for email destinations, and shown on Slack deliveries.", "example": "Weekly user signups" }, "prompt": { @@ -1989,16 +2043,64 @@ "oneOf": [ { "$ref": "#/components/schemas/RoutineEmailDestination" + }, + { + "$ref": "#/components/schemas/RoutineSlackDestination" } ], "discriminator": { "propertyName": "type", "mapping": { - "email": "#/components/schemas/RoutineEmailDestination" + "email": "#/components/schemas/RoutineEmailDestination", + "slack": "#/components/schemas/RoutineSlackDestination" } }, "description": "Single delivery destination for the routine. To send results to multiple destinations, create one routine per destination. Omni runs the prompt once per scheduled run using the routine owner's permissions, and every recipient receives the same result regardless of their own permissions." }, + "RoutineEmailDestination": { + "type": "object", + "properties": { + "recipientEmails": { + "type": "array", + "items": { + "type": "string", + "format": "email" + }, + "maxItems": 100, + "default": [], + "description": "Email addresses that receive each scheduled run of the routine.", + "example": [ + "alice@example.com", + "bob@example.com" + ] + }, + "type": { + "type": "string", + "enum": [ + "email" + ], + "description": "Selects email delivery — each scheduled run is sent to the listed email recipients and user groups.", + "example": "email" + }, + "userGroupIds": { + "type": "array", + "items": { + "type": "string", + "format": "uuid" + }, + "maxItems": 100, + "default": [], + "description": "User group IDs whose active members receive each scheduled run. Omni expands each group to the members' current email addresses when the routine runs.", + "example": [ + "550e8400-e29b-41d4-a716-446655440000" + ] + } + }, + "required": [ + "type" + ], + "additionalProperties": false + }, "RoutineUpdateBody": { "type": "object", "properties": { @@ -2024,7 +2126,7 @@ "type": "string", "minLength": 1, "maxLength": 512, - "description": "New customer-visible name of the routine, used as the email subject." + "description": "New customer-visible name of the routine. Used as the email subject for email destinations, and shown on Slack deliveries." }, "prompt": { "type": "string", @@ -3428,6 +3530,7 @@ "sankey", "single-record", "svg-map", + "treemap", "omni-spreadsheet", "spreadsheet-tab", "summary-value", @@ -3660,6 +3763,7 @@ "summaryValue", "svgMap", "table", + "treemap", null ], "description": "Chart type" @@ -4222,6 +4326,33 @@ "name" ] }, + "DocumentsUpgradeLayoutResponse": { + "type": "object", + "properties": { + "identifier": { + "type": "string", + "description": "Document identifier" + }, + "upgraded": { + "type": "boolean", + "description": "True when the layout was upgraded, false when the document already had advanced layout (no-op)." + } + }, + "required": [ + "identifier", + "upgraded" + ] + }, + "DocumentsUpgradeLayoutBody": { + "type": "object", + "properties": { + "clearExistingDraft": { + "type": "boolean", + "default": false, + "description": "When upgrading a published document, discard any existing draft instead of failing with a conflict." + } + } + }, "DocumentsBulkUpdateLabelsResponse": { "type": "object", "properties": { @@ -5390,6 +5521,10 @@ ], "description": "Render mode: \"chart\" for visualization, \"result\" for data table, \"ai\" for AI summary, \"metadata\" for query metadata" }, + "detachedContent": { + "type": "string", + "description": "Set when a metadata field is detached: local text rendered instead of the query value" + }, "format": { "type": "string", "enum": [ @@ -7125,10 +7260,12 @@ "type": "string" }, "value": { - "type": "string" + "type": "string", + "description": "Page link target. Must exactly equal an existing page container’s instanceKey — not its name, label, or a slug. A value matching no page redirects to the main dashboard view with a \"Page not found\" message. Ignored when `uri` is set." } } - } + }, + "description": "Omit to auto-derive one tab per page, kept in sync as pages are added, removed, renamed, or reordered. Set to curate, reorder, or add custom-URL tabs; each option’s `value` must then match a page instanceKey." }, "style": { "type": "object", @@ -11187,401 +11324,1203 @@ "type": "object", "properties": { "instanceKey": { - "type": "string" - }, - "type": { - "type": "string" - } - }, - "required": [ - "instanceKey", - "type" - ], - "additionalProperties": {} - } - ] - }, - { - "type": "object", - "properties": { - "gridPosition": { - "type": "object", - "properties": { - "h": { - "type": "number" - }, - "w": { - "type": "number" - }, - "x": { - "type": "number" + "type": "string", + "description": "Unique identifier for this specific placement of the content item. Use this key (not the query id) when repositioning or removing items." }, - "y": { - "type": "number" - } - }, - "required": [ - "h", - "w", - "x", - "y" - ] - } - }, - "required": [ - "gridPosition" - ] - } - ] - } - ] - } - }, - "containerType": { - "type": "string", - "enum": [ - "grid" - ] - }, - "gridPosition": { - "type": "object", - "properties": { - "h": { - "type": "number", - "description": "Height in grid units (default: 36 for charts)" - }, - "w": { - "type": "number", - "description": "Width in grid columns on a 24-column grid. Common widths: 24 (full), 12 (half), 8 (third), 6 (quarter). x + w must not exceed 24." - }, - "x": { - "type": "number", - "description": "X position on a 24-column grid (0=left edge, 12=middle). Items side-by-side share the same y with complementary x values." - }, - "y": { - "type": "number", - "description": "Y position in grid units (0=top, higher values=lower on page)" - } - }, - "required": [ - "h", - "w", - "x", - "y" - ] - }, - "metadata": { - "type": "object", - "properties": { - "attachedQueryKey": { - "type": "string", - "description": "Set by the auto-add-tile flow when this container was generated for a specific workbook tab. The server removes containers with a matching `attachedQueryKey` when that tab is deleted. The reducer clears this when the user adds unrelated content (a different query, filter, text tile, page switcher, or sub-container)." - }, - "generatedHeading": { - "type": "boolean", - "description": "Marks the auto-injected heading wrapper (title + description row) created for a tile, so it can be labeled generically and treated as managed." - }, - "locked": { - "type": "boolean", - "description": "Locks the container's internal arrangement so its children cannot be dragged, reordered, resized, or have new items dropped in. Cascades to all descendants. Does not lock the container's own position/size." - } - }, - "description": "Optional bookkeeping for this container (e.g. `attachedQueryKey` for auto-placed tiles)" - }, - "padding": { - "anyOf": [ - { - "type": "number", - "enum": [ - 0 - ] - }, - { - "type": "number", - "enum": [ - 0.5 - ] - }, - { - "type": "number", - "enum": [ - 1 - ] - }, - { - "type": "number", - "enum": [ - 2 - ] - }, - { - "type": "number", - "enum": [ - 3 - ] - }, - { - "type": "number", - "enum": [ - 4 - ] - }, - { - "type": "number", - "enum": [ - 5 - ] - }, - { - "type": "number", - "enum": [ - 6 - ] - }, - { - "type": "number", - "enum": [ - 7 - ] - }, - { - "type": "number", - "enum": [ - 8 - ] - }, - { - "type": "array", - "prefixItems": [ - { - "anyOf": [ - { - "type": "number", - "enum": [ - 0 - ] - }, - { - "type": "number", - "enum": [ - 0.5 - ] - }, - { - "type": "number", - "enum": [ - 1 - ] - }, - { - "type": "number", - "enum": [ - 2 - ] - }, - { - "type": "number", - "enum": [ - 3 - ] - }, - { - "type": "number", - "enum": [ - 4 - ] - }, - { - "type": "number", - "enum": [ - 5 - ] - }, - { - "type": "number", - "enum": [ - 6 - ] - }, - { - "type": "number", - "enum": [ - 7 - ] - }, - { - "type": "number", - "enum": [ - 8 - ] - } - ] - } - ] - }, - { - "type": "array", - "prefixItems": [ - { - "anyOf": [ - { - "type": "number", - "enum": [ - 0 - ] - }, - { - "type": "number", - "enum": [ - 0.5 - ] - }, - { - "type": "number", - "enum": [ - 1 - ] - }, - { - "type": "number", - "enum": [ - 2 - ] - }, - { - "type": "number", - "enum": [ - 3 - ] - }, - { - "type": "number", - "enum": [ - 4 - ] - }, - { - "type": "number", - "enum": [ - 5 - ] - }, - { - "type": "number", - "enum": [ - 6 - ] - }, - { - "type": "number", - "enum": [ - 7 - ] - }, - { - "type": "number", - "enum": [ - 8 - ] - } - ] - }, - { - "anyOf": [ - { - "type": "number", - "enum": [ - 0 - ] - }, - { - "type": "number", - "enum": [ - 0.5 - ] - }, - { - "type": "number", - "enum": [ - 1 - ] - }, - { - "type": "number", - "enum": [ - 2 - ] - }, - { - "type": "number", - "enum": [ - 3 - ] - }, - { - "type": "number", - "enum": [ - 4 - ] - }, - { - "type": "number", - "enum": [ - 5 - ] - }, - { - "type": "number", - "enum": [ - 6 - ] - }, - { - "type": "number", - "enum": [ - 7 - ] - }, - { - "type": "number", - "enum": [ - 8 - ] - } - ] - } - ] - }, - { - "type": "array", - "prefixItems": [ - { - "anyOf": [ - { - "type": "number", - "enum": [ - 0 - ] - }, - { - "type": "number", - "enum": [ - 0.5 - ] - }, - { - "type": "number", - "enum": [ - 1 - ] - }, - { - "type": "number", - "enum": [ - 2 - ] - }, - { + "padding": { + "anyOf": [ + { + "type": "number", + "enum": [ + 0 + ] + }, + { + "type": "number", + "enum": [ + 0.5 + ] + }, + { + "type": "number", + "enum": [ + 1 + ] + }, + { + "type": "number", + "enum": [ + 2 + ] + }, + { + "type": "number", + "enum": [ + 3 + ] + }, + { + "type": "number", + "enum": [ + 4 + ] + }, + { + "type": "number", + "enum": [ + 5 + ] + }, + { + "type": "number", + "enum": [ + 6 + ] + }, + { + "type": "number", + "enum": [ + 7 + ] + }, + { + "type": "number", + "enum": [ + 8 + ] + }, + { + "type": "array", + "prefixItems": [ + { + "anyOf": [ + { + "type": "number", + "enum": [ + 0 + ] + }, + { + "type": "number", + "enum": [ + 0.5 + ] + }, + { + "type": "number", + "enum": [ + 1 + ] + }, + { + "type": "number", + "enum": [ + 2 + ] + }, + { + "type": "number", + "enum": [ + 3 + ] + }, + { + "type": "number", + "enum": [ + 4 + ] + }, + { + "type": "number", + "enum": [ + 5 + ] + }, + { + "type": "number", + "enum": [ + 6 + ] + }, + { + "type": "number", + "enum": [ + 7 + ] + }, + { + "type": "number", + "enum": [ + 8 + ] + } + ] + } + ] + }, + { + "type": "array", + "prefixItems": [ + { + "anyOf": [ + { + "type": "number", + "enum": [ + 0 + ] + }, + { + "type": "number", + "enum": [ + 0.5 + ] + }, + { + "type": "number", + "enum": [ + 1 + ] + }, + { + "type": "number", + "enum": [ + 2 + ] + }, + { + "type": "number", + "enum": [ + 3 + ] + }, + { + "type": "number", + "enum": [ + 4 + ] + }, + { + "type": "number", + "enum": [ + 5 + ] + }, + { + "type": "number", + "enum": [ + 6 + ] + }, + { + "type": "number", + "enum": [ + 7 + ] + }, + { + "type": "number", + "enum": [ + 8 + ] + } + ] + }, + { + "anyOf": [ + { + "type": "number", + "enum": [ + 0 + ] + }, + { + "type": "number", + "enum": [ + 0.5 + ] + }, + { + "type": "number", + "enum": [ + 1 + ] + }, + { + "type": "number", + "enum": [ + 2 + ] + }, + { + "type": "number", + "enum": [ + 3 + ] + }, + { + "type": "number", + "enum": [ + 4 + ] + }, + { + "type": "number", + "enum": [ + 5 + ] + }, + { + "type": "number", + "enum": [ + 6 + ] + }, + { + "type": "number", + "enum": [ + 7 + ] + }, + { + "type": "number", + "enum": [ + 8 + ] + } + ] + } + ] + }, + { + "type": "array", + "prefixItems": [ + { + "anyOf": [ + { + "type": "number", + "enum": [ + 0 + ] + }, + { + "type": "number", + "enum": [ + 0.5 + ] + }, + { + "type": "number", + "enum": [ + 1 + ] + }, + { + "type": "number", + "enum": [ + 2 + ] + }, + { + "type": "number", + "enum": [ + 3 + ] + }, + { + "type": "number", + "enum": [ + 4 + ] + }, + { + "type": "number", + "enum": [ + 5 + ] + }, + { + "type": "number", + "enum": [ + 6 + ] + }, + { + "type": "number", + "enum": [ + 7 + ] + }, + { + "type": "number", + "enum": [ + 8 + ] + } + ] + }, + { + "anyOf": [ + { + "type": "number", + "enum": [ + 0 + ] + }, + { + "type": "number", + "enum": [ + 0.5 + ] + }, + { + "type": "number", + "enum": [ + 1 + ] + }, + { + "type": "number", + "enum": [ + 2 + ] + }, + { + "type": "number", + "enum": [ + 3 + ] + }, + { + "type": "number", + "enum": [ + 4 + ] + }, + { + "type": "number", + "enum": [ + 5 + ] + }, + { + "type": "number", + "enum": [ + 6 + ] + }, + { + "type": "number", + "enum": [ + 7 + ] + }, + { + "type": "number", + "enum": [ + 8 + ] + } + ] + }, + { + "anyOf": [ + { + "type": "number", + "enum": [ + 0 + ] + }, + { + "type": "number", + "enum": [ + 0.5 + ] + }, + { + "type": "number", + "enum": [ + 1 + ] + }, + { + "type": "number", + "enum": [ + 2 + ] + }, + { + "type": "number", + "enum": [ + 3 + ] + }, + { + "type": "number", + "enum": [ + 4 + ] + }, + { + "type": "number", + "enum": [ + 5 + ] + }, + { + "type": "number", + "enum": [ + 6 + ] + }, + { + "type": "number", + "enum": [ + 7 + ] + }, + { + "type": "number", + "enum": [ + 8 + ] + } + ] + } + ] + }, + { + "type": "array", + "prefixItems": [ + { + "anyOf": [ + { + "type": "number", + "enum": [ + 0 + ] + }, + { + "type": "number", + "enum": [ + 0.5 + ] + }, + { + "type": "number", + "enum": [ + 1 + ] + }, + { + "type": "number", + "enum": [ + 2 + ] + }, + { + "type": "number", + "enum": [ + 3 + ] + }, + { + "type": "number", + "enum": [ + 4 + ] + }, + { + "type": "number", + "enum": [ + 5 + ] + }, + { + "type": "number", + "enum": [ + 6 + ] + }, + { + "type": "number", + "enum": [ + 7 + ] + }, + { + "type": "number", + "enum": [ + 8 + ] + } + ] + }, + { + "anyOf": [ + { + "type": "number", + "enum": [ + 0 + ] + }, + { + "type": "number", + "enum": [ + 0.5 + ] + }, + { + "type": "number", + "enum": [ + 1 + ] + }, + { + "type": "number", + "enum": [ + 2 + ] + }, + { + "type": "number", + "enum": [ + 3 + ] + }, + { + "type": "number", + "enum": [ + 4 + ] + }, + { + "type": "number", + "enum": [ + 5 + ] + }, + { + "type": "number", + "enum": [ + 6 + ] + }, + { + "type": "number", + "enum": [ + 7 + ] + }, + { + "type": "number", + "enum": [ + 8 + ] + } + ] + }, + { + "anyOf": [ + { + "type": "number", + "enum": [ + 0 + ] + }, + { + "type": "number", + "enum": [ + 0.5 + ] + }, + { + "type": "number", + "enum": [ + 1 + ] + }, + { + "type": "number", + "enum": [ + 2 + ] + }, + { + "type": "number", + "enum": [ + 3 + ] + }, + { + "type": "number", + "enum": [ + 4 + ] + }, + { + "type": "number", + "enum": [ + 5 + ] + }, + { + "type": "number", + "enum": [ + 6 + ] + }, + { + "type": "number", + "enum": [ + 7 + ] + }, + { + "type": "number", + "enum": [ + 8 + ] + } + ] + }, + { + "anyOf": [ + { + "type": "number", + "enum": [ + 0 + ] + }, + { + "type": "number", + "enum": [ + 0.5 + ] + }, + { + "type": "number", + "enum": [ + 1 + ] + }, + { + "type": "number", + "enum": [ + 2 + ] + }, + { + "type": "number", + "enum": [ + 3 + ] + }, + { + "type": "number", + "enum": [ + 4 + ] + }, + { + "type": "number", + "enum": [ + 5 + ] + }, + { + "type": "number", + "enum": [ + 6 + ] + }, + { + "type": "number", + "enum": [ + 7 + ] + }, + { + "type": "number", + "enum": [ + 8 + ] + } + ] + } + ] + }, + { + "type": "null" + } + ] + }, + "preset": { + "type": "string", + "pattern": "^[a-z0-9-]+$", + "description": "Visual preset for the content item (e.g., \"tile-align\" for outer spacing to align with tile containers)" + }, + "description": { + "type": "string", + "description": "Lightweight supporting text shown beneath the label, e.g. wire-frame instructions." + }, + "label": { + "type": "string", + "description": "Custom heading. Falls back to a type-derived default (e.g. \"Placeholder query\") when unset." + }, + "placeholderType": { + "type": "string", + "enum": [ + "query", + "control", + "filter", + "text" + ], + "description": "The content type this placeholder stands in for. Unset means no type has been picked yet." + }, + "style": { + "type": "object", + "properties": { + "aspectRatio": { + "type": "string" + }, + "fillSpace": { + "type": "boolean" + }, + "height": { + "type": "string" + }, + "maxHeight": { + "type": "string" + }, + "maxWidth": { + "type": "string" + }, + "minHeight": { + "type": "string" + }, + "minWidth": { + "type": "string" + }, + "width": { + "type": "string" + } + } + }, + "type": { + "type": "string", + "enum": [ + "placeholder" + ] + } + }, + "required": [ + "instanceKey", + "type" + ] + }, + { + "type": "object", + "properties": { + "instanceKey": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "required": [ + "instanceKey", + "type" + ], + "additionalProperties": {} + } + ] + }, + { + "type": "object", + "properties": { + "gridPosition": { + "type": "object", + "properties": { + "h": { + "type": "number" + }, + "w": { + "type": "number" + }, + "x": { + "type": "number" + }, + "y": { + "type": "number" + } + }, + "required": [ + "h", + "w", + "x", + "y" + ] + } + }, + "required": [ + "gridPosition" + ] + } + ] + } + ] + } + }, + "containerType": { + "type": "string", + "enum": [ + "grid" + ] + }, + "gridPosition": { + "type": "object", + "properties": { + "h": { + "type": "integer", + "minimum": 1, + "description": "Height in grid units (default: 36 for charts)" + }, + "w": { + "type": "integer", + "minimum": 1, + "description": "Width in grid columns on a 24-column grid. Common widths: 24 (full), 12 (half), 8 (third), 6 (quarter). x + w must not exceed 24." + }, + "x": { + "type": "integer", + "minimum": 0, + "description": "X position on a 24-column grid (0=left edge, 12=middle). Items side-by-side share the same y with complementary x values." + }, + "y": { + "type": "integer", + "minimum": 0, + "description": "Y position in grid units (0=top, higher values=lower on page)" + } + }, + "required": [ + "h", + "w", + "x", + "y" + ] + }, + "metadata": { + "type": "object", + "properties": { + "attachedQueryKey": { + "type": "string", + "description": "Set by the auto-add-tile flow when this container was generated for a specific workbook tab. The server removes containers with a matching `attachedQueryKey` when that tab is deleted. The reducer clears this when the user adds unrelated content (a different query, filter, text tile, page switcher, or sub-container)." + }, + "generatedHeading": { + "type": "boolean", + "description": "Marks the auto-injected heading wrapper (title + description row) created for a tile, so it can be labeled generically and treated as managed." + }, + "locked": { + "type": "boolean", + "description": "Locks the container's internal arrangement so its children cannot be dragged, reordered, resized, or have new items dropped in. Cascades to all descendants. Does not lock the container's own position/size." + } + }, + "description": "Optional bookkeeping for this container (e.g. `attachedQueryKey` for auto-placed tiles)" + }, + "padding": { + "anyOf": [ + { + "type": "number", + "enum": [ + 0 + ] + }, + { + "type": "number", + "enum": [ + 0.5 + ] + }, + { + "type": "number", + "enum": [ + 1 + ] + }, + { + "type": "number", + "enum": [ + 2 + ] + }, + { + "type": "number", + "enum": [ + 3 + ] + }, + { + "type": "number", + "enum": [ + 4 + ] + }, + { + "type": "number", + "enum": [ + 5 + ] + }, + { + "type": "number", + "enum": [ + 6 + ] + }, + { + "type": "number", + "enum": [ + 7 + ] + }, + { + "type": "number", + "enum": [ + 8 + ] + }, + { + "type": "array", + "prefixItems": [ + { + "anyOf": [ + { + "type": "number", + "enum": [ + 0 + ] + }, + { + "type": "number", + "enum": [ + 0.5 + ] + }, + { + "type": "number", + "enum": [ + 1 + ] + }, + { + "type": "number", + "enum": [ + 2 + ] + }, + { + "type": "number", + "enum": [ + 3 + ] + }, + { + "type": "number", + "enum": [ + 4 + ] + }, + { + "type": "number", + "enum": [ + 5 + ] + }, + { + "type": "number", + "enum": [ + 6 + ] + }, + { + "type": "number", + "enum": [ + 7 + ] + }, + { + "type": "number", + "enum": [ + 8 + ] + } + ] + } + ] + }, + { + "type": "array", + "prefixItems": [ + { + "anyOf": [ + { + "type": "number", + "enum": [ + 0 + ] + }, + { + "type": "number", + "enum": [ + 0.5 + ] + }, + { + "type": "number", + "enum": [ + 1 + ] + }, + { + "type": "number", + "enum": [ + 2 + ] + }, + { + "type": "number", + "enum": [ + 3 + ] + }, + { + "type": "number", + "enum": [ + 4 + ] + }, + { + "type": "number", + "enum": [ + 5 + ] + }, + { + "type": "number", + "enum": [ + 6 + ] + }, + { + "type": "number", + "enum": [ + 7 + ] + }, + { + "type": "number", + "enum": [ + 8 + ] + } + ] + }, + { + "anyOf": [ + { + "type": "number", + "enum": [ + 0 + ] + }, + { + "type": "number", + "enum": [ + 0.5 + ] + }, + { + "type": "number", + "enum": [ + 1 + ] + }, + { + "type": "number", + "enum": [ + 2 + ] + }, + { + "type": "number", + "enum": [ + 3 + ] + }, + { + "type": "number", + "enum": [ + 4 + ] + }, + { + "type": "number", + "enum": [ + 5 + ] + }, + { + "type": "number", + "enum": [ + 6 + ] + }, + { + "type": "number", + "enum": [ + 7 + ] + }, + { + "type": "number", + "enum": [ + 8 + ] + } + ] + } + ] + }, + { + "type": "array", + "prefixItems": [ + { + "anyOf": [ + { + "type": "number", + "enum": [ + 0 + ] + }, + { + "type": "number", + "enum": [ + 0.5 + ] + }, + { + "type": "number", + "enum": [ + 1 + ] + }, + { + "type": "number", + "enum": [ + 2 + ] + }, + { "type": "number", "enum": [ 3 @@ -11942,161 +12881,974 @@ 8 ] } - ] + ] + }, + { + "anyOf": [ + { + "type": "number", + "enum": [ + 0 + ] + }, + { + "type": "number", + "enum": [ + 0.5 + ] + }, + { + "type": "number", + "enum": [ + 1 + ] + }, + { + "type": "number", + "enum": [ + 2 + ] + }, + { + "type": "number", + "enum": [ + 3 + ] + }, + { + "type": "number", + "enum": [ + 4 + ] + }, + { + "type": "number", + "enum": [ + 5 + ] + }, + { + "type": "number", + "enum": [ + 6 + ] + }, + { + "type": "number", + "enum": [ + 7 + ] + }, + { + "type": "number", + "enum": [ + 8 + ] + } + ] + } + ] + } + ] + }, + "style": { + "type": "string", + "pattern": "^[a-z0-9-]+$" + } + }, + "required": [ + "instanceKey", + "children", + "containerType" + ], + "description": "Grid container — children are positioned on a grid (each carries a gridPosition)." + }, + "StackContainer": { + "type": "object", + "properties": { + "description": { + "type": "string", + "description": "Optional description for the container, providing additional context or information" + }, + "instanceKey": { + "type": "string", + "description": "Unique identifier for this container. Used to reference the container when adding, moving, or removing children." + }, + "name": { + "type": "string", + "description": "Human-readable name for the container, used for easier reference in logic and design" + }, + "aspectRatio": { + "type": "string" + }, + "fillSpace": { + "type": "boolean" + }, + "height": { + "type": "string" + }, + "maxHeight": { + "type": "string" + }, + "maxWidth": { + "type": "string" + }, + "minHeight": { + "type": "string" + }, + "minWidth": { + "type": "string" + }, + "width": { + "type": "string" + }, + "after": { + "anyOf": [ + { + "$ref": "#/components/schemas/StackContainer" + }, + { + "$ref": "#/components/schemas/ReferenceContainer" + } + ] + }, + "align": { + "type": "string", + "enum": [ + "flex-start", + "flex-end", + "center", + "stretch" + ], + "description": "Cross-axis alignment of children (e.g., center, stretch)" + }, + "before": { + "anyOf": [ + { + "$ref": "#/components/schemas/StackContainer" + }, + { + "$ref": "#/components/schemas/ReferenceContainer" + } + ] + }, + "children": { + "type": "array", + "items": { + "anyOf": [ + { + "type": "object", + "properties": { + "instanceKey": { + "type": "string", + "description": "Unique identifier for this specific placement of the content item. Use this key (not the query id) when repositioning or removing items." + }, + "padding": { + "anyOf": [ + { + "type": "number", + "enum": [ + 0 + ] + }, + { + "type": "number", + "enum": [ + 0.5 + ] + }, + { + "type": "number", + "enum": [ + 1 + ] + }, + { + "type": "number", + "enum": [ + 2 + ] + }, + { + "type": "number", + "enum": [ + 3 + ] + }, + { + "type": "number", + "enum": [ + 4 + ] + }, + { + "type": "number", + "enum": [ + 5 + ] + }, + { + "type": "number", + "enum": [ + 6 + ] + }, + { + "type": "number", + "enum": [ + 7 + ] + }, + { + "type": "number", + "enum": [ + 8 + ] + }, + { + "type": "array", + "prefixItems": [ + { + "anyOf": [ + { + "type": "number", + "enum": [ + 0 + ] + }, + { + "type": "number", + "enum": [ + 0.5 + ] + }, + { + "type": "number", + "enum": [ + 1 + ] + }, + { + "type": "number", + "enum": [ + 2 + ] + }, + { + "type": "number", + "enum": [ + 3 + ] + }, + { + "type": "number", + "enum": [ + 4 + ] + }, + { + "type": "number", + "enum": [ + 5 + ] + }, + { + "type": "number", + "enum": [ + 6 + ] + }, + { + "type": "number", + "enum": [ + 7 + ] + }, + { + "type": "number", + "enum": [ + 8 + ] + } + ] + } + ] + }, + { + "type": "array", + "prefixItems": [ + { + "anyOf": [ + { + "type": "number", + "enum": [ + 0 + ] + }, + { + "type": "number", + "enum": [ + 0.5 + ] + }, + { + "type": "number", + "enum": [ + 1 + ] + }, + { + "type": "number", + "enum": [ + 2 + ] + }, + { + "type": "number", + "enum": [ + 3 + ] + }, + { + "type": "number", + "enum": [ + 4 + ] + }, + { + "type": "number", + "enum": [ + 5 + ] + }, + { + "type": "number", + "enum": [ + 6 + ] + }, + { + "type": "number", + "enum": [ + 7 + ] + }, + { + "type": "number", + "enum": [ + 8 + ] + } + ] + }, + { + "anyOf": [ + { + "type": "number", + "enum": [ + 0 + ] + }, + { + "type": "number", + "enum": [ + 0.5 + ] + }, + { + "type": "number", + "enum": [ + 1 + ] + }, + { + "type": "number", + "enum": [ + 2 + ] + }, + { + "type": "number", + "enum": [ + 3 + ] + }, + { + "type": "number", + "enum": [ + 4 + ] + }, + { + "type": "number", + "enum": [ + 5 + ] + }, + { + "type": "number", + "enum": [ + 6 + ] + }, + { + "type": "number", + "enum": [ + 7 + ] + }, + { + "type": "number", + "enum": [ + 8 + ] + } + ] + } + ] + }, + { + "type": "array", + "prefixItems": [ + { + "anyOf": [ + { + "type": "number", + "enum": [ + 0 + ] + }, + { + "type": "number", + "enum": [ + 0.5 + ] + }, + { + "type": "number", + "enum": [ + 1 + ] + }, + { + "type": "number", + "enum": [ + 2 + ] + }, + { + "type": "number", + "enum": [ + 3 + ] + }, + { + "type": "number", + "enum": [ + 4 + ] + }, + { + "type": "number", + "enum": [ + 5 + ] + }, + { + "type": "number", + "enum": [ + 6 + ] + }, + { + "type": "number", + "enum": [ + 7 + ] + }, + { + "type": "number", + "enum": [ + 8 + ] + } + ] + }, + { + "anyOf": [ + { + "type": "number", + "enum": [ + 0 + ] + }, + { + "type": "number", + "enum": [ + 0.5 + ] + }, + { + "type": "number", + "enum": [ + 1 + ] + }, + { + "type": "number", + "enum": [ + 2 + ] + }, + { + "type": "number", + "enum": [ + 3 + ] + }, + { + "type": "number", + "enum": [ + 4 + ] + }, + { + "type": "number", + "enum": [ + 5 + ] + }, + { + "type": "number", + "enum": [ + 6 + ] + }, + { + "type": "number", + "enum": [ + 7 + ] + }, + { + "type": "number", + "enum": [ + 8 + ] + } + ] + }, + { + "anyOf": [ + { + "type": "number", + "enum": [ + 0 + ] + }, + { + "type": "number", + "enum": [ + 0.5 + ] + }, + { + "type": "number", + "enum": [ + 1 + ] + }, + { + "type": "number", + "enum": [ + 2 + ] + }, + { + "type": "number", + "enum": [ + 3 + ] + }, + { + "type": "number", + "enum": [ + 4 + ] + }, + { + "type": "number", + "enum": [ + 5 + ] + }, + { + "type": "number", + "enum": [ + 6 + ] + }, + { + "type": "number", + "enum": [ + 7 + ] + }, + { + "type": "number", + "enum": [ + 8 + ] + } + ] + } + ] + }, + { + "type": "array", + "prefixItems": [ + { + "anyOf": [ + { + "type": "number", + "enum": [ + 0 + ] + }, + { + "type": "number", + "enum": [ + 0.5 + ] + }, + { + "type": "number", + "enum": [ + 1 + ] + }, + { + "type": "number", + "enum": [ + 2 + ] + }, + { + "type": "number", + "enum": [ + 3 + ] + }, + { + "type": "number", + "enum": [ + 4 + ] + }, + { + "type": "number", + "enum": [ + 5 + ] + }, + { + "type": "number", + "enum": [ + 6 + ] + }, + { + "type": "number", + "enum": [ + 7 + ] + }, + { + "type": "number", + "enum": [ + 8 + ] + } + ] + }, + { + "anyOf": [ + { + "type": "number", + "enum": [ + 0 + ] + }, + { + "type": "number", + "enum": [ + 0.5 + ] + }, + { + "type": "number", + "enum": [ + 1 + ] + }, + { + "type": "number", + "enum": [ + 2 + ] + }, + { + "type": "number", + "enum": [ + 3 + ] + }, + { + "type": "number", + "enum": [ + 4 + ] + }, + { + "type": "number", + "enum": [ + 5 + ] + }, + { + "type": "number", + "enum": [ + 6 + ] + }, + { + "type": "number", + "enum": [ + 7 + ] + }, + { + "type": "number", + "enum": [ + 8 + ] + } + ] + }, + { + "anyOf": [ + { + "type": "number", + "enum": [ + 0 + ] + }, + { + "type": "number", + "enum": [ + 0.5 + ] + }, + { + "type": "number", + "enum": [ + 1 + ] + }, + { + "type": "number", + "enum": [ + 2 + ] + }, + { + "type": "number", + "enum": [ + 3 + ] + }, + { + "type": "number", + "enum": [ + 4 + ] + }, + { + "type": "number", + "enum": [ + 5 + ] + }, + { + "type": "number", + "enum": [ + 6 + ] + }, + { + "type": "number", + "enum": [ + 7 + ] + }, + { + "type": "number", + "enum": [ + 8 + ] + } + ] + }, + { + "anyOf": [ + { + "type": "number", + "enum": [ + 0 + ] + }, + { + "type": "number", + "enum": [ + 0.5 + ] + }, + { + "type": "number", + "enum": [ + 1 + ] + }, + { + "type": "number", + "enum": [ + 2 + ] + }, + { + "type": "number", + "enum": [ + 3 + ] + }, + { + "type": "number", + "enum": [ + 4 + ] + }, + { + "type": "number", + "enum": [ + 5 + ] + }, + { + "type": "number", + "enum": [ + 6 + ] + }, + { + "type": "number", + "enum": [ + 7 + ] + }, + { + "type": "number", + "enum": [ + 8 + ] + } + ] + } + ] + }, + { + "type": "null" + } + ] + }, + "preset": { + "type": "string", + "pattern": "^[a-z0-9-]+$", + "description": "Visual preset for the content item (e.g., \"tile-align\" for outer spacing to align with tile containers)" + }, + "as": { + "type": "string", + "enum": [ + "chart", + "result", + "ai", + "metadata" + ], + "description": "Render mode: \"chart\" for visualization, \"result\" for data table, \"ai\" for AI summary, \"metadata\" for query metadata" + }, + "detachedContent": { + "type": "string", + "description": "Set when a metadata field is detached: local text rendered instead of the query value" + }, + "format": { + "type": "string", + "enum": [ + "subtitle", + "description", + "name" + ], + "description": "Display format when as is \"ai\" or \"metadata\": \"name\" (metadata only), \"subtitle\", or \"description\"" + }, + "id": { + "type": "string", + "pattern": "^[1-9][0-9]*$", + "description": "The query presentation ID this content item references" + }, + "name": { + "type": "string", + "description": "Display name for this query item" + }, + "style": { + "type": "object", + "properties": { + "aspectRatio": { + "type": "string" + }, + "fillSpace": { + "type": "boolean" + }, + "height": { + "type": "string" + }, + "maxHeight": { + "type": "string" + }, + "maxWidth": { + "type": "string" + }, + "minHeight": { + "type": "string" + }, + "minWidth": { + "type": "string" + }, + "width": { + "type": "string" + } + } + }, + "type": { + "type": "string", + "enum": [ + "query" + ] + } }, - { - "anyOf": [ - { - "type": "number", - "enum": [ - 0 - ] - }, - { - "type": "number", - "enum": [ - 0.5 - ] - }, - { - "type": "number", - "enum": [ - 1 - ] - }, - { - "type": "number", - "enum": [ - 2 - ] - }, - { - "type": "number", - "enum": [ - 3 - ] - }, - { - "type": "number", - "enum": [ - 4 - ] - }, - { - "type": "number", - "enum": [ - 5 - ] - }, - { - "type": "number", - "enum": [ - 6 - ] - }, - { - "type": "number", - "enum": [ - 7 - ] - }, - { - "type": "number", - "enum": [ - 8 - ] - } - ] - } - ] - } - ] - }, - "style": { - "type": "string", - "pattern": "^[a-z0-9-]+$" - } - }, - "required": [ - "instanceKey", - "children", - "containerType" - ], - "description": "Grid container — children are positioned on a grid (each carries a gridPosition)." - }, - "StackContainer": { - "type": "object", - "properties": { - "description": { - "type": "string", - "description": "Optional description for the container, providing additional context or information" - }, - "instanceKey": { - "type": "string", - "description": "Unique identifier for this container. Used to reference the container when adding, moving, or removing children." - }, - "name": { - "type": "string", - "description": "Human-readable name for the container, used for easier reference in logic and design" - }, - "aspectRatio": { - "type": "string" - }, - "fillSpace": { - "type": "boolean" - }, - "height": { - "type": "string" - }, - "maxHeight": { - "type": "string" - }, - "maxWidth": { - "type": "string" - }, - "minHeight": { - "type": "string" - }, - "minWidth": { - "type": "string" - }, - "width": { - "type": "string" - }, - "after": { - "anyOf": [ - { - "$ref": "#/components/schemas/StackContainer" - }, - { - "$ref": "#/components/schemas/ReferenceContainer" - } - ] - }, - "align": { - "type": "string", - "enum": [ - "flex-start", - "flex-end", - "center", - "stretch" - ], - "description": "Cross-axis alignment of children (e.g., center, stretch)" - }, - "before": { - "anyOf": [ - { - "$ref": "#/components/schemas/StackContainer" - }, - { - "$ref": "#/components/schemas/ReferenceContainer" - } - ] - }, - "children": { - "type": "array", - "items": { - "anyOf": [ + "required": [ + "instanceKey", + "id", + "type" + ] + }, { "type": "object", "properties": { @@ -12836,33 +14588,46 @@ "pattern": "^[a-z0-9-]+$", "description": "Visual preset for the content item (e.g., \"tile-align\" for outer spacing to align with tile containers)" }, - "as": { - "type": "string", - "enum": [ - "chart", - "result", - "ai", - "metadata" - ], - "description": "Render mode: \"chart\" for visualization, \"result\" for data table, \"ai\" for AI summary, \"metadata\" for query metadata" - }, - "format": { - "type": "string", - "enum": [ - "subtitle", - "description", - "name" + "appearance": { + "oneOf": [ + { + "type": "object", + "properties": { + "as": { + "type": "string", + "enum": [ + "inline" + ] + } + }, + "required": [ + "as" + ] + }, + { + "type": "object", + "properties": { + "as": { + "type": "string", + "enum": [ + "tooltip" + ] + } + }, + "required": [ + "as" + ] + } ], - "description": "Display format when as is \"ai\" or \"metadata\": \"name\" (metadata only), \"subtitle\", or \"description\"" + "description": "Display mode: \"inline\" renders directly, \"tooltip\" shows on hover" }, - "id": { + "content": { "type": "string", - "pattern": "^[1-9][0-9]*$", - "description": "The query presentation ID this content item references" + "description": "The text content to display (supports markdown)" }, "name": { "type": "string", - "description": "Display name for this query item" + "description": "Display name for this text item (e.g., title, subtitle)" }, "style": { "type": "object", @@ -12893,16 +14658,25 @@ } } }, + "textAlign": { + "type": "string", + "enum": [ + "start", + "center", + "end" + ], + "description": "Text alignment: \"start\", \"center\", or \"end\"" + }, "type": { "type": "string", "enum": [ - "query" + "inline-text" ] } }, "required": [ "instanceKey", - "id", + "content", "type" ] }, @@ -13653,7 +15427,14 @@ "as": { "type": "string", "enum": [ - "inline" + "tabs" + ] + }, + "variant": { + "type": "string", + "enum": [ + "underline", + "bordered" ] } }, @@ -13667,24 +15448,88 @@ "as": { "type": "string", "enum": [ - "tooltip" + "buttons" + ] + }, + "variant": { + "type": "string", + "enum": [ + "segment", + "toggle", + "pills" + ] + } + }, + "required": [ + "as" + ] + }, + { + "type": "object", + "properties": { + "as": { + "type": "string", + "enum": [ + "list" + ] + }, + "description": { + "type": "boolean" + } + }, + "required": [ + "as" + ] + }, + { + "type": "object", + "properties": { + "as": { + "type": "string", + "enum": [ + "dropdown" ] + }, + "description": { + "type": "boolean" } }, "required": [ "as" ] } - ], - "description": "Display mode: \"inline\" renders directly, \"tooltip\" shows on hover" - }, - "content": { - "type": "string", - "description": "The text content to display (supports markdown)" + ] }, - "name": { - "type": "string", - "description": "Display name for this text item (e.g., title, subtitle)" + "options": { + "type": "array", + "items": { + "type": "object", + "properties": { + "disabled": { + "type": "boolean" + }, + "id": { + "type": "string" + }, + "includeControls": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "target": { + "type": "string" + }, + "uri": { + "type": "string" + }, + "value": { + "type": "string", + "description": "Page link target. Must exactly equal an existing page container’s instanceKey — not its name, label, or a slug. A value matching no page redirects to the main dashboard view with a \"Page not found\" message. Ignored when `uri` is set." + } + } + }, + "description": "Omit to auto-derive one tab per page, kept in sync as pages are added, removed, renamed, or reordered. Set to curate, reorder, or add custom-URL tabs; each option’s `value` must then match a page instanceKey." }, "style": { "type": "object", @@ -13715,25 +15560,15 @@ } } }, - "textAlign": { - "type": "string", - "enum": [ - "start", - "center", - "end" - ], - "description": "Text alignment: \"start\", \"center\", or \"end\"" - }, "type": { "type": "string", "enum": [ - "inline-text" + "inline-page-switcher" ] } }, "required": [ "instanceKey", - "content", "type" ] }, @@ -14476,115 +16311,10 @@ "pattern": "^[a-z0-9-]+$", "description": "Visual preset for the content item (e.g., \"tile-align\" for outer spacing to align with tile containers)" }, - "appearance": { - "oneOf": [ - { - "type": "object", - "properties": { - "as": { - "type": "string", - "enum": [ - "tabs" - ] - }, - "variant": { - "type": "string", - "enum": [ - "underline", - "bordered" - ] - } - }, - "required": [ - "as" - ] - }, - { - "type": "object", - "properties": { - "as": { - "type": "string", - "enum": [ - "buttons" - ] - }, - "variant": { - "type": "string", - "enum": [ - "segment", - "toggle", - "pills" - ] - } - }, - "required": [ - "as" - ] - }, - { - "type": "object", - "properties": { - "as": { - "type": "string", - "enum": [ - "list" - ] - }, - "description": { - "type": "boolean" - } - }, - "required": [ - "as" - ] - }, - { - "type": "object", - "properties": { - "as": { - "type": "string", - "enum": [ - "dropdown" - ] - }, - "description": { - "type": "boolean" - } - }, - "required": [ - "as" - ] - } - ] - }, - "options": { - "type": "array", - "items": { - "type": "object", - "properties": { - "disabled": { - "type": "boolean" - }, - "id": { - "type": "string" - }, - "includeControls": { - "type": "boolean" - }, - "label": { - "type": "string" - }, - "target": { - "type": "string" - }, - "uri": { - "type": "string" - }, - "value": { - "type": "string" - } - } - } + "id": { + "type": "string", + "format": "uuid", + "description": "UUID of the rich text content block" }, "style": { "type": "object", @@ -14618,12 +16348,13 @@ "type": { "type": "string", "enum": [ - "inline-page-switcher" + "text" ] } }, "required": [ "instanceKey", + "id", "type" ] }, @@ -15367,9 +17098,13 @@ "description": "Visual preset for the content item (e.g., \"tile-align\" for outer spacing to align with tile containers)" }, "id": { + "type": "string" + }, + "type": { "type": "string", - "format": "uuid", - "description": "UUID of the rich text content block" + "enum": [ + "control" + ] }, "style": { "type": "object", @@ -15399,12 +17134,6 @@ "type": "string" } } - }, - "type": { - "type": "string", - "enum": [ - "text" - ] } }, "required": [ @@ -16158,9 +17887,51 @@ "type": { "type": "string", "enum": [ - "control" + "filter" ] }, + "appearance": { + "type": "object", + "properties": { + "control": { + "type": "string", + "enum": [ + "buttonToggle", + "dropdown" + ] + }, + "display": { + "type": "string", + "enum": [ + "inline", + "popover" + ] + }, + "options": { + "type": "array", + "items": { + "type": "object", + "properties": { + "label": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "required": [ + "value" + ] + } + }, + "value": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, "style": { "type": "object", "properties": { @@ -16936,56 +18707,11 @@ "pattern": "^[a-z0-9-]+$", "description": "Visual preset for the content item (e.g., \"tile-align\" for outer spacing to align with tile containers)" }, - "id": { - "type": "string" - }, - "type": { - "type": "string", - "enum": [ - "filter" - ] - }, - "appearance": { - "type": "object", - "properties": { - "control": { - "type": "string", - "enum": [ - "buttonToggle", - "dropdown" - ] - }, - "display": { - "type": "string", - "enum": [ - "inline", - "popover" - ] - }, - "options": { - "type": "array", - "items": { - "type": "object", - "properties": { - "label": { - "type": "string" - }, - "value": { - "type": "string" - } - }, - "required": [ - "value" - ] - } - }, - "value": { - "type": "array", - "items": { - "type": "string" - } - } - } + "size": { + "type": "number", + "minimum": 0, + "maximum": 2000, + "description": "Fixed size in px along the parent stack axis (default 16). In grids the size comes from gridPosition; ignored when style.fillSpace is true." }, "style": { "type": "object", @@ -17015,11 +18741,16 @@ "type": "string" } } + }, + "type": { + "type": "string", + "enum": [ + "inline-spacer" + ] } }, "required": [ "instanceKey", - "id", "type" ] }, @@ -17762,11 +19493,32 @@ "pattern": "^[a-z0-9-]+$", "description": "Visual preset for the content item (e.g., \"tile-align\" for outer spacing to align with tile containers)" }, - "size": { - "type": "number", - "minimum": 0, - "maximum": 2000, - "description": "Fixed size in px along the parent stack axis (default 16). In grids the size comes from gridPosition; ignored when style.fillSpace is true." + "align": { + "type": "string", + "enum": [ + "start", + "center", + "end" + ], + "description": "Placement of the line within its slot along the cross axis (default center): horizontal → top/center/bottom, vertical → left/center/right" + }, + "color": { + "type": "string", + "enum": [ + "border1", + "border4", + "text1", + "text4" + ], + "description": "Theme color for the line, subtle → bold (default border4)" + }, + "direction": { + "type": "string", + "enum": [ + "horizontal", + "vertical" + ], + "description": "Line orientation (default horizontal)" }, "style": { "type": "object", @@ -17797,10 +19549,33 @@ } } }, + "thickness": { + "anyOf": [ + { + "type": "number", + "enum": [ + 1 + ] + }, + { + "type": "number", + "enum": [ + 2 + ] + }, + { + "type": "number", + "enum": [ + 4 + ] + } + ], + "description": "Line thickness in px (default 1)" + }, "type": { "type": "string", "enum": [ - "inline-spacer" + "inline-divider" ] } }, @@ -18548,32 +20323,23 @@ "pattern": "^[a-z0-9-]+$", "description": "Visual preset for the content item (e.g., \"tile-align\" for outer spacing to align with tile containers)" }, - "align": { + "description": { "type": "string", - "enum": [ - "start", - "center", - "end" - ], - "description": "Placement of the line within its slot along the cross axis (default center): horizontal → top/center/bottom, vertical → left/center/right" + "description": "Lightweight supporting text shown beneath the label, e.g. wire-frame instructions." }, - "color": { + "label": { "type": "string", - "enum": [ - "border1", - "border4", - "text1", - "text4" - ], - "description": "Theme color for the line, subtle → bold (default border4)" + "description": "Custom heading. Falls back to a type-derived default (e.g. \"Placeholder query\") when unset." }, - "direction": { + "placeholderType": { "type": "string", "enum": [ - "horizontal", - "vertical" + "query", + "control", + "filter", + "text" ], - "description": "Line orientation (default horizontal)" + "description": "The content type this placeholder stands in for. Unset means no type has been picked yet." }, "style": { "type": "object", @@ -18604,33 +20370,10 @@ } } }, - "thickness": { - "anyOf": [ - { - "type": "number", - "enum": [ - 1 - ] - }, - { - "type": "number", - "enum": [ - 2 - ] - }, - { - "type": "number", - "enum": [ - 4 - ] - } - ], - "description": "Line thickness in px (default 1)" - }, "type": { "type": "string", "enum": [ - "inline-divider" + "placeholder" ] } }, @@ -23594,6 +25337,7 @@ "summaryValue", "svgMap", "table", + "treemap", null ], "description": "High-level chart type (e.g. \"bar\", \"line\", \"area\")." @@ -23612,6 +25356,12 @@ "visConfig": { "type": "object", "properties": { + "config": { + "type": "object", + "properties": {}, + "additionalProperties": {}, + "description": "The vis-type-specific spec — KPI rows, chart mark/series, etc. GET nests the spec here; PATCH also accepts it spread flat next to visType for backward compatibility." + }, "visType": { "type": [ "string", @@ -23628,6 +25378,7 @@ "sankey", "single-record", "svg-map", + "treemap", "omni-spreadsheet", "spreadsheet-tab", "summary-value", @@ -27666,6 +29417,7 @@ "summaryValue", "svgMap", "table", + "treemap", null ], "description": "High-level chart type (e.g. \"bar\", \"line\", \"area\")." @@ -27684,6 +29436,12 @@ "visConfig": { "type": "object", "properties": { + "config": { + "type": "object", + "properties": {}, + "additionalProperties": {}, + "description": "The vis-type-specific spec — KPI rows, chart mark/series, etc. GET nests the spec here; PATCH also accepts it spread flat next to visType for backward compatibility." + }, "visType": { "type": [ "string", @@ -27700,6 +29458,7 @@ "sankey", "single-record", "svg-map", + "treemap", "omni-spreadsheet", "spreadsheet-tab", "summary-value", @@ -28743,6 +30502,14 @@ "agentic_job": { "$ref": "#/components/schemas/EvalRunResultAgenticJob" }, + "ai_timing_ms": { + "type": [ + "integer", + "null" + ], + "description": "Strict main-agent LLM processing time in milliseconds — the measured model-call duration, excluding tool execution and subagent model calls (those count toward `tool_timing_ms`). Shown as \"AI time\" in the UI. Runs recorded before this was measured fall back to an approximation (`timing_ms` minus tool latency).", + "example": 4121 + }, "cost": { "type": [ "number", @@ -28815,12 +30582,21 @@ "integer", "null" ], - "description": "Total AI time in milliseconds — all LLM processing and tool calls. Shown as \"AI time\" in the UI.", + "description": "Total `/generate` wall-time in milliseconds — LLM processing plus inner-loop tool execution. `ai_timing_ms` and `tool_timing_ms` split this; warehouse query time is separate (`query_timing_ms`).", "example": 4321 + }, + "tool_timing_ms": { + "type": [ + "integer", + "null" + ], + "description": "Inner-loop tool latency in milliseconds — time spent running tools the model invoked (model and field-value lookups, query planning), excluding the warehouse query itself (`query_timing_ms`). Null for runs recorded before per-tool latency was tracked.", + "example": 200 } }, "required": [ "agentic_job", + "ai_timing_ms", "cost", "error_reason", "expectation", @@ -28830,7 +30606,8 @@ "query_timing_ms", "score", "scoring_cost", - "timing_ms" + "timing_ms", + "tool_timing_ms" ] }, "EvalRunResultAgenticJob": { @@ -31679,6 +33456,10 @@ "type": "integer", "description": "Number of documents modified" }, + "replaced_input_column_keys_count": { + "type": "integer", + "description": "Number of input columns whose key references were replaced" + }, "replaced_queries_count": { "type": "integer", "description": "Number of queries replaced" @@ -31695,6 +33476,7 @@ "required": [ "replaced_dashboard_filters_count", "replaced_documents_count", + "replaced_input_column_keys_count", "replaced_queries_count", "replaced_workbook_models_count", "skipped_pr_required_count" @@ -34796,6 +36578,16 @@ } } }, + "403": { + "description": "Insufficient permissions. AI query generation must be enabled for the organization and the caller must have permission to use AI on the job's model.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError403" + } + } + } + }, "404": { "description": "Job not found. The job may not exist or may belong to a different organization.", "content": { @@ -34948,6 +36740,16 @@ } } }, + "403": { + "description": "Insufficient permissions. AI query generation must be enabled for the organization and the caller must have permission to use AI on the job's model.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError403" + } + } + } + }, "404": { "description": "Job not found, not in COMPLETE state, or result is no longer available (results are retained for 14 days).", "content": { @@ -35015,6 +36817,16 @@ } } }, + "403": { + "description": "Insufficient permissions. AI query generation must be enabled for the organization and the caller must have permission to use AI on the job's model.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError403" + } + } + } + }, "404": { "description": "Job not found, not in COMPLETE state, or the apiAiVis feature flag is not enabled.", "content": { @@ -35451,7 +37263,7 @@ } }, "post": { - "description": "Create a routine that runs a saved prompt on a schedule and delivers the AI response through a single email destination. Each scheduled run executes once using the routine owner's permissions, and every recipient receives the same result. Organization API keys can pass `?userId=` to create the routine for a specific organization member.", + "description": "Create a routine that runs a saved prompt on a schedule and delivers the AI response through a single destination — email (one or more recipients / user groups) or Slack (a single channel or direct message). Each scheduled run executes once using the routine owner's permissions, and every recipient receives the same result. Organization API keys can pass `?userId=` to create the routine for a specific organization member.", "operationId": "routineCreate", "summary": "Create a routine", "tags": [ @@ -36254,6 +38066,14 @@ "items": { "type": "object", "properties": { + "allowBranchConnectionEnvironments": { + "type": [ + "boolean", + "null" + ], + "description": "Whether a branch may select its own connection environment. When user-attribute environment selection is also enabled, a branch selection overrides the user attribute.", + "example": false + }, "baseRole": { "type": [ "string", @@ -36267,7 +38087,8 @@ "boolean", "null" ], - "description": "Whether branch environments override user attributes", + "deprecated": true, + "description": "Deprecated alias for `allowBranchConnectionEnvironments`; same value. Use `allowBranchConnectionEnvironments` instead.", "example": false }, "createdAt": { @@ -36369,6 +38190,7 @@ } }, "required": [ + "allowBranchConnectionEnvironments", "baseRole", "branchConnectionEnvironmentOverridesUserAttr", "createdAt", @@ -36734,6 +38556,14 @@ "connection": { "type": "object", "properties": { + "allowBranchConnectionEnvironments": { + "type": [ + "boolean", + "null" + ], + "description": "Whether a branch may select its own connection environment. When user-attribute environment selection is also enabled, a branch selection overrides the user attribute.", + "example": false + }, "baseRole": { "type": [ "string", @@ -36747,7 +38577,8 @@ "boolean", "null" ], - "description": "Whether branch environments override user attributes", + "deprecated": true, + "description": "Deprecated alias for `allowBranchConnectionEnvironments`; same value. Use `allowBranchConnectionEnvironments` instead.", "example": false }, "createdAt": { @@ -36849,6 +38680,7 @@ } }, "required": [ + "allowBranchConnectionEnvironments", "baseRole", "branchConnectionEnvironmentOverridesUserAttr", "createdAt", @@ -40154,6 +41986,65 @@ } } }, + "/api/v1/documents/{identifier}/upgrade": { + "post": { + "description": "Upgrades a document to the advanced dashboard layout (the \"File > Upgrade layout\" UI action). No-ops when the document already has advanced layout. For published documents the upgrade goes through a draft/publish workflow automatically; if a draft already exists, the request returns 409 unless `clearExistingDraft` is set to `true`.", + "operationId": "documentsUpgradeLayout", + "summary": "Upgrade dashboard layout", + "tags": [ + "Documents" + ], + "parameters": [ + { + "schema": { + "type": "string", + "description": "Document identifier (either document ID or identifier slug)", + "example": "abc123" + }, + "required": true, + "description": "Document identifier (either document ID or identifier slug)", + "name": "identifier", + "in": "path" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DocumentsUpgradeLayoutBody" + } + } + } + }, + "responses": { + "200": { + "description": "Layout upgraded, or no-op if the document already had advanced layout", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DocumentsUpgradeLayoutResponse" + } + } + } + }, + "400": { + "description": "Document does not have a dashboard to upgrade" + }, + "401": { + "description": "Authentication required" + }, + "403": { + "description": "Permission denied" + }, + "404": { + "description": "Document not found" + }, + "409": { + "description": "A draft already exists for the published document; set clearExistingDraft to override" + } + } + } + }, "/api/v1/documents/{identifier}/favorite": { "put": { "operationId": "documentsAddFavorite", diff --git a/cmd/omni/openapi.json b/cmd/omni/openapi.json index 3de471f..e5bdc5d 100644 --- a/cmd/omni/openapi.json +++ b/cmd/omni/openapi.json @@ -1347,6 +1347,11 @@ "description": "Human-readable name describing what this query retrieves.", "example": "Top 5 Products by Revenue" }, + "resultId": { + "type": "string", + "description": "Stable, unique identifier for this query result within the job. Use it to reference a specific result — for example, to correlate or de-duplicate results across responses.", + "example": "928c5838-000d-4943-b305-f6242c1b4922" + }, "status": { "type": "string", "enum": [ @@ -1392,7 +1397,7 @@ "body": { "type": "string", "description": "Body / description copy shown beneath the headline on AI helper landing surfaces.", - "example": "Ask a data question to get started. I can help refine answers, adjust charts, or surface new areas to explore." + "example": "I can help answer data questions, build a Dashboard, or create an App." }, "headline": { "type": "string", @@ -1728,7 +1733,7 @@ "description": "Display-only notes about the routine, or null." }, "destination": { - "$ref": "#/components/schemas/RoutineEmailDestination" + "$ref": "#/components/schemas/RoutineDestinationResponse" }, "disabled": { "type": "boolean", @@ -1749,7 +1754,7 @@ }, "name": { "type": "string", - "description": "Customer-visible name of the routine, used as the email subject." + "description": "Customer-visible name of the routine. Used as the email subject for email destinations, and shown on Slack deliveries." }, "prompt": { "type": "string", @@ -1757,7 +1762,7 @@ }, "recipientCount": { "type": "integer", - "description": "Number of distinct deliverable recipients after expanding user groups and removing duplicates." + "description": "Number of distinct deliverable recipients. For email, user groups are expanded to members and duplicates removed; a Slack routine is always 1 (its single channel or DM)." }, "schedule": { "type": "string", @@ -1810,7 +1815,25 @@ "updatedAt" ] }, - "RoutineEmailDestination": { + "RoutineDestinationResponse": { + "oneOf": [ + { + "$ref": "#/components/schemas/RoutineEmailDestinationResponse" + }, + { + "$ref": "#/components/schemas/RoutineSlackDestination" + } + ], + "discriminator": { + "propertyName": "type", + "mapping": { + "email": "#/components/schemas/RoutineEmailDestinationResponse", + "slack": "#/components/schemas/RoutineSlackDestination" + } + }, + "description": "Delivery configuration for the routine." + }, + "RoutineEmailDestinationResponse": { "type": "object", "properties": { "recipientEmails": { @@ -1819,9 +1842,7 @@ "type": "string", "format": "email" }, - "maxItems": 100, - "default": [], - "description": "Email addresses that receive each scheduled run of the routine.", + "description": "Email addresses configured as direct recipients of each scheduled run, resolved from their current membership.", "example": [ "alice@example.com", "bob@example.com" @@ -1832,7 +1853,7 @@ "enum": [ "email" ], - "description": "Destination type. Only `email` is supported.", + "description": "Selects email delivery — each scheduled run is sent to the listed email recipients and user groups.", "example": "email" }, "userGroupIds": { @@ -1841,8 +1862,6 @@ "type": "string", "format": "uuid" }, - "maxItems": 100, - "default": [], "description": "User group IDs whose active members receive each scheduled run. Omni expands each group to the members' current email addresses when the routine runs.", "example": [ "550e8400-e29b-41d4-a716-446655440000" @@ -1850,10 +1869,45 @@ } }, "required": [ + "recipientEmails", + "type", + "userGroupIds" + ], + "additionalProperties": false + }, + "RoutineSlackDestination": { + "type": "object", + "properties": { + "recipientId": { + "type": "string", + "minLength": 1, + "description": "The Slack channel ID (e.g. \"C01234567\") or user ID (e.g. \"U01234567\") that receives each scheduled run. Exactly one recipient per Slack routine.", + "example": "C01234567" + }, + "slackRecipientType": { + "type": "string", + "enum": [ + "channel", + "users" + ], + "description": "Whether `recipientId` is a Slack channel or a user (delivered as a direct message).", + "example": "channel" + }, + "type": { + "type": "string", + "enum": [ + "slack" + ], + "description": "Selects Slack delivery — each scheduled run is posted to one Slack channel or sent as a direct message to one user.", + "example": "slack" + } + }, + "required": [ + "recipientId", + "slackRecipientType", "type" ], - "additionalProperties": false, - "description": "Email delivery configuration for the routine." + "additionalProperties": false }, "RoutineLastRun": { "type": [ @@ -1944,7 +1998,7 @@ "type": "string", "minLength": 1, "maxLength": 512, - "description": "Customer-visible name of the routine. Used as the email subject for each scheduled run.", + "description": "Customer-visible name of the routine. Used as the email subject for email destinations, and shown on Slack deliveries.", "example": "Weekly user signups" }, "prompt": { @@ -1989,16 +2043,64 @@ "oneOf": [ { "$ref": "#/components/schemas/RoutineEmailDestination" + }, + { + "$ref": "#/components/schemas/RoutineSlackDestination" } ], "discriminator": { "propertyName": "type", "mapping": { - "email": "#/components/schemas/RoutineEmailDestination" + "email": "#/components/schemas/RoutineEmailDestination", + "slack": "#/components/schemas/RoutineSlackDestination" } }, "description": "Single delivery destination for the routine. To send results to multiple destinations, create one routine per destination. Omni runs the prompt once per scheduled run using the routine owner's permissions, and every recipient receives the same result regardless of their own permissions." }, + "RoutineEmailDestination": { + "type": "object", + "properties": { + "recipientEmails": { + "type": "array", + "items": { + "type": "string", + "format": "email" + }, + "maxItems": 100, + "default": [], + "description": "Email addresses that receive each scheduled run of the routine.", + "example": [ + "alice@example.com", + "bob@example.com" + ] + }, + "type": { + "type": "string", + "enum": [ + "email" + ], + "description": "Selects email delivery — each scheduled run is sent to the listed email recipients and user groups.", + "example": "email" + }, + "userGroupIds": { + "type": "array", + "items": { + "type": "string", + "format": "uuid" + }, + "maxItems": 100, + "default": [], + "description": "User group IDs whose active members receive each scheduled run. Omni expands each group to the members' current email addresses when the routine runs.", + "example": [ + "550e8400-e29b-41d4-a716-446655440000" + ] + } + }, + "required": [ + "type" + ], + "additionalProperties": false + }, "RoutineUpdateBody": { "type": "object", "properties": { @@ -2024,7 +2126,7 @@ "type": "string", "minLength": 1, "maxLength": 512, - "description": "New customer-visible name of the routine, used as the email subject." + "description": "New customer-visible name of the routine. Used as the email subject for email destinations, and shown on Slack deliveries." }, "prompt": { "type": "string", @@ -3428,6 +3530,7 @@ "sankey", "single-record", "svg-map", + "treemap", "omni-spreadsheet", "spreadsheet-tab", "summary-value", @@ -3660,6 +3763,7 @@ "summaryValue", "svgMap", "table", + "treemap", null ], "description": "Chart type" @@ -4222,6 +4326,33 @@ "name" ] }, + "DocumentsUpgradeLayoutResponse": { + "type": "object", + "properties": { + "identifier": { + "type": "string", + "description": "Document identifier" + }, + "upgraded": { + "type": "boolean", + "description": "True when the layout was upgraded, false when the document already had advanced layout (no-op)." + } + }, + "required": [ + "identifier", + "upgraded" + ] + }, + "DocumentsUpgradeLayoutBody": { + "type": "object", + "properties": { + "clearExistingDraft": { + "type": "boolean", + "default": false, + "description": "When upgrading a published document, discard any existing draft instead of failing with a conflict." + } + } + }, "DocumentsBulkUpdateLabelsResponse": { "type": "object", "properties": { @@ -5390,6 +5521,10 @@ ], "description": "Render mode: \"chart\" for visualization, \"result\" for data table, \"ai\" for AI summary, \"metadata\" for query metadata" }, + "detachedContent": { + "type": "string", + "description": "Set when a metadata field is detached: local text rendered instead of the query value" + }, "format": { "type": "string", "enum": [ @@ -7125,10 +7260,12 @@ "type": "string" }, "value": { - "type": "string" + "type": "string", + "description": "Page link target. Must exactly equal an existing page container’s instanceKey — not its name, label, or a slug. A value matching no page redirects to the main dashboard view with a \"Page not found\" message. Ignored when `uri` is set." } } - } + }, + "description": "Omit to auto-derive one tab per page, kept in sync as pages are added, removed, renamed, or reordered. Set to curate, reorder, or add custom-URL tabs; each option’s `value` must then match a page instanceKey." }, "style": { "type": "object", @@ -11187,401 +11324,1203 @@ "type": "object", "properties": { "instanceKey": { - "type": "string" - }, - "type": { - "type": "string" - } - }, - "required": [ - "instanceKey", - "type" - ], - "additionalProperties": {} - } - ] - }, - { - "type": "object", - "properties": { - "gridPosition": { - "type": "object", - "properties": { - "h": { - "type": "number" - }, - "w": { - "type": "number" - }, - "x": { - "type": "number" + "type": "string", + "description": "Unique identifier for this specific placement of the content item. Use this key (not the query id) when repositioning or removing items." }, - "y": { - "type": "number" - } - }, - "required": [ - "h", - "w", - "x", - "y" - ] - } - }, - "required": [ - "gridPosition" - ] - } - ] - } - ] - } - }, - "containerType": { - "type": "string", - "enum": [ - "grid" - ] - }, - "gridPosition": { - "type": "object", - "properties": { - "h": { - "type": "number", - "description": "Height in grid units (default: 36 for charts)" - }, - "w": { - "type": "number", - "description": "Width in grid columns on a 24-column grid. Common widths: 24 (full), 12 (half), 8 (third), 6 (quarter). x + w must not exceed 24." - }, - "x": { - "type": "number", - "description": "X position on a 24-column grid (0=left edge, 12=middle). Items side-by-side share the same y with complementary x values." - }, - "y": { - "type": "number", - "description": "Y position in grid units (0=top, higher values=lower on page)" - } - }, - "required": [ - "h", - "w", - "x", - "y" - ] - }, - "metadata": { - "type": "object", - "properties": { - "attachedQueryKey": { - "type": "string", - "description": "Set by the auto-add-tile flow when this container was generated for a specific workbook tab. The server removes containers with a matching `attachedQueryKey` when that tab is deleted. The reducer clears this when the user adds unrelated content (a different query, filter, text tile, page switcher, or sub-container)." - }, - "generatedHeading": { - "type": "boolean", - "description": "Marks the auto-injected heading wrapper (title + description row) created for a tile, so it can be labeled generically and treated as managed." - }, - "locked": { - "type": "boolean", - "description": "Locks the container's internal arrangement so its children cannot be dragged, reordered, resized, or have new items dropped in. Cascades to all descendants. Does not lock the container's own position/size." - } - }, - "description": "Optional bookkeeping for this container (e.g. `attachedQueryKey` for auto-placed tiles)" - }, - "padding": { - "anyOf": [ - { - "type": "number", - "enum": [ - 0 - ] - }, - { - "type": "number", - "enum": [ - 0.5 - ] - }, - { - "type": "number", - "enum": [ - 1 - ] - }, - { - "type": "number", - "enum": [ - 2 - ] - }, - { - "type": "number", - "enum": [ - 3 - ] - }, - { - "type": "number", - "enum": [ - 4 - ] - }, - { - "type": "number", - "enum": [ - 5 - ] - }, - { - "type": "number", - "enum": [ - 6 - ] - }, - { - "type": "number", - "enum": [ - 7 - ] - }, - { - "type": "number", - "enum": [ - 8 - ] - }, - { - "type": "array", - "prefixItems": [ - { - "anyOf": [ - { - "type": "number", - "enum": [ - 0 - ] - }, - { - "type": "number", - "enum": [ - 0.5 - ] - }, - { - "type": "number", - "enum": [ - 1 - ] - }, - { - "type": "number", - "enum": [ - 2 - ] - }, - { - "type": "number", - "enum": [ - 3 - ] - }, - { - "type": "number", - "enum": [ - 4 - ] - }, - { - "type": "number", - "enum": [ - 5 - ] - }, - { - "type": "number", - "enum": [ - 6 - ] - }, - { - "type": "number", - "enum": [ - 7 - ] - }, - { - "type": "number", - "enum": [ - 8 - ] - } - ] - } - ] - }, - { - "type": "array", - "prefixItems": [ - { - "anyOf": [ - { - "type": "number", - "enum": [ - 0 - ] - }, - { - "type": "number", - "enum": [ - 0.5 - ] - }, - { - "type": "number", - "enum": [ - 1 - ] - }, - { - "type": "number", - "enum": [ - 2 - ] - }, - { - "type": "number", - "enum": [ - 3 - ] - }, - { - "type": "number", - "enum": [ - 4 - ] - }, - { - "type": "number", - "enum": [ - 5 - ] - }, - { - "type": "number", - "enum": [ - 6 - ] - }, - { - "type": "number", - "enum": [ - 7 - ] - }, - { - "type": "number", - "enum": [ - 8 - ] - } - ] - }, - { - "anyOf": [ - { - "type": "number", - "enum": [ - 0 - ] - }, - { - "type": "number", - "enum": [ - 0.5 - ] - }, - { - "type": "number", - "enum": [ - 1 - ] - }, - { - "type": "number", - "enum": [ - 2 - ] - }, - { - "type": "number", - "enum": [ - 3 - ] - }, - { - "type": "number", - "enum": [ - 4 - ] - }, - { - "type": "number", - "enum": [ - 5 - ] - }, - { - "type": "number", - "enum": [ - 6 - ] - }, - { - "type": "number", - "enum": [ - 7 - ] - }, - { - "type": "number", - "enum": [ - 8 - ] - } - ] - } - ] - }, - { - "type": "array", - "prefixItems": [ - { - "anyOf": [ - { - "type": "number", - "enum": [ - 0 - ] - }, - { - "type": "number", - "enum": [ - 0.5 - ] - }, - { - "type": "number", - "enum": [ - 1 - ] - }, - { - "type": "number", - "enum": [ - 2 - ] - }, - { + "padding": { + "anyOf": [ + { + "type": "number", + "enum": [ + 0 + ] + }, + { + "type": "number", + "enum": [ + 0.5 + ] + }, + { + "type": "number", + "enum": [ + 1 + ] + }, + { + "type": "number", + "enum": [ + 2 + ] + }, + { + "type": "number", + "enum": [ + 3 + ] + }, + { + "type": "number", + "enum": [ + 4 + ] + }, + { + "type": "number", + "enum": [ + 5 + ] + }, + { + "type": "number", + "enum": [ + 6 + ] + }, + { + "type": "number", + "enum": [ + 7 + ] + }, + { + "type": "number", + "enum": [ + 8 + ] + }, + { + "type": "array", + "prefixItems": [ + { + "anyOf": [ + { + "type": "number", + "enum": [ + 0 + ] + }, + { + "type": "number", + "enum": [ + 0.5 + ] + }, + { + "type": "number", + "enum": [ + 1 + ] + }, + { + "type": "number", + "enum": [ + 2 + ] + }, + { + "type": "number", + "enum": [ + 3 + ] + }, + { + "type": "number", + "enum": [ + 4 + ] + }, + { + "type": "number", + "enum": [ + 5 + ] + }, + { + "type": "number", + "enum": [ + 6 + ] + }, + { + "type": "number", + "enum": [ + 7 + ] + }, + { + "type": "number", + "enum": [ + 8 + ] + } + ] + } + ] + }, + { + "type": "array", + "prefixItems": [ + { + "anyOf": [ + { + "type": "number", + "enum": [ + 0 + ] + }, + { + "type": "number", + "enum": [ + 0.5 + ] + }, + { + "type": "number", + "enum": [ + 1 + ] + }, + { + "type": "number", + "enum": [ + 2 + ] + }, + { + "type": "number", + "enum": [ + 3 + ] + }, + { + "type": "number", + "enum": [ + 4 + ] + }, + { + "type": "number", + "enum": [ + 5 + ] + }, + { + "type": "number", + "enum": [ + 6 + ] + }, + { + "type": "number", + "enum": [ + 7 + ] + }, + { + "type": "number", + "enum": [ + 8 + ] + } + ] + }, + { + "anyOf": [ + { + "type": "number", + "enum": [ + 0 + ] + }, + { + "type": "number", + "enum": [ + 0.5 + ] + }, + { + "type": "number", + "enum": [ + 1 + ] + }, + { + "type": "number", + "enum": [ + 2 + ] + }, + { + "type": "number", + "enum": [ + 3 + ] + }, + { + "type": "number", + "enum": [ + 4 + ] + }, + { + "type": "number", + "enum": [ + 5 + ] + }, + { + "type": "number", + "enum": [ + 6 + ] + }, + { + "type": "number", + "enum": [ + 7 + ] + }, + { + "type": "number", + "enum": [ + 8 + ] + } + ] + } + ] + }, + { + "type": "array", + "prefixItems": [ + { + "anyOf": [ + { + "type": "number", + "enum": [ + 0 + ] + }, + { + "type": "number", + "enum": [ + 0.5 + ] + }, + { + "type": "number", + "enum": [ + 1 + ] + }, + { + "type": "number", + "enum": [ + 2 + ] + }, + { + "type": "number", + "enum": [ + 3 + ] + }, + { + "type": "number", + "enum": [ + 4 + ] + }, + { + "type": "number", + "enum": [ + 5 + ] + }, + { + "type": "number", + "enum": [ + 6 + ] + }, + { + "type": "number", + "enum": [ + 7 + ] + }, + { + "type": "number", + "enum": [ + 8 + ] + } + ] + }, + { + "anyOf": [ + { + "type": "number", + "enum": [ + 0 + ] + }, + { + "type": "number", + "enum": [ + 0.5 + ] + }, + { + "type": "number", + "enum": [ + 1 + ] + }, + { + "type": "number", + "enum": [ + 2 + ] + }, + { + "type": "number", + "enum": [ + 3 + ] + }, + { + "type": "number", + "enum": [ + 4 + ] + }, + { + "type": "number", + "enum": [ + 5 + ] + }, + { + "type": "number", + "enum": [ + 6 + ] + }, + { + "type": "number", + "enum": [ + 7 + ] + }, + { + "type": "number", + "enum": [ + 8 + ] + } + ] + }, + { + "anyOf": [ + { + "type": "number", + "enum": [ + 0 + ] + }, + { + "type": "number", + "enum": [ + 0.5 + ] + }, + { + "type": "number", + "enum": [ + 1 + ] + }, + { + "type": "number", + "enum": [ + 2 + ] + }, + { + "type": "number", + "enum": [ + 3 + ] + }, + { + "type": "number", + "enum": [ + 4 + ] + }, + { + "type": "number", + "enum": [ + 5 + ] + }, + { + "type": "number", + "enum": [ + 6 + ] + }, + { + "type": "number", + "enum": [ + 7 + ] + }, + { + "type": "number", + "enum": [ + 8 + ] + } + ] + } + ] + }, + { + "type": "array", + "prefixItems": [ + { + "anyOf": [ + { + "type": "number", + "enum": [ + 0 + ] + }, + { + "type": "number", + "enum": [ + 0.5 + ] + }, + { + "type": "number", + "enum": [ + 1 + ] + }, + { + "type": "number", + "enum": [ + 2 + ] + }, + { + "type": "number", + "enum": [ + 3 + ] + }, + { + "type": "number", + "enum": [ + 4 + ] + }, + { + "type": "number", + "enum": [ + 5 + ] + }, + { + "type": "number", + "enum": [ + 6 + ] + }, + { + "type": "number", + "enum": [ + 7 + ] + }, + { + "type": "number", + "enum": [ + 8 + ] + } + ] + }, + { + "anyOf": [ + { + "type": "number", + "enum": [ + 0 + ] + }, + { + "type": "number", + "enum": [ + 0.5 + ] + }, + { + "type": "number", + "enum": [ + 1 + ] + }, + { + "type": "number", + "enum": [ + 2 + ] + }, + { + "type": "number", + "enum": [ + 3 + ] + }, + { + "type": "number", + "enum": [ + 4 + ] + }, + { + "type": "number", + "enum": [ + 5 + ] + }, + { + "type": "number", + "enum": [ + 6 + ] + }, + { + "type": "number", + "enum": [ + 7 + ] + }, + { + "type": "number", + "enum": [ + 8 + ] + } + ] + }, + { + "anyOf": [ + { + "type": "number", + "enum": [ + 0 + ] + }, + { + "type": "number", + "enum": [ + 0.5 + ] + }, + { + "type": "number", + "enum": [ + 1 + ] + }, + { + "type": "number", + "enum": [ + 2 + ] + }, + { + "type": "number", + "enum": [ + 3 + ] + }, + { + "type": "number", + "enum": [ + 4 + ] + }, + { + "type": "number", + "enum": [ + 5 + ] + }, + { + "type": "number", + "enum": [ + 6 + ] + }, + { + "type": "number", + "enum": [ + 7 + ] + }, + { + "type": "number", + "enum": [ + 8 + ] + } + ] + }, + { + "anyOf": [ + { + "type": "number", + "enum": [ + 0 + ] + }, + { + "type": "number", + "enum": [ + 0.5 + ] + }, + { + "type": "number", + "enum": [ + 1 + ] + }, + { + "type": "number", + "enum": [ + 2 + ] + }, + { + "type": "number", + "enum": [ + 3 + ] + }, + { + "type": "number", + "enum": [ + 4 + ] + }, + { + "type": "number", + "enum": [ + 5 + ] + }, + { + "type": "number", + "enum": [ + 6 + ] + }, + { + "type": "number", + "enum": [ + 7 + ] + }, + { + "type": "number", + "enum": [ + 8 + ] + } + ] + } + ] + }, + { + "type": "null" + } + ] + }, + "preset": { + "type": "string", + "pattern": "^[a-z0-9-]+$", + "description": "Visual preset for the content item (e.g., \"tile-align\" for outer spacing to align with tile containers)" + }, + "description": { + "type": "string", + "description": "Lightweight supporting text shown beneath the label, e.g. wire-frame instructions." + }, + "label": { + "type": "string", + "description": "Custom heading. Falls back to a type-derived default (e.g. \"Placeholder query\") when unset." + }, + "placeholderType": { + "type": "string", + "enum": [ + "query", + "control", + "filter", + "text" + ], + "description": "The content type this placeholder stands in for. Unset means no type has been picked yet." + }, + "style": { + "type": "object", + "properties": { + "aspectRatio": { + "type": "string" + }, + "fillSpace": { + "type": "boolean" + }, + "height": { + "type": "string" + }, + "maxHeight": { + "type": "string" + }, + "maxWidth": { + "type": "string" + }, + "minHeight": { + "type": "string" + }, + "minWidth": { + "type": "string" + }, + "width": { + "type": "string" + } + } + }, + "type": { + "type": "string", + "enum": [ + "placeholder" + ] + } + }, + "required": [ + "instanceKey", + "type" + ] + }, + { + "type": "object", + "properties": { + "instanceKey": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "required": [ + "instanceKey", + "type" + ], + "additionalProperties": {} + } + ] + }, + { + "type": "object", + "properties": { + "gridPosition": { + "type": "object", + "properties": { + "h": { + "type": "number" + }, + "w": { + "type": "number" + }, + "x": { + "type": "number" + }, + "y": { + "type": "number" + } + }, + "required": [ + "h", + "w", + "x", + "y" + ] + } + }, + "required": [ + "gridPosition" + ] + } + ] + } + ] + } + }, + "containerType": { + "type": "string", + "enum": [ + "grid" + ] + }, + "gridPosition": { + "type": "object", + "properties": { + "h": { + "type": "integer", + "minimum": 1, + "description": "Height in grid units (default: 36 for charts)" + }, + "w": { + "type": "integer", + "minimum": 1, + "description": "Width in grid columns on a 24-column grid. Common widths: 24 (full), 12 (half), 8 (third), 6 (quarter). x + w must not exceed 24." + }, + "x": { + "type": "integer", + "minimum": 0, + "description": "X position on a 24-column grid (0=left edge, 12=middle). Items side-by-side share the same y with complementary x values." + }, + "y": { + "type": "integer", + "minimum": 0, + "description": "Y position in grid units (0=top, higher values=lower on page)" + } + }, + "required": [ + "h", + "w", + "x", + "y" + ] + }, + "metadata": { + "type": "object", + "properties": { + "attachedQueryKey": { + "type": "string", + "description": "Set by the auto-add-tile flow when this container was generated for a specific workbook tab. The server removes containers with a matching `attachedQueryKey` when that tab is deleted. The reducer clears this when the user adds unrelated content (a different query, filter, text tile, page switcher, or sub-container)." + }, + "generatedHeading": { + "type": "boolean", + "description": "Marks the auto-injected heading wrapper (title + description row) created for a tile, so it can be labeled generically and treated as managed." + }, + "locked": { + "type": "boolean", + "description": "Locks the container's internal arrangement so its children cannot be dragged, reordered, resized, or have new items dropped in. Cascades to all descendants. Does not lock the container's own position/size." + } + }, + "description": "Optional bookkeeping for this container (e.g. `attachedQueryKey` for auto-placed tiles)" + }, + "padding": { + "anyOf": [ + { + "type": "number", + "enum": [ + 0 + ] + }, + { + "type": "number", + "enum": [ + 0.5 + ] + }, + { + "type": "number", + "enum": [ + 1 + ] + }, + { + "type": "number", + "enum": [ + 2 + ] + }, + { + "type": "number", + "enum": [ + 3 + ] + }, + { + "type": "number", + "enum": [ + 4 + ] + }, + { + "type": "number", + "enum": [ + 5 + ] + }, + { + "type": "number", + "enum": [ + 6 + ] + }, + { + "type": "number", + "enum": [ + 7 + ] + }, + { + "type": "number", + "enum": [ + 8 + ] + }, + { + "type": "array", + "prefixItems": [ + { + "anyOf": [ + { + "type": "number", + "enum": [ + 0 + ] + }, + { + "type": "number", + "enum": [ + 0.5 + ] + }, + { + "type": "number", + "enum": [ + 1 + ] + }, + { + "type": "number", + "enum": [ + 2 + ] + }, + { + "type": "number", + "enum": [ + 3 + ] + }, + { + "type": "number", + "enum": [ + 4 + ] + }, + { + "type": "number", + "enum": [ + 5 + ] + }, + { + "type": "number", + "enum": [ + 6 + ] + }, + { + "type": "number", + "enum": [ + 7 + ] + }, + { + "type": "number", + "enum": [ + 8 + ] + } + ] + } + ] + }, + { + "type": "array", + "prefixItems": [ + { + "anyOf": [ + { + "type": "number", + "enum": [ + 0 + ] + }, + { + "type": "number", + "enum": [ + 0.5 + ] + }, + { + "type": "number", + "enum": [ + 1 + ] + }, + { + "type": "number", + "enum": [ + 2 + ] + }, + { + "type": "number", + "enum": [ + 3 + ] + }, + { + "type": "number", + "enum": [ + 4 + ] + }, + { + "type": "number", + "enum": [ + 5 + ] + }, + { + "type": "number", + "enum": [ + 6 + ] + }, + { + "type": "number", + "enum": [ + 7 + ] + }, + { + "type": "number", + "enum": [ + 8 + ] + } + ] + }, + { + "anyOf": [ + { + "type": "number", + "enum": [ + 0 + ] + }, + { + "type": "number", + "enum": [ + 0.5 + ] + }, + { + "type": "number", + "enum": [ + 1 + ] + }, + { + "type": "number", + "enum": [ + 2 + ] + }, + { + "type": "number", + "enum": [ + 3 + ] + }, + { + "type": "number", + "enum": [ + 4 + ] + }, + { + "type": "number", + "enum": [ + 5 + ] + }, + { + "type": "number", + "enum": [ + 6 + ] + }, + { + "type": "number", + "enum": [ + 7 + ] + }, + { + "type": "number", + "enum": [ + 8 + ] + } + ] + } + ] + }, + { + "type": "array", + "prefixItems": [ + { + "anyOf": [ + { + "type": "number", + "enum": [ + 0 + ] + }, + { + "type": "number", + "enum": [ + 0.5 + ] + }, + { + "type": "number", + "enum": [ + 1 + ] + }, + { + "type": "number", + "enum": [ + 2 + ] + }, + { "type": "number", "enum": [ 3 @@ -11942,161 +12881,974 @@ 8 ] } - ] + ] + }, + { + "anyOf": [ + { + "type": "number", + "enum": [ + 0 + ] + }, + { + "type": "number", + "enum": [ + 0.5 + ] + }, + { + "type": "number", + "enum": [ + 1 + ] + }, + { + "type": "number", + "enum": [ + 2 + ] + }, + { + "type": "number", + "enum": [ + 3 + ] + }, + { + "type": "number", + "enum": [ + 4 + ] + }, + { + "type": "number", + "enum": [ + 5 + ] + }, + { + "type": "number", + "enum": [ + 6 + ] + }, + { + "type": "number", + "enum": [ + 7 + ] + }, + { + "type": "number", + "enum": [ + 8 + ] + } + ] + } + ] + } + ] + }, + "style": { + "type": "string", + "pattern": "^[a-z0-9-]+$" + } + }, + "required": [ + "instanceKey", + "children", + "containerType" + ], + "description": "Grid container — children are positioned on a grid (each carries a gridPosition)." + }, + "StackContainer": { + "type": "object", + "properties": { + "description": { + "type": "string", + "description": "Optional description for the container, providing additional context or information" + }, + "instanceKey": { + "type": "string", + "description": "Unique identifier for this container. Used to reference the container when adding, moving, or removing children." + }, + "name": { + "type": "string", + "description": "Human-readable name for the container, used for easier reference in logic and design" + }, + "aspectRatio": { + "type": "string" + }, + "fillSpace": { + "type": "boolean" + }, + "height": { + "type": "string" + }, + "maxHeight": { + "type": "string" + }, + "maxWidth": { + "type": "string" + }, + "minHeight": { + "type": "string" + }, + "minWidth": { + "type": "string" + }, + "width": { + "type": "string" + }, + "after": { + "anyOf": [ + { + "$ref": "#/components/schemas/StackContainer" + }, + { + "$ref": "#/components/schemas/ReferenceContainer" + } + ] + }, + "align": { + "type": "string", + "enum": [ + "flex-start", + "flex-end", + "center", + "stretch" + ], + "description": "Cross-axis alignment of children (e.g., center, stretch)" + }, + "before": { + "anyOf": [ + { + "$ref": "#/components/schemas/StackContainer" + }, + { + "$ref": "#/components/schemas/ReferenceContainer" + } + ] + }, + "children": { + "type": "array", + "items": { + "anyOf": [ + { + "type": "object", + "properties": { + "instanceKey": { + "type": "string", + "description": "Unique identifier for this specific placement of the content item. Use this key (not the query id) when repositioning or removing items." + }, + "padding": { + "anyOf": [ + { + "type": "number", + "enum": [ + 0 + ] + }, + { + "type": "number", + "enum": [ + 0.5 + ] + }, + { + "type": "number", + "enum": [ + 1 + ] + }, + { + "type": "number", + "enum": [ + 2 + ] + }, + { + "type": "number", + "enum": [ + 3 + ] + }, + { + "type": "number", + "enum": [ + 4 + ] + }, + { + "type": "number", + "enum": [ + 5 + ] + }, + { + "type": "number", + "enum": [ + 6 + ] + }, + { + "type": "number", + "enum": [ + 7 + ] + }, + { + "type": "number", + "enum": [ + 8 + ] + }, + { + "type": "array", + "prefixItems": [ + { + "anyOf": [ + { + "type": "number", + "enum": [ + 0 + ] + }, + { + "type": "number", + "enum": [ + 0.5 + ] + }, + { + "type": "number", + "enum": [ + 1 + ] + }, + { + "type": "number", + "enum": [ + 2 + ] + }, + { + "type": "number", + "enum": [ + 3 + ] + }, + { + "type": "number", + "enum": [ + 4 + ] + }, + { + "type": "number", + "enum": [ + 5 + ] + }, + { + "type": "number", + "enum": [ + 6 + ] + }, + { + "type": "number", + "enum": [ + 7 + ] + }, + { + "type": "number", + "enum": [ + 8 + ] + } + ] + } + ] + }, + { + "type": "array", + "prefixItems": [ + { + "anyOf": [ + { + "type": "number", + "enum": [ + 0 + ] + }, + { + "type": "number", + "enum": [ + 0.5 + ] + }, + { + "type": "number", + "enum": [ + 1 + ] + }, + { + "type": "number", + "enum": [ + 2 + ] + }, + { + "type": "number", + "enum": [ + 3 + ] + }, + { + "type": "number", + "enum": [ + 4 + ] + }, + { + "type": "number", + "enum": [ + 5 + ] + }, + { + "type": "number", + "enum": [ + 6 + ] + }, + { + "type": "number", + "enum": [ + 7 + ] + }, + { + "type": "number", + "enum": [ + 8 + ] + } + ] + }, + { + "anyOf": [ + { + "type": "number", + "enum": [ + 0 + ] + }, + { + "type": "number", + "enum": [ + 0.5 + ] + }, + { + "type": "number", + "enum": [ + 1 + ] + }, + { + "type": "number", + "enum": [ + 2 + ] + }, + { + "type": "number", + "enum": [ + 3 + ] + }, + { + "type": "number", + "enum": [ + 4 + ] + }, + { + "type": "number", + "enum": [ + 5 + ] + }, + { + "type": "number", + "enum": [ + 6 + ] + }, + { + "type": "number", + "enum": [ + 7 + ] + }, + { + "type": "number", + "enum": [ + 8 + ] + } + ] + } + ] + }, + { + "type": "array", + "prefixItems": [ + { + "anyOf": [ + { + "type": "number", + "enum": [ + 0 + ] + }, + { + "type": "number", + "enum": [ + 0.5 + ] + }, + { + "type": "number", + "enum": [ + 1 + ] + }, + { + "type": "number", + "enum": [ + 2 + ] + }, + { + "type": "number", + "enum": [ + 3 + ] + }, + { + "type": "number", + "enum": [ + 4 + ] + }, + { + "type": "number", + "enum": [ + 5 + ] + }, + { + "type": "number", + "enum": [ + 6 + ] + }, + { + "type": "number", + "enum": [ + 7 + ] + }, + { + "type": "number", + "enum": [ + 8 + ] + } + ] + }, + { + "anyOf": [ + { + "type": "number", + "enum": [ + 0 + ] + }, + { + "type": "number", + "enum": [ + 0.5 + ] + }, + { + "type": "number", + "enum": [ + 1 + ] + }, + { + "type": "number", + "enum": [ + 2 + ] + }, + { + "type": "number", + "enum": [ + 3 + ] + }, + { + "type": "number", + "enum": [ + 4 + ] + }, + { + "type": "number", + "enum": [ + 5 + ] + }, + { + "type": "number", + "enum": [ + 6 + ] + }, + { + "type": "number", + "enum": [ + 7 + ] + }, + { + "type": "number", + "enum": [ + 8 + ] + } + ] + }, + { + "anyOf": [ + { + "type": "number", + "enum": [ + 0 + ] + }, + { + "type": "number", + "enum": [ + 0.5 + ] + }, + { + "type": "number", + "enum": [ + 1 + ] + }, + { + "type": "number", + "enum": [ + 2 + ] + }, + { + "type": "number", + "enum": [ + 3 + ] + }, + { + "type": "number", + "enum": [ + 4 + ] + }, + { + "type": "number", + "enum": [ + 5 + ] + }, + { + "type": "number", + "enum": [ + 6 + ] + }, + { + "type": "number", + "enum": [ + 7 + ] + }, + { + "type": "number", + "enum": [ + 8 + ] + } + ] + } + ] + }, + { + "type": "array", + "prefixItems": [ + { + "anyOf": [ + { + "type": "number", + "enum": [ + 0 + ] + }, + { + "type": "number", + "enum": [ + 0.5 + ] + }, + { + "type": "number", + "enum": [ + 1 + ] + }, + { + "type": "number", + "enum": [ + 2 + ] + }, + { + "type": "number", + "enum": [ + 3 + ] + }, + { + "type": "number", + "enum": [ + 4 + ] + }, + { + "type": "number", + "enum": [ + 5 + ] + }, + { + "type": "number", + "enum": [ + 6 + ] + }, + { + "type": "number", + "enum": [ + 7 + ] + }, + { + "type": "number", + "enum": [ + 8 + ] + } + ] + }, + { + "anyOf": [ + { + "type": "number", + "enum": [ + 0 + ] + }, + { + "type": "number", + "enum": [ + 0.5 + ] + }, + { + "type": "number", + "enum": [ + 1 + ] + }, + { + "type": "number", + "enum": [ + 2 + ] + }, + { + "type": "number", + "enum": [ + 3 + ] + }, + { + "type": "number", + "enum": [ + 4 + ] + }, + { + "type": "number", + "enum": [ + 5 + ] + }, + { + "type": "number", + "enum": [ + 6 + ] + }, + { + "type": "number", + "enum": [ + 7 + ] + }, + { + "type": "number", + "enum": [ + 8 + ] + } + ] + }, + { + "anyOf": [ + { + "type": "number", + "enum": [ + 0 + ] + }, + { + "type": "number", + "enum": [ + 0.5 + ] + }, + { + "type": "number", + "enum": [ + 1 + ] + }, + { + "type": "number", + "enum": [ + 2 + ] + }, + { + "type": "number", + "enum": [ + 3 + ] + }, + { + "type": "number", + "enum": [ + 4 + ] + }, + { + "type": "number", + "enum": [ + 5 + ] + }, + { + "type": "number", + "enum": [ + 6 + ] + }, + { + "type": "number", + "enum": [ + 7 + ] + }, + { + "type": "number", + "enum": [ + 8 + ] + } + ] + }, + { + "anyOf": [ + { + "type": "number", + "enum": [ + 0 + ] + }, + { + "type": "number", + "enum": [ + 0.5 + ] + }, + { + "type": "number", + "enum": [ + 1 + ] + }, + { + "type": "number", + "enum": [ + 2 + ] + }, + { + "type": "number", + "enum": [ + 3 + ] + }, + { + "type": "number", + "enum": [ + 4 + ] + }, + { + "type": "number", + "enum": [ + 5 + ] + }, + { + "type": "number", + "enum": [ + 6 + ] + }, + { + "type": "number", + "enum": [ + 7 + ] + }, + { + "type": "number", + "enum": [ + 8 + ] + } + ] + } + ] + }, + { + "type": "null" + } + ] + }, + "preset": { + "type": "string", + "pattern": "^[a-z0-9-]+$", + "description": "Visual preset for the content item (e.g., \"tile-align\" for outer spacing to align with tile containers)" + }, + "as": { + "type": "string", + "enum": [ + "chart", + "result", + "ai", + "metadata" + ], + "description": "Render mode: \"chart\" for visualization, \"result\" for data table, \"ai\" for AI summary, \"metadata\" for query metadata" + }, + "detachedContent": { + "type": "string", + "description": "Set when a metadata field is detached: local text rendered instead of the query value" + }, + "format": { + "type": "string", + "enum": [ + "subtitle", + "description", + "name" + ], + "description": "Display format when as is \"ai\" or \"metadata\": \"name\" (metadata only), \"subtitle\", or \"description\"" + }, + "id": { + "type": "string", + "pattern": "^[1-9][0-9]*$", + "description": "The query presentation ID this content item references" + }, + "name": { + "type": "string", + "description": "Display name for this query item" + }, + "style": { + "type": "object", + "properties": { + "aspectRatio": { + "type": "string" + }, + "fillSpace": { + "type": "boolean" + }, + "height": { + "type": "string" + }, + "maxHeight": { + "type": "string" + }, + "maxWidth": { + "type": "string" + }, + "minHeight": { + "type": "string" + }, + "minWidth": { + "type": "string" + }, + "width": { + "type": "string" + } + } + }, + "type": { + "type": "string", + "enum": [ + "query" + ] + } }, - { - "anyOf": [ - { - "type": "number", - "enum": [ - 0 - ] - }, - { - "type": "number", - "enum": [ - 0.5 - ] - }, - { - "type": "number", - "enum": [ - 1 - ] - }, - { - "type": "number", - "enum": [ - 2 - ] - }, - { - "type": "number", - "enum": [ - 3 - ] - }, - { - "type": "number", - "enum": [ - 4 - ] - }, - { - "type": "number", - "enum": [ - 5 - ] - }, - { - "type": "number", - "enum": [ - 6 - ] - }, - { - "type": "number", - "enum": [ - 7 - ] - }, - { - "type": "number", - "enum": [ - 8 - ] - } - ] - } - ] - } - ] - }, - "style": { - "type": "string", - "pattern": "^[a-z0-9-]+$" - } - }, - "required": [ - "instanceKey", - "children", - "containerType" - ], - "description": "Grid container — children are positioned on a grid (each carries a gridPosition)." - }, - "StackContainer": { - "type": "object", - "properties": { - "description": { - "type": "string", - "description": "Optional description for the container, providing additional context or information" - }, - "instanceKey": { - "type": "string", - "description": "Unique identifier for this container. Used to reference the container when adding, moving, or removing children." - }, - "name": { - "type": "string", - "description": "Human-readable name for the container, used for easier reference in logic and design" - }, - "aspectRatio": { - "type": "string" - }, - "fillSpace": { - "type": "boolean" - }, - "height": { - "type": "string" - }, - "maxHeight": { - "type": "string" - }, - "maxWidth": { - "type": "string" - }, - "minHeight": { - "type": "string" - }, - "minWidth": { - "type": "string" - }, - "width": { - "type": "string" - }, - "after": { - "anyOf": [ - { - "$ref": "#/components/schemas/StackContainer" - }, - { - "$ref": "#/components/schemas/ReferenceContainer" - } - ] - }, - "align": { - "type": "string", - "enum": [ - "flex-start", - "flex-end", - "center", - "stretch" - ], - "description": "Cross-axis alignment of children (e.g., center, stretch)" - }, - "before": { - "anyOf": [ - { - "$ref": "#/components/schemas/StackContainer" - }, - { - "$ref": "#/components/schemas/ReferenceContainer" - } - ] - }, - "children": { - "type": "array", - "items": { - "anyOf": [ + "required": [ + "instanceKey", + "id", + "type" + ] + }, { "type": "object", "properties": { @@ -12836,33 +14588,46 @@ "pattern": "^[a-z0-9-]+$", "description": "Visual preset for the content item (e.g., \"tile-align\" for outer spacing to align with tile containers)" }, - "as": { - "type": "string", - "enum": [ - "chart", - "result", - "ai", - "metadata" - ], - "description": "Render mode: \"chart\" for visualization, \"result\" for data table, \"ai\" for AI summary, \"metadata\" for query metadata" - }, - "format": { - "type": "string", - "enum": [ - "subtitle", - "description", - "name" + "appearance": { + "oneOf": [ + { + "type": "object", + "properties": { + "as": { + "type": "string", + "enum": [ + "inline" + ] + } + }, + "required": [ + "as" + ] + }, + { + "type": "object", + "properties": { + "as": { + "type": "string", + "enum": [ + "tooltip" + ] + } + }, + "required": [ + "as" + ] + } ], - "description": "Display format when as is \"ai\" or \"metadata\": \"name\" (metadata only), \"subtitle\", or \"description\"" + "description": "Display mode: \"inline\" renders directly, \"tooltip\" shows on hover" }, - "id": { + "content": { "type": "string", - "pattern": "^[1-9][0-9]*$", - "description": "The query presentation ID this content item references" + "description": "The text content to display (supports markdown)" }, "name": { "type": "string", - "description": "Display name for this query item" + "description": "Display name for this text item (e.g., title, subtitle)" }, "style": { "type": "object", @@ -12893,16 +14658,25 @@ } } }, + "textAlign": { + "type": "string", + "enum": [ + "start", + "center", + "end" + ], + "description": "Text alignment: \"start\", \"center\", or \"end\"" + }, "type": { "type": "string", "enum": [ - "query" + "inline-text" ] } }, "required": [ "instanceKey", - "id", + "content", "type" ] }, @@ -13653,7 +15427,14 @@ "as": { "type": "string", "enum": [ - "inline" + "tabs" + ] + }, + "variant": { + "type": "string", + "enum": [ + "underline", + "bordered" ] } }, @@ -13667,24 +15448,88 @@ "as": { "type": "string", "enum": [ - "tooltip" + "buttons" + ] + }, + "variant": { + "type": "string", + "enum": [ + "segment", + "toggle", + "pills" + ] + } + }, + "required": [ + "as" + ] + }, + { + "type": "object", + "properties": { + "as": { + "type": "string", + "enum": [ + "list" + ] + }, + "description": { + "type": "boolean" + } + }, + "required": [ + "as" + ] + }, + { + "type": "object", + "properties": { + "as": { + "type": "string", + "enum": [ + "dropdown" ] + }, + "description": { + "type": "boolean" } }, "required": [ "as" ] } - ], - "description": "Display mode: \"inline\" renders directly, \"tooltip\" shows on hover" - }, - "content": { - "type": "string", - "description": "The text content to display (supports markdown)" + ] }, - "name": { - "type": "string", - "description": "Display name for this text item (e.g., title, subtitle)" + "options": { + "type": "array", + "items": { + "type": "object", + "properties": { + "disabled": { + "type": "boolean" + }, + "id": { + "type": "string" + }, + "includeControls": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "target": { + "type": "string" + }, + "uri": { + "type": "string" + }, + "value": { + "type": "string", + "description": "Page link target. Must exactly equal an existing page container’s instanceKey — not its name, label, or a slug. A value matching no page redirects to the main dashboard view with a \"Page not found\" message. Ignored when `uri` is set." + } + } + }, + "description": "Omit to auto-derive one tab per page, kept in sync as pages are added, removed, renamed, or reordered. Set to curate, reorder, or add custom-URL tabs; each option’s `value` must then match a page instanceKey." }, "style": { "type": "object", @@ -13715,25 +15560,15 @@ } } }, - "textAlign": { - "type": "string", - "enum": [ - "start", - "center", - "end" - ], - "description": "Text alignment: \"start\", \"center\", or \"end\"" - }, "type": { "type": "string", "enum": [ - "inline-text" + "inline-page-switcher" ] } }, "required": [ "instanceKey", - "content", "type" ] }, @@ -14476,115 +16311,10 @@ "pattern": "^[a-z0-9-]+$", "description": "Visual preset for the content item (e.g., \"tile-align\" for outer spacing to align with tile containers)" }, - "appearance": { - "oneOf": [ - { - "type": "object", - "properties": { - "as": { - "type": "string", - "enum": [ - "tabs" - ] - }, - "variant": { - "type": "string", - "enum": [ - "underline", - "bordered" - ] - } - }, - "required": [ - "as" - ] - }, - { - "type": "object", - "properties": { - "as": { - "type": "string", - "enum": [ - "buttons" - ] - }, - "variant": { - "type": "string", - "enum": [ - "segment", - "toggle", - "pills" - ] - } - }, - "required": [ - "as" - ] - }, - { - "type": "object", - "properties": { - "as": { - "type": "string", - "enum": [ - "list" - ] - }, - "description": { - "type": "boolean" - } - }, - "required": [ - "as" - ] - }, - { - "type": "object", - "properties": { - "as": { - "type": "string", - "enum": [ - "dropdown" - ] - }, - "description": { - "type": "boolean" - } - }, - "required": [ - "as" - ] - } - ] - }, - "options": { - "type": "array", - "items": { - "type": "object", - "properties": { - "disabled": { - "type": "boolean" - }, - "id": { - "type": "string" - }, - "includeControls": { - "type": "boolean" - }, - "label": { - "type": "string" - }, - "target": { - "type": "string" - }, - "uri": { - "type": "string" - }, - "value": { - "type": "string" - } - } - } + "id": { + "type": "string", + "format": "uuid", + "description": "UUID of the rich text content block" }, "style": { "type": "object", @@ -14618,12 +16348,13 @@ "type": { "type": "string", "enum": [ - "inline-page-switcher" + "text" ] } }, "required": [ "instanceKey", + "id", "type" ] }, @@ -15367,9 +17098,13 @@ "description": "Visual preset for the content item (e.g., \"tile-align\" for outer spacing to align with tile containers)" }, "id": { + "type": "string" + }, + "type": { "type": "string", - "format": "uuid", - "description": "UUID of the rich text content block" + "enum": [ + "control" + ] }, "style": { "type": "object", @@ -15399,12 +17134,6 @@ "type": "string" } } - }, - "type": { - "type": "string", - "enum": [ - "text" - ] } }, "required": [ @@ -16158,9 +17887,51 @@ "type": { "type": "string", "enum": [ - "control" + "filter" ] }, + "appearance": { + "type": "object", + "properties": { + "control": { + "type": "string", + "enum": [ + "buttonToggle", + "dropdown" + ] + }, + "display": { + "type": "string", + "enum": [ + "inline", + "popover" + ] + }, + "options": { + "type": "array", + "items": { + "type": "object", + "properties": { + "label": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "required": [ + "value" + ] + } + }, + "value": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, "style": { "type": "object", "properties": { @@ -16936,56 +18707,11 @@ "pattern": "^[a-z0-9-]+$", "description": "Visual preset for the content item (e.g., \"tile-align\" for outer spacing to align with tile containers)" }, - "id": { - "type": "string" - }, - "type": { - "type": "string", - "enum": [ - "filter" - ] - }, - "appearance": { - "type": "object", - "properties": { - "control": { - "type": "string", - "enum": [ - "buttonToggle", - "dropdown" - ] - }, - "display": { - "type": "string", - "enum": [ - "inline", - "popover" - ] - }, - "options": { - "type": "array", - "items": { - "type": "object", - "properties": { - "label": { - "type": "string" - }, - "value": { - "type": "string" - } - }, - "required": [ - "value" - ] - } - }, - "value": { - "type": "array", - "items": { - "type": "string" - } - } - } + "size": { + "type": "number", + "minimum": 0, + "maximum": 2000, + "description": "Fixed size in px along the parent stack axis (default 16). In grids the size comes from gridPosition; ignored when style.fillSpace is true." }, "style": { "type": "object", @@ -17015,11 +18741,16 @@ "type": "string" } } + }, + "type": { + "type": "string", + "enum": [ + "inline-spacer" + ] } }, "required": [ "instanceKey", - "id", "type" ] }, @@ -17762,11 +19493,32 @@ "pattern": "^[a-z0-9-]+$", "description": "Visual preset for the content item (e.g., \"tile-align\" for outer spacing to align with tile containers)" }, - "size": { - "type": "number", - "minimum": 0, - "maximum": 2000, - "description": "Fixed size in px along the parent stack axis (default 16). In grids the size comes from gridPosition; ignored when style.fillSpace is true." + "align": { + "type": "string", + "enum": [ + "start", + "center", + "end" + ], + "description": "Placement of the line within its slot along the cross axis (default center): horizontal → top/center/bottom, vertical → left/center/right" + }, + "color": { + "type": "string", + "enum": [ + "border1", + "border4", + "text1", + "text4" + ], + "description": "Theme color for the line, subtle → bold (default border4)" + }, + "direction": { + "type": "string", + "enum": [ + "horizontal", + "vertical" + ], + "description": "Line orientation (default horizontal)" }, "style": { "type": "object", @@ -17797,10 +19549,33 @@ } } }, + "thickness": { + "anyOf": [ + { + "type": "number", + "enum": [ + 1 + ] + }, + { + "type": "number", + "enum": [ + 2 + ] + }, + { + "type": "number", + "enum": [ + 4 + ] + } + ], + "description": "Line thickness in px (default 1)" + }, "type": { "type": "string", "enum": [ - "inline-spacer" + "inline-divider" ] } }, @@ -18548,32 +20323,23 @@ "pattern": "^[a-z0-9-]+$", "description": "Visual preset for the content item (e.g., \"tile-align\" for outer spacing to align with tile containers)" }, - "align": { + "description": { "type": "string", - "enum": [ - "start", - "center", - "end" - ], - "description": "Placement of the line within its slot along the cross axis (default center): horizontal → top/center/bottom, vertical → left/center/right" + "description": "Lightweight supporting text shown beneath the label, e.g. wire-frame instructions." }, - "color": { + "label": { "type": "string", - "enum": [ - "border1", - "border4", - "text1", - "text4" - ], - "description": "Theme color for the line, subtle → bold (default border4)" + "description": "Custom heading. Falls back to a type-derived default (e.g. \"Placeholder query\") when unset." }, - "direction": { + "placeholderType": { "type": "string", "enum": [ - "horizontal", - "vertical" + "query", + "control", + "filter", + "text" ], - "description": "Line orientation (default horizontal)" + "description": "The content type this placeholder stands in for. Unset means no type has been picked yet." }, "style": { "type": "object", @@ -18604,33 +20370,10 @@ } } }, - "thickness": { - "anyOf": [ - { - "type": "number", - "enum": [ - 1 - ] - }, - { - "type": "number", - "enum": [ - 2 - ] - }, - { - "type": "number", - "enum": [ - 4 - ] - } - ], - "description": "Line thickness in px (default 1)" - }, "type": { "type": "string", "enum": [ - "inline-divider" + "placeholder" ] } }, @@ -23594,6 +25337,7 @@ "summaryValue", "svgMap", "table", + "treemap", null ], "description": "High-level chart type (e.g. \"bar\", \"line\", \"area\")." @@ -23612,6 +25356,12 @@ "visConfig": { "type": "object", "properties": { + "config": { + "type": "object", + "properties": {}, + "additionalProperties": {}, + "description": "The vis-type-specific spec — KPI rows, chart mark/series, etc. GET nests the spec here; PATCH also accepts it spread flat next to visType for backward compatibility." + }, "visType": { "type": [ "string", @@ -23628,6 +25378,7 @@ "sankey", "single-record", "svg-map", + "treemap", "omni-spreadsheet", "spreadsheet-tab", "summary-value", @@ -27666,6 +29417,7 @@ "summaryValue", "svgMap", "table", + "treemap", null ], "description": "High-level chart type (e.g. \"bar\", \"line\", \"area\")." @@ -27684,6 +29436,12 @@ "visConfig": { "type": "object", "properties": { + "config": { + "type": "object", + "properties": {}, + "additionalProperties": {}, + "description": "The vis-type-specific spec — KPI rows, chart mark/series, etc. GET nests the spec here; PATCH also accepts it spread flat next to visType for backward compatibility." + }, "visType": { "type": [ "string", @@ -27700,6 +29458,7 @@ "sankey", "single-record", "svg-map", + "treemap", "omni-spreadsheet", "spreadsheet-tab", "summary-value", @@ -28743,6 +30502,14 @@ "agentic_job": { "$ref": "#/components/schemas/EvalRunResultAgenticJob" }, + "ai_timing_ms": { + "type": [ + "integer", + "null" + ], + "description": "Strict main-agent LLM processing time in milliseconds — the measured model-call duration, excluding tool execution and subagent model calls (those count toward `tool_timing_ms`). Shown as \"AI time\" in the UI. Runs recorded before this was measured fall back to an approximation (`timing_ms` minus tool latency).", + "example": 4121 + }, "cost": { "type": [ "number", @@ -28815,12 +30582,21 @@ "integer", "null" ], - "description": "Total AI time in milliseconds — all LLM processing and tool calls. Shown as \"AI time\" in the UI.", + "description": "Total `/generate` wall-time in milliseconds — LLM processing plus inner-loop tool execution. `ai_timing_ms` and `tool_timing_ms` split this; warehouse query time is separate (`query_timing_ms`).", "example": 4321 + }, + "tool_timing_ms": { + "type": [ + "integer", + "null" + ], + "description": "Inner-loop tool latency in milliseconds — time spent running tools the model invoked (model and field-value lookups, query planning), excluding the warehouse query itself (`query_timing_ms`). Null for runs recorded before per-tool latency was tracked.", + "example": 200 } }, "required": [ "agentic_job", + "ai_timing_ms", "cost", "error_reason", "expectation", @@ -28830,7 +30606,8 @@ "query_timing_ms", "score", "scoring_cost", - "timing_ms" + "timing_ms", + "tool_timing_ms" ] }, "EvalRunResultAgenticJob": { @@ -31679,6 +33456,10 @@ "type": "integer", "description": "Number of documents modified" }, + "replaced_input_column_keys_count": { + "type": "integer", + "description": "Number of input columns whose key references were replaced" + }, "replaced_queries_count": { "type": "integer", "description": "Number of queries replaced" @@ -31695,6 +33476,7 @@ "required": [ "replaced_dashboard_filters_count", "replaced_documents_count", + "replaced_input_column_keys_count", "replaced_queries_count", "replaced_workbook_models_count", "skipped_pr_required_count" @@ -34796,6 +36578,16 @@ } } }, + "403": { + "description": "Insufficient permissions. AI query generation must be enabled for the organization and the caller must have permission to use AI on the job's model.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError403" + } + } + } + }, "404": { "description": "Job not found. The job may not exist or may belong to a different organization.", "content": { @@ -34948,6 +36740,16 @@ } } }, + "403": { + "description": "Insufficient permissions. AI query generation must be enabled for the organization and the caller must have permission to use AI on the job's model.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError403" + } + } + } + }, "404": { "description": "Job not found, not in COMPLETE state, or result is no longer available (results are retained for 14 days).", "content": { @@ -35015,6 +36817,16 @@ } } }, + "403": { + "description": "Insufficient permissions. AI query generation must be enabled for the organization and the caller must have permission to use AI on the job's model.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError403" + } + } + } + }, "404": { "description": "Job not found, not in COMPLETE state, or the apiAiVis feature flag is not enabled.", "content": { @@ -35451,7 +37263,7 @@ } }, "post": { - "description": "Create a routine that runs a saved prompt on a schedule and delivers the AI response through a single email destination. Each scheduled run executes once using the routine owner's permissions, and every recipient receives the same result. Organization API keys can pass `?userId=` to create the routine for a specific organization member.", + "description": "Create a routine that runs a saved prompt on a schedule and delivers the AI response through a single destination — email (one or more recipients / user groups) or Slack (a single channel or direct message). Each scheduled run executes once using the routine owner's permissions, and every recipient receives the same result. Organization API keys can pass `?userId=` to create the routine for a specific organization member.", "operationId": "routineCreate", "summary": "Create a routine", "tags": [ @@ -36254,6 +38066,14 @@ "items": { "type": "object", "properties": { + "allowBranchConnectionEnvironments": { + "type": [ + "boolean", + "null" + ], + "description": "Whether a branch may select its own connection environment. When user-attribute environment selection is also enabled, a branch selection overrides the user attribute.", + "example": false + }, "baseRole": { "type": [ "string", @@ -36267,7 +38087,8 @@ "boolean", "null" ], - "description": "Whether branch environments override user attributes", + "deprecated": true, + "description": "Deprecated alias for `allowBranchConnectionEnvironments`; same value. Use `allowBranchConnectionEnvironments` instead.", "example": false }, "createdAt": { @@ -36369,6 +38190,7 @@ } }, "required": [ + "allowBranchConnectionEnvironments", "baseRole", "branchConnectionEnvironmentOverridesUserAttr", "createdAt", @@ -36734,6 +38556,14 @@ "connection": { "type": "object", "properties": { + "allowBranchConnectionEnvironments": { + "type": [ + "boolean", + "null" + ], + "description": "Whether a branch may select its own connection environment. When user-attribute environment selection is also enabled, a branch selection overrides the user attribute.", + "example": false + }, "baseRole": { "type": [ "string", @@ -36747,7 +38577,8 @@ "boolean", "null" ], - "description": "Whether branch environments override user attributes", + "deprecated": true, + "description": "Deprecated alias for `allowBranchConnectionEnvironments`; same value. Use `allowBranchConnectionEnvironments` instead.", "example": false }, "createdAt": { @@ -36849,6 +38680,7 @@ } }, "required": [ + "allowBranchConnectionEnvironments", "baseRole", "branchConnectionEnvironmentOverridesUserAttr", "createdAt", @@ -40154,6 +41986,65 @@ } } }, + "/api/v1/documents/{identifier}/upgrade": { + "post": { + "description": "Upgrades a document to the advanced dashboard layout (the \"File > Upgrade layout\" UI action). No-ops when the document already has advanced layout. For published documents the upgrade goes through a draft/publish workflow automatically; if a draft already exists, the request returns 409 unless `clearExistingDraft` is set to `true`.", + "operationId": "documentsUpgradeLayout", + "summary": "Upgrade dashboard layout", + "tags": [ + "Documents" + ], + "parameters": [ + { + "schema": { + "type": "string", + "description": "Document identifier (either document ID or identifier slug)", + "example": "abc123" + }, + "required": true, + "description": "Document identifier (either document ID or identifier slug)", + "name": "identifier", + "in": "path" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DocumentsUpgradeLayoutBody" + } + } + } + }, + "responses": { + "200": { + "description": "Layout upgraded, or no-op if the document already had advanced layout", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DocumentsUpgradeLayoutResponse" + } + } + } + }, + "400": { + "description": "Document does not have a dashboard to upgrade" + }, + "401": { + "description": "Authentication required" + }, + "403": { + "description": "Permission denied" + }, + "404": { + "description": "Document not found" + }, + "409": { + "description": "A draft already exists for the published document; set clearExistingDraft to override" + } + } + } + }, "/api/v1/documents/{identifier}/favorite": { "put": { "operationId": "documentsAddFavorite",