diff --git a/api/openapi.json b/api/openapi.json index b83fb7c..28c20c3 100644 --- a/api/openapi.json +++ b/api/openapi.json @@ -15,6 +15,10 @@ "description": "AI-powered data analysis. Submit natural language questions as synchronous queries or asynchronous jobs, and retrieve results including generated queries, data, and summarized answers.", "name": "AI" }, + { + "description": "AI evaluation: manage prompt sets and runs used to score AI quality against curated prompt suites.", + "name": "AI Eval" + }, { "description": "API token management", "name": "API Tokens" @@ -118,407 +122,559 @@ "description": "Update an existing variable by ID. Variable names cannot be changed after creation.", "title": "DbtEnvironmentVariableUpdate" }, - "AiGenerateQueryResponse": { + "CompositeFilter": { "type": "object", "properties": { - "error": { - "type": [ - "object", - "null" - ], - "properties": { - "detail": { - "type": "string", - "description": "Detailed error message explaining why query generation failed.", - "example": "The AI was unable to generate a query for this prompt. Try rephrasing your question to be more specific about the data you want to retrieve." - }, - "message": { - "type": "string", - "description": "Short error summary.", - "example": "No query generated" - } - }, - "required": [ - "detail", - "message" - ], - "description": "Error details if query generation failed. Null on success." - }, - "query": { - "$ref": "#/components/schemas/AiSemanticQuery" - }, - "result": { - "type": "object", - "additionalProperties": {}, - "description": "Query execution results as a JSON object. Only present when runQuery is true (the default) and the query executed successfully. The structure contains the query result data." + "cancel_query_filter": { + "type": "boolean" }, - "topic": { - "type": "string", - "description": "The topic name that was used for query generation.", - "example": "order_items" + "ignore_if_unjoinable": { + "type": "boolean" }, - "workbookUrl": { + "conjunction": { "type": "string", - "format": "uri", - "description": "URL to view and edit the generated query in an Omni workbook. Only present when workbookUrl was set to true in the request.", - "example": "https://myorg.omni.co/w/abc123/1" - } - }, - "required": [ - "error", - "query" - ] - }, - "AiSemanticQuery": { - "type": [ - "object", - "null" - ], - "properties": { - "fields": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Ordered list of fully qualified field names to include in the query (e.g., \"view_name.field_name\").", - "example": [ - "products.name", - "order_items.total_revenue" + "enum": [ + "OR", + "AND" ] }, "filters": { - "type": "object", - "additionalProperties": {}, - "description": "Filter conditions keyed by fully qualified field name. Filter values vary by field type." - }, - "limit": { - "type": "integer", - "description": "Maximum number of rows to return.", - "example": 500 - }, - "sorts": { "type": "array", "items": { - "$ref": "#/components/schemas/AiQuerySort" - }, - "description": "Sort specifications applied to the query results." - }, - "table": { - "type": "string", - "description": "The base topic or view name for the query.", - "example": "order_items" - } - }, - "required": [ - "fields" - ], - "additionalProperties": {}, - "description": "The generated semantic query definition. Null if generation failed. This query can be passed directly to the POST /api/v1/query/run endpoint." - }, - "AiQuerySort": { - "type": "object", - "properties": { - "column_name": { - "type": "string", - "description": "Fully qualified field name to sort by (e.g., \"view_name.field_name\").", - "example": "order_items.total_revenue" - }, - "sort_descending": { - "type": "boolean", - "description": "Whether to sort in descending order.", - "example": true - } - }, - "required": [ - "column_name", - "sort_descending" - ] - }, - "ApiError400": { - "type": "object", - "properties": { - "detail": { - "type": "string", - "description": "Human-readable error message describing what went wrong.", - "example": "Bad Request: prompt: Required" - }, - "status": { - "type": "integer", - "description": "HTTP status code of the error.", - "example": 400 - } - }, - "required": [ - "detail", - "status" - ] - }, - "ApiError401": { - "type": "object", - "properties": { - "detail": { - "type": "string", - "description": "Human-readable error message describing what went wrong.", - "example": "Unauthorized: Missing or invalid API key" - }, - "status": { - "type": "integer", - "description": "HTTP status code of the error.", - "example": 401 - } - }, - "required": [ - "detail", - "status" - ] - }, - "ApiError403": { - "type": "object", - "properties": { - "detail": { - "type": "string", - "description": "Human-readable error message describing what went wrong.", - "example": "Forbidden: AI query generation is not enabled for this organization" - }, - "status": { - "type": "integer", - "description": "HTTP status code of the error.", - "example": 403 - } - }, - "required": [ - "detail", - "status" - ] - }, - "ApiError404": { - "type": "object", - "properties": { - "detail": { - "type": "string", - "description": "Human-readable error message describing what went wrong.", - "example": "Model 770e8400-e29b-41d4-a716-446655440002 not found" - }, - "status": { - "type": "integer", - "description": "HTTP status code of the error.", - "example": 404 - } - }, - "required": [ - "detail", - "status" - ] - }, - "AiGenerateQueryBody": { - "allOf": [ - { - "$ref": "#/components/schemas/AiTopicParams" - }, - { - "type": "object", - "properties": { - "prompt": { - "type": "string", - "description": "The natural language prompt describing the data you want to retrieve.", - "example": "Show me total revenue by month for the last year" - }, - "queryAllViews": { - "type": "boolean", - "description": "If true and the model has query_all_views_and_fields enabled, AI can query views not in any topic." - }, - "runQuery": { - "type": "boolean", - "description": "Whether to execute the generated query and return results. Defaults to true. Set to false to only generate the query definition without executing it.", - "example": true - }, - "userId": { - "type": "string", - "format": "uuid", - "description": "User ID to execute the query as. Their permissions will be applied for row-level security. Only valid with organization-scoped API keys. Personal access tokens always act as the authenticated user.", - "example": "990e8400-e29b-41d4-a716-446655440004" - }, - "workbookUrl": { - "type": "boolean", - "description": "If true, creates a new workbook with the generated query and returns its URL. Useful for sharing results or further exploration.", - "example": false - } - }, - "required": [ - "prompt" - ] - } - ] - }, - "AiTopicParams": { - "type": "object", - "properties": { - "branchId": { - "type": "string", - "format": "uuid", - "description": "Optional branch ID for the model. Must be a branch of the shared model specified by modelId.", - "example": "550e8400-e29b-41d4-a716-446655440000" - }, - "currentTopicName": { - "type": "string", - "description": "The name of the current topic to scope query generation. If not provided, AI will automatically select the best topic for your prompt.", - "example": "order_items" - }, - "modelId": { - "type": "string", - "format": "uuid", - "description": "The UUID of the shared model to query against. Only shared models are supported.", - "example": "770e8400-e29b-41d4-a716-446655440002" - } - }, - "required": [ - "modelId" - ] - }, - "AiPickTopicResponse": { - "type": "object", - "properties": { - "topicId": { - "type": "string", - "description": "The name of the topic that best matches the prompt. Use this as the topicName parameter when calling generate-query or submitting an AI job.", - "example": "order_items" + "anyOf": [ + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "case_insensitive": { + "type": "boolean" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "kind": { + "type": "string", + "enum": [ + "CONTAINS", + "ENDS_WITH", + "STARTS_WITH", + "EQUALS", + "IS_EMPTY", + "SQL_LIKE" + ] + }, + "type": { + "type": "string", + "enum": [ + "string" + ] + }, + "values": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "kind", + "type", + "values" + ] + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "is_inclusive": { + "type": "boolean" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "kind": { + "type": "string", + "enum": [ + "LESS_THAN", + "GREATER_THAN", + "EQUALS", + "BETWEEN" + ] + }, + "type": { + "type": "string", + "enum": [ + "number" + ] + }, + "values": { + "type": "array", + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + } + ] + } + } + }, + "required": [ + "kind", + "type", + "values" + ] + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "isFiscal": { + "type": "boolean" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "kind": { + "type": "string", + "enum": [ + "IS_ON_DAY_OF_WEEK", + "IS_ON_DAY_OF_QUARTER", + "IS_IN_MONTH_OF_YEAR", + "IS_ON_DAY_OF_YEAR", + "IS_AT_HOUR_OF_DAY", + "IS_IN_QUARTER_OF_YEAR", + "IS_IN_WEEK_OF_YEAR", + "IS_ON_DAY_OF_MONTH", + "BETWEEN", + "ON_OR_AFTER", + "BEFORE", + "TIME_FOR_INTERVAL_DURATION", + "TIME_FOR_UNIT_DURATION", + "QUERY_OFFSET" + ] + }, + "left_side": { + "type": [ + "string", + "null" + ] + }, + "offset_interval_string": { + "type": [ + "string", + "null" + ] + }, + "right_side": { + "type": [ + "string", + "null" + ] + }, + "type": { + "type": "string", + "enum": [ + "date" + ] + }, + "ui_type": { + "type": [ + "string", + "null" + ], + "enum": [ + "ANY_TIME", + "BEFORE", + "BETWEEN", + "MONTH_OF_YEAR", + "PAST", + "YEAR", + "DAY", + "IS_ON_DAY_OF_WEEK", + "ON_OR_AFTER", + "IS_IN_THE_MONTH", + "IS_IN_THE_QUARTER", + "IS_IN_THE_FISCAL_QUARTER", + "IS_IN_THE_FISCAL_YEAR", + "TIME_FOR_INTERVAL_DURATION", + "TIME_FOR_UNIT_DURATION", + "CUSTOM", + null + ] + } + }, + "required": [ + "kind", + "type" + ] + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "type": { + "type": "string", + "enum": [ + "null" + ] + } + }, + "required": [ + "type" + ] + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "treat_nulls_as_false": { + "type": "boolean" + }, + "type": { + "type": "string", + "enum": [ + "boolean" + ] + } + }, + "required": [ + "type" + ] + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "disregard_limit": { + "type": "boolean" + }, + "field_name": { + "type": "string" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "query_id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "query" + ] + }, + "view_query": { + "type": "object", + "properties": { + "fields": { + "type": "array", + "items": { + "type": "string" + } + }, + "filters": { + "type": "object", + "additionalProperties": {}, + "default": {} + }, + "limit": { + "type": "number" + }, + "sorts": { + "type": "array", + "items": {}, + "default": [] + }, + "table": { + "type": "string" + } + }, + "required": [ + "fields" + ], + "additionalProperties": {} + } + }, + "required": [ + "type" + ] + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "type": { + "type": "string", + "enum": [ + "user_attribute" + ] + }, + "user_attribute_name": { + "type": "string" + } + }, + "required": [ + "type", + "user_attribute_name" + ] + }, + { + "$ref": "#/components/schemas/CompositeFilter" + } + ] + }, + "description": "Child filters — each a simple filter or another composite filter. Recursive; see the dashboard-filters reference for the full grammar." + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "type": { + "type": "string", + "enum": [ + "composite" + ] } }, "required": [ - "topicId" + "conjunction", + "filters", + "type" ] }, - "AiPickTopicBody": { - "allOf": [ - { - "$ref": "#/components/schemas/AiTopicParams" - }, - { - "type": "object", - "properties": { - "potentialTopicNames": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Optional list of topic names to limit consideration to. If not provided, all topics the user has access to in the model will be evaluated.", - "example": [ - "order_items", - "customers", - "products" - ] - }, - "prompt": { + "AiGenerateQueryResponse": { + "type": "object", + "properties": { + "baseView": { + "type": [ + "string", + "null" + ], + "description": "The base view name used for query generation when queryAllViews surfaced a non-topic view. Mutually exclusive with `topic` — exactly one is non-null when a query was generated.", + "example": null + }, + "downgradedModelTier": { + "type": "string", + "description": "Present only when the organization is over its AI downgrade threshold, signaling the query was generated on a downgraded (cheaper) model tier (e.g. 'haiku') to conserve credits. Advisory and best-effort — the call still succeeds, and clients may surface that a downgraded model was used. Absent when no downgrade applied.", + "example": "haiku" + }, + "error": { + "type": [ + "object", + "null" + ], + "properties": { + "detail": { "type": "string", - "description": "The natural language prompt to analyze. The AI will determine which topic best matches the data described in this prompt.", - "example": "How many orders were placed last month?" + "description": "Detailed error message explaining why query generation failed.", + "example": "The AI was unable to generate a query for this prompt. Try rephrasing your question to be more specific about the data you want to retrieve." }, - "userId": { + "message": { "type": "string", - "format": "uuid", - "description": "User ID to evaluate topic access as. Their permissions will be used for permission-aware topic selection. Only valid with organization-scoped API keys. Personal access tokens always act as the authenticated user.", - "example": "990e8400-e29b-41d4-a716-446655440004" + "description": "Short error summary.", + "example": "No query generated" } }, "required": [ - "prompt" - ] + "detail", + "message" + ], + "description": "Error details if query generation failed. Null on success." + }, + "query": { + "$ref": "#/components/schemas/AiSemanticQuery" + }, + "result": { + "type": "object", + "additionalProperties": {}, + "description": "Query execution results as a JSON object. Only present when runQuery is true (the default) and the query executed successfully. The structure contains the query result data." + }, + "topic": { + "type": [ + "string", + "null" + ], + "description": "The topic name used for query generation. Mutually exclusive with `baseView` — exactly one is non-null when a query was generated.", + "example": "order_items" + }, + "workbookUrl": { + "type": "string", + "format": "uri", + "description": "URL to view and edit the generated query in an Omni workbook. Only present when workbookUrl was set to true in the request.", + "example": "https://myorg.omni.co/w/abc123/1" } + }, + "required": [ + "error", + "query" ] }, - "AiSearchOmniDocsResponse": { - "type": "object", + "AiSemanticQuery": { + "type": [ + "object", + "null" + ], "properties": { - "answer": { - "type": "string", - "description": "A synthesized answer to the question, based on the Omni documentation.", - "example": "To create a dashboard filter, navigate to your dashboard and click the \"Add Filter\" button..." + "fields": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Ordered list of fully qualified field names to include in the query (e.g., \"view_name.field_name\").", + "example": [ + "products.name", + "order_items.total_revenue" + ] }, - "sources": { + "filters": { + "type": "object", + "additionalProperties": {}, + "description": "Filter conditions keyed by fully qualified field name. Filter values vary by field type." + }, + "limit": { + "type": "integer", + "description": "Maximum number of rows to return.", + "example": 500 + }, + "sorts": { "type": "array", "items": { - "type": "object", - "properties": { - "title": { - "type": "string", - "description": "The title of the source documentation page.", - "example": "Dashboard Filters" - }, - "url": { - "type": "string", - "format": "uri", - "description": "URL of the source documentation page.", - "example": "https://docs.omni.co/docs/dashboards/filters" - } - }, - "required": [ - "title", - "url" - ] + "$ref": "#/components/schemas/AiQuerySort" }, - "description": "List of documentation pages that were used to synthesize the answer." + "description": "Sort specifications applied to the query results." + }, + "table": { + "type": "string", + "description": "The base topic or view name for the query.", + "example": "order_items" } }, "required": [ - "answer", - "sources" - ] + "fields" + ], + "additionalProperties": {}, + "description": "The generated semantic query definition. Null if generation failed. This query can be passed directly to the POST /api/v1/query/run endpoint." }, - "AiSearchOmniDocsBody": { + "AiQuerySort": { "type": "object", "properties": { - "question": { + "column_name": { "type": "string", - "minLength": 1, - "maxLength": 2000, - "description": "A natural language question about Omni features, configuration, modeling, dashboards, or other topics covered in the Omni documentation.", - "example": "How do I create a dashboard filter?" + "description": "Fully qualified field name to sort by (e.g., \"view_name.field_name\").", + "example": "order_items.total_revenue" + }, + "sort_descending": { + "type": "boolean", + "description": "Whether to sort in descending order.", + "example": true } }, "required": [ - "question" + "column_name", + "sort_descending" ] }, - "AiJobSubmitResponse": { + "ApiError400": { "type": "object", "properties": { - "conversationId": { - "type": "string", - "format": "uuid", - "description": "The conversation ID for this job. Pass this as conversationId in subsequent job submissions to continue the conversation with additional context.", - "example": "660e8400-e29b-41d4-a716-446655440001" - }, - "jobId": { + "detail": { "type": "string", - "format": "uuid", - "description": "The unique identifier for the created job. Use this to poll status via GET /api/v1/ai/jobs/{jobId} or retrieve results via GET /api/v1/ai/jobs/{jobId}/result.", - "example": "550e8400-e29b-41d4-a716-446655440000" + "description": "Human-readable error message describing what went wrong.", + "example": "Bad Request: prompt: Required" }, - "omniChatUrl": { - "type": "string", - "format": "uri", - "description": "URL to view this conversation in the Omni chat interface. Opens the chat session where the job actions and results are visible.", - "example": "https://my-org.omni.co/chat/660e8400-e29b-41d4-a716-446655440001" + "status": { + "type": "integer", + "description": "HTTP status code of the error.", + "example": 400 } }, "required": [ - "conversationId", - "jobId", - "omniChatUrl" + "detail", + "status" ] }, - "ApiError409": { + "ApiError401": { "type": "object", "properties": { "detail": { "type": "string", "description": "Human-readable error message describing what went wrong.", - "example": "An active job already exists for this conversation" + "example": "Unauthorized: Missing or invalid API key" }, "status": { "type": "integer", "description": "HTTP status code of the error.", - "example": 409 + "example": 401 } }, "required": [ @@ -526,845 +682,1021 @@ "status" ] }, - "AiJobSubmitBody": { + "AiCreditShutoffError": { "type": "object", "properties": { - "branchId": { - "type": "string", - "format": "uuid", - "description": "Optional branch ID for the model. Must be a branch of the shared model specified by modelId. Use this to query against in-progress model changes.", - "example": "550e8400-e29b-41d4-a716-446655440000" - }, - "conversationId": { - "type": "string", - "format": "uuid", - "description": "Conversation ID to continue an existing conversation thread. The AI will have access to the context from previous jobs in the same conversation. If omitted, a new conversation is created. Only one active job can exist per conversation.", - "example": "660e8400-e29b-41d4-a716-446655440001" - }, - "modelId": { - "type": "string", - "format": "uuid", - "description": "The UUID of the shared model to query against. Only shared models are supported.", - "example": "770e8400-e29b-41d4-a716-446655440002" - }, - "progressWebhookEnabled": { - "type": "boolean", - "default": false, - "description": "When true, real-time progress events are POSTed to webhookUrl during execution (e.g., \"Searching for revenue fields\", \"Query returned 42 rows\"). Requires webhookUrl. Progress events are best-effort: single attempt, no retries, failures do not affect job execution.", - "example": true - }, - "prompt": { - "type": "string", - "minLength": 1, - "description": "The natural language prompt for the AI to process. The AI will analyze your question, generate appropriate queries, execute them, and return a summarized answer.", - "example": "What are the top 5 products by revenue this quarter?" - }, - "topicName": { + "code": { "type": "string", - "maxLength": 256, - "description": "Topic name to scope query generation. Topics define a set of related views and their join paths. If not provided, the AI will automatically select the best topic. Use the pick-topic endpoint to determine the right topic programmatically.", - "example": "order_items" - }, - "webhookMetadata": { - "type": "object", - "additionalProperties": {}, - "description": "Arbitrary metadata object that will be included unchanged in webhook payloads. Use this to correlate webhook notifications with your own system (e.g., tracking IDs, channel references).", - "example": { - "externalId": "task-123", - "slackChannel": "C0123456789" - } + "enum": [ + "shutoff" + ], + "description": "Stable reason code identifying an AI-credit shutoff.", + "example": "shutoff" }, - "webhookSigningSecret": { + "detail": { "type": "string", - "description": "Secret key for HMAC-SHA256 webhook payload signing. When provided, each webhook request includes X-Omni-Signature and X-Omni-Signature-Timestamp headers for verification. Required if webhookUrl is specified." + "description": "Human-readable error message describing what went wrong.", + "example": "The AI agent is currently unavailable. Contact your administrator to re-enable." }, - "webhookUrl": { - "type": "string", - "format": "uri", - "description": "URL to receive webhook POSTs. Always receives a terminal event (job.complete or job.failed) when the job finishes. When progressWebhookEnabled is true, also receives real-time progress events during execution.", - "example": "https://example.com/webhooks/omni" + "status": { + "type": "integer", + "description": "HTTP status code of the error.", + "example": 402 } }, "required": [ - "modelId", - "prompt" + "code", + "detail", + "status" ] }, - "AiJobStatusResponse": { + "ApiError403": { "type": "object", "properties": { - "branchId": { - "type": [ - "string", - "null" - ], - "format": "uuid", - "description": "Branch ID used for model context, or null if querying the main shared model." - }, - "cancelledAt": { - "type": "string", - "format": "date-time", - "description": "When the job was cancelled. Only present in CANCELLED state.", - "example": "2025-01-15T10:00:12.000Z" - }, - "cancelledBy": { - "type": "string", - "format": "uuid", - "description": "User ID of who cancelled the job. Only present in CANCELLED state.", - "example": "990e8400-e29b-41d4-a716-446655440004" - }, - "completedAt": { + "detail": { "type": "string", - "format": "date-time", - "description": "When the job finished (successfully or with error). Present in COMPLETE and FAILED states.", - "example": "2025-01-15T10:01:30.000Z" + "description": "Human-readable error message describing what went wrong.", + "example": "Forbidden: AI query generation is not enabled for this organization" }, - "conversationId": { + "status": { + "type": "integer", + "description": "HTTP status code of the error.", + "example": 403 + } + }, + "required": [ + "detail", + "status" + ] + }, + "ApiError404": { + "type": "object", + "properties": { + "detail": { "type": "string", - "format": "uuid", - "description": "The conversation this job belongs to. Use this to submit follow-up jobs in the same conversation thread.", - "example": "660e8400-e29b-41d4-a716-446655440001" + "description": "Human-readable error message describing what went wrong.", + "example": "Model 770e8400-e29b-41d4-a716-446655440002 not found" }, - "createdAt": { - "type": "string", - "format": "date-time", - "description": "When the job was submitted.", - "example": "2025-01-15T10:00:00.000Z" + "status": { + "type": "integer", + "description": "HTTP status code of the error.", + "example": 404 + } + }, + "required": [ + "detail", + "status" + ] + }, + "AiGenerateQueryBody": { + "allOf": [ + { + "$ref": "#/components/schemas/AiTopicParams" }, - "error": { + { "type": "object", "properties": { - "code": { + "prompt": { "type": "string", - "description": "Machine-readable error code.", - "example": "QUERY_EXECUTION_ERROR" + "description": "The natural language prompt describing the data you want to retrieve.", + "example": "Show me total revenue by month for the last year" }, - "detail": { - "type": "string", - "description": "Additional error detail or context.", - "example": "The query timed out after 300 seconds" + "queryAllViews": { + "type": "boolean", + "description": "If true and the model has query_all_views_and_fields enabled, AI can query views not in any topic." }, - "message": { - "type": "string", - "description": "Human-readable error message.", - "example": "Column 'revenue' not found in table 'orders'" - } - }, - "required": [ - "message" - ], - "additionalProperties": {}, - "description": "Error details explaining why the job failed. Only present in FAILED state." - }, - "executionStartedAt": { - "type": "string", - "format": "date-time", - "description": "When execution began. Present once the job transitions from QUEUED to EXECUTING. May be absent on jobs that failed or were cancelled before execution started.", - "example": "2025-01-15T10:00:05.000Z" - }, - "id": { - "type": "string", - "format": "uuid", - "description": "The unique identifier for this job.", - "example": "550e8400-e29b-41d4-a716-446655440000" - }, - "modelId": { - "type": [ - "string", - "null" - ], - "format": "uuid", - "description": "The shared model ID used for query generation.", - "example": "770e8400-e29b-41d4-a716-446655440002" - }, - "omniChatUrl": { - "type": "string", - "format": "uri", - "description": "URL to view this conversation in the Omni chat interface. Opens the chat session where the job actions and results are visible.", - "example": "https://my-org.omni.co/chat/660e8400-e29b-41d4-a716-446655440001" - }, - "organizationId": { - "type": "string", - "format": "uuid", - "description": "The organization that owns this job.", - "example": "880e8400-e29b-41d4-a716-446655440003" - }, - "progress": { - "type": [ - "object", - "null" - ], - "properties": { - "iteration": { - "type": "integer", - "description": "Current iteration number. The AI may take multiple iterations to refine queries and generate a complete answer.", - "example": 2 + "runQuery": { + "type": "boolean", + "description": "Whether to execute the generated query and return results. Defaults to true. Set to false to only generate the query definition without executing it.", + "example": true }, - "message": { + "userId": { "type": "string", - "description": "Human-readable status message describing what the AI is currently doing.", - "example": "Running query: Top products by revenue" + "format": "uuid", + "description": "User ID to execute the query as. Their permissions will be applied for row-level security. Only valid with organization-scoped API keys. Personal access tokens always act as the authenticated user.", + "example": "990e8400-e29b-41d4-a716-446655440004" }, - "updatedAt": { - "type": "string", - "format": "date-time", - "description": "When this progress update was recorded.", - "example": "2025-01-15T10:00:08.000Z" + "workbookUrl": { + "type": "boolean", + "description": "If true, creates a new workbook with the generated query and returns its URL. Useful for sharing results or further exploration.", + "example": false } }, "required": [ - "iteration", - "message", - "updatedAt" - ], - "description": "Real-time progress information. Only present in EXECUTING state. Null if no progress has been reported yet. Updated in real-time as the AI works through iterations." - }, - "prompt": { - "type": "string", - "description": "The natural language prompt that was submitted.", - "example": "What are the top 5 products by revenue?" - }, - "resultSummary": { + "prompt" + ] + } + ] + }, + "AiTopicParams": { + "type": "object", + "properties": { + "branchId": { "type": "string", - "description": "Markdown-formatted summary of the job result. Only present in COMPLETE state. For the full result with query details and data, use GET /api/v1/ai/jobs/{jobId}/result.", - "example": "### Top 5 Products by Revenue\n\n1. **Sunglasses** - $678,994\n2. **Jeans** - $475,072" + "format": "uuid", + "description": "Optional branch ID for the model. Must be a branch of the shared model specified by modelId.", + "example": "550e8400-e29b-41d4-a716-446655440000" }, - "state": { + "currentTopicName": { "type": "string", - "enum": [ - "CANCELLED", - "COMPLETE", - "DELIVERING", - "EXECUTING", - "FAILED", - "QUEUED" - ], - "description": "Current state of the job. Terminal states are COMPLETE, FAILED, and CANCELLED. Poll until the job reaches a terminal state.", - "example": "QUEUED" - }, - "topicName": { - "type": [ - "string", - "null" - ], - "description": "Topic name used to scope query generation, or null if the AI selected the topic automatically.", + "description": "The name of the current topic to scope query generation. If not provided, AI will automatically select the best topic for your prompt.", "example": "order_items" }, - "updatedAt": { - "type": "string", - "format": "date-time", - "description": "When the job record was last modified.", - "example": "2025-01-15T10:00:05.000Z" - }, - "userId": { + "modelId": { "type": "string", "format": "uuid", - "description": "The user ID who created (or is associated with) this job.", - "example": "990e8400-e29b-41d4-a716-446655440004" + "description": "The UUID of the shared model to query against. Only shared models are supported.", + "example": "770e8400-e29b-41d4-a716-446655440002" } }, "required": [ - "branchId", - "conversationId", - "createdAt", - "id", - "modelId", - "omniChatUrl", - "organizationId", - "prompt", - "state", - "topicName", - "updatedAt", - "userId" + "modelId" ] }, - "AiJobCancelResponse": { + "AiPickTopicResponse": { "type": "object", "properties": { - "jobId": { - "type": "string", - "format": "uuid", - "description": "The job ID that was requested to cancel.", - "example": "550e8400-e29b-41d4-a716-446655440000" - }, - "state": { + "topicId": { "type": "string", - "enum": [ - "CANCELLED", - "COMPLETE", - "DELIVERING", - "EXECUTING", - "FAILED", - "QUEUED" - ], - "description": "The job state after the cancellation attempt. CANCELLED if the cancellation was successful. If the job was already in a terminal state (COMPLETE, FAILED, CANCELLED), the current state is returned unchanged — the endpoint is idempotent.", - "example": "CANCELLED" + "description": "The name of the topic that best matches the prompt. Use this as the topicName parameter when calling generate-query or submitting an AI job.", + "example": "order_items" } }, "required": [ - "jobId", - "state" + "topicId" ] }, - "AiJobResultResponse": { - "type": "object", - "properties": { - "actions": { - "type": "array", + "AiPickTopicBody": { + "allOf": [ + { + "$ref": "#/components/schemas/AiTopicParams" + }, + { + "type": "object", + "properties": { + "potentialTopicNames": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Optional list of topic names to limit consideration to. If not provided, all topics the user has access to in the model will be evaluated.", + "example": [ + "order_items", + "customers", + "products" + ] + }, + "prompt": { + "type": "string", + "description": "The natural language prompt to analyze. The AI will determine which topic best matches the data described in this prompt.", + "example": "How many orders were placed last month?" + }, + "userId": { + "type": "string", + "format": "uuid", + "description": "User ID to evaluate topic access as. Their permissions will be used for permission-aware topic selection. Only valid with organization-scoped API keys. Personal access tokens always act as the authenticated user.", + "example": "990e8400-e29b-41d4-a716-446655440004" + } + }, + "required": [ + "prompt" + ] + } + ] + }, + "AiSearchOmniDocsResponse": { + "type": "object", + "properties": { + "answer": { + "type": "string", + "description": "A synthesized answer to the question, based on the Omni documentation.", + "example": "To create a dashboard filter, navigate to your dashboard and click the \"Add Filter\" button..." + }, + "sources": { + "type": "array", "items": { - "$ref": "#/components/schemas/AiJobAction" + "type": "object", + "properties": { + "title": { + "type": "string", + "description": "The title of the source documentation page.", + "example": "Dashboard Filters" + }, + "url": { + "type": "string", + "format": "uri", + "description": "URL of the source documentation page.", + "example": "https://docs.omni.co/docs/dashboards/filters" + } + }, + "required": [ + "title", + "url" + ] }, - "description": "Ordered list of actions the AI took during execution. Each action represents a step such as generating a query, executing it, or synthesizing a final answer." + "description": "List of documentation pages that were used to synthesize the answer." + } + }, + "required": [ + "answer", + "sources" + ] + }, + "AiSearchOmniDocsBody": { + "type": "object", + "properties": { + "question": { + "type": "string", + "minLength": 1, + "maxLength": 2000, + "description": "A natural language question about Omni features, configuration, modeling, dashboards, or other topics covered in the Omni documentation.", + "example": "How do I create a dashboard filter?" + } + }, + "required": [ + "question" + ] + }, + "AiJobSubmitResponse": { + "type": "object", + "properties": { + "conversationId": { + "type": "string", + "format": "uuid", + "description": "The conversation ID for this job. Pass this as conversationId in subsequent job submissions to continue the conversation with additional context.", + "example": "660e8400-e29b-41d4-a716-446655440001" }, - "message": { + "jobId": { "type": "string", - "description": "The AI's final response message in Markdown format. This is the complete answer to the original prompt, incorporating data from all executed queries.", - "example": "### Top 5 Products by Revenue\n\n1. **Sunglasses** - $678,994\n2. **Jeans** - $475,072" + "format": "uuid", + "description": "The unique identifier for the created job. Use this to poll status via GET /api/v1/ai/jobs/{jobId} or retrieve results via GET /api/v1/ai/jobs/{jobId}/result.", + "example": "550e8400-e29b-41d4-a716-446655440000" }, "omniChatUrl": { "type": "string", "format": "uri", "description": "URL to view this conversation in the Omni chat interface. Opens the chat session where the job actions and results are visible.", "example": "https://my-org.omni.co/chat/660e8400-e29b-41d4-a716-446655440001" - }, - "resultSummary": { - "type": "string", - "description": "Summary of the job result. Typically matches the final message content.", - "example": "### Top 5 Products by Revenue\n\n1. **Sunglasses** - $678,994\n2. **Jeans** - $475,072" - }, - "topic": { - "type": "string", - "description": "The topic name used for query generation.", - "example": "order_items" } }, - "additionalProperties": {} + "required": [ + "conversationId", + "jobId", + "omniChatUrl" + ] }, - "AiJobAction": { + "ApiError409": { "type": "object", "properties": { - "message": { - "type": "string", - "description": "The AI's explanation of what it is doing in this step, written in natural language.", - "example": "I'll generate a query to find the top 5 products by total revenue." - }, - "result": { - "$ref": "#/components/schemas/AiJobActionQueryResult" - }, - "timestamp": { + "detail": { "type": "string", - "description": "ISO 8601 timestamp when this action occurred.", - "example": "2025-01-15T10:00:10.000Z" + "description": "Human-readable error message describing what went wrong.", + "example": "An active job already exists for this conversation" }, - "type": { - "type": "string", - "description": "The type of action. Common types include \"generate_query\" (query generation and execution) and \"summarize\" (final answer synthesis).", - "example": "generate_query" + "status": { + "type": "integer", + "description": "HTTP status code of the error.", + "example": 409 } }, "required": [ - "message", - "timestamp", - "type" - ], - "additionalProperties": {} + "detail", + "status" + ] }, - "AiJobActionQueryResult": { + "AiJobSubmitBody": { "type": "object", "properties": { - "csvResult": { + "branchId": { "type": "string", - "description": "Query results formatted as CSV text.", - "example": "Name,Total Revenue\nRay-Ban Sunglasses,\"678,994.41\"\nLevi's 501 Jeans,\"475,072.00\"" + "format": "uuid", + "description": "Optional branch ID for the model. Must be a branch of the shared model specified by modelId. Use this to query against in-progress model changes.", + "example": "550e8400-e29b-41d4-a716-446655440000" }, - "csvResultWasTruncated": { - "type": "boolean", - "description": "Whether the CSV data was truncated due to size limits. If true, the full result set may contain additional rows not included in csvResult.", - "example": false + "conversationId": { + "type": "string", + "format": "uuid", + "description": "Conversation ID to continue an existing conversation thread. The AI will have access to the context from previous jobs in the same conversation. If omitted, a new conversation is created. Only one active job can exist per conversation.", + "example": "660e8400-e29b-41d4-a716-446655440001" }, - "hasResults": { + "modelId": { + "type": "string", + "format": "uuid", + "description": "The UUID of the shared model to query against. Only shared models are supported.", + "example": "770e8400-e29b-41d4-a716-446655440002" + }, + "progressWebhookEnabled": { "type": "boolean", - "description": "Whether the query returned any data rows.", + "default": false, + "description": "When true, real-time progress events are POSTed to webhookUrl during execution (e.g., \"Searching for revenue fields\", \"Query returned 42 rows\"). Requires webhookUrl. Progress events are best-effort: single attempt, no retries, failures do not affect job execution.", "example": true }, - "query": { - "type": "object", - "additionalProperties": {}, - "description": "The semantic query definition that was executed. This can be used with the POST /api/v1/query/run endpoint to re-run the query." + "prompt": { + "type": "string", + "minLength": 1, + "description": "The natural language prompt for the AI to process. The AI will analyze your question, generate appropriate queries, execute them, and return a summarized answer.", + "example": "What are the top 5 products by revenue this quarter?" }, - "queryName": { + "topicName": { "type": "string", - "description": "Human-readable name describing what this query retrieves.", - "example": "Top 5 Products by Revenue" + "maxLength": 256, + "description": "Topic name to scope query generation. Topics define a set of related views and their join paths. If not provided, the AI will automatically select the best topic. Use the pick-topic endpoint to determine the right topic programmatically.", + "example": "order_items" }, - "status": { + "webhookMetadata": { + "type": "object", + "additionalProperties": {}, + "description": "Arbitrary metadata object that will be included unchanged in webhook payloads. Use this to correlate webhook notifications with your own system (e.g., tracking IDs, channel references).", + "example": { + "externalId": "task-123", + "slackChannel": "C0123456789" + } + }, + "webhookSigningSecret": { "type": "string", - "enum": [ - "success", - "error" - ], - "description": "Whether the query executed successfully.", - "example": "success" + "description": "Secret key for HMAC-SHA256 webhook payload signing. When provided, each webhook request includes X-Omni-Signature and X-Omni-Signature-Timestamp headers for verification. Required if webhookUrl is specified." }, - "totalRowCount": { - "type": "integer", - "description": "Total number of rows returned by the query.", - "example": 5 - } - }, - "required": [ - "csvResult", - "csvResultWasTruncated", - "hasResults", - "query", - "queryName", - "status", - "totalRowCount" - ], - "description": "Query result data. Only present for generate_query action types." - }, - "ApiError422": { - "type": "object", - "properties": { - "error": { + "webhookUrl": { "type": "string", - "description": "Human-readable error message describing what went wrong.", - "example": "No Arrow IPC data available for visualization" + "format": "uri", + "description": "URL to receive webhook POSTs. Always receives a terminal event (job.complete or job.failed) when the job finishes. When progressWebhookEnabled is true, also receives real-time progress events during execution.", + "example": "https://example.com/webhooks/omni" } }, "required": [ - "error" + "modelId", + "prompt" ] }, - "ApiKeyListResponse": { + "AiJobStatusResponse": { "type": "object", "properties": { - "pageInfo": { - "$ref": "#/components/schemas/PageInfo" - }, - "records": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ApiKey" - } - } - }, - "required": [ - "pageInfo", - "records" - ] - }, - "PageInfo": { - "type": "object", - "properties": { - "hasNextPage": { - "type": "boolean", - "description": "Whether more results are available" - }, - "nextCursor": { + "branchId": { "type": [ "string", "null" ], - "description": "Cursor for fetching the next page" + "format": "uuid", + "description": "Branch ID used for model context, or null if querying the main shared model." }, - "pageSize": { - "type": "number", - "description": "Number of results per page" + "cancelledAt": { + "type": "string", + "format": "date-time", + "description": "When the job was cancelled. Only present in CANCELLED state.", + "example": "2025-01-15T10:00:12.000Z" + }, + "cancelledBy": { + "type": "string", + "format": "uuid", + "description": "User ID of who cancelled the job. Only present in CANCELLED state.", + "example": "990e8400-e29b-41d4-a716-446655440004" + }, + "completedAt": { + "type": "string", + "format": "date-time", + "description": "When the job finished (successfully or with error). Present in COMPLETE and FAILED states.", + "example": "2025-01-15T10:01:30.000Z" + }, + "conversationId": { + "type": "string", + "format": "uuid", + "description": "The conversation this job belongs to. Use this to submit follow-up jobs in the same conversation thread.", + "example": "660e8400-e29b-41d4-a716-446655440001" }, - "totalRecords": { - "type": "number", - "description": "Total number of records matching the query" - } - }, - "required": [ - "hasNextPage", - "nextCursor", - "pageSize", - "totalRecords" - ] - }, - "ApiKey": { - "type": "object", - "properties": { "createdAt": { "type": "string", "format": "date-time", - "description": "ISO 8601 timestamp of when the token was created", - "example": "2026-01-15T10:00:00.000Z" + "description": "When the job was submitted.", + "example": "2025-01-15T10:00:00.000Z" }, - "enabled": { - "type": "boolean", - "description": "Whether the token can currently authenticate. Organization tokens may be disabled by admins; personal and MCP tokens are always `true` (revocation deletes them).", - "example": true + "error": { + "type": "object", + "properties": { + "code": { + "type": "string", + "description": "Machine-readable error code.", + "example": "QUERY_EXECUTION_ERROR" + }, + "detail": { + "type": "string", + "description": "Additional error detail or context.", + "example": "The query timed out after 300 seconds" + }, + "message": { + "type": "string", + "description": "Human-readable error message.", + "example": "Column 'revenue' not found in table 'orders'" + } + }, + "required": [ + "message" + ], + "additionalProperties": {}, + "description": "Error details explaining why the job failed. Only present in FAILED state." + }, + "executionStartedAt": { + "type": "string", + "format": "date-time", + "description": "When execution began. Present once the job transitions from QUEUED to EXECUTING. May be absent on jobs that failed or were cancelled before execution started.", + "example": "2025-01-15T10:00:05.000Z" }, "id": { "type": "string", "format": "uuid", - "description": "Unique identifier for the token", - "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" + "description": "The unique identifier for this job.", + "example": "550e8400-e29b-41d4-a716-446655440000" }, - "membershipId": { + "modelId": { "type": [ "string", "null" ], "format": "uuid", - "description": "Membership ID of the user the token is scoped to. Null for organization-level tokens.", - "example": "b2c3d4e5-f6a7-8901-bcde-f12345678901" + "description": "The shared model ID used for query generation.", + "example": "770e8400-e29b-41d4-a716-446655440002" }, - "name": { + "omniChatUrl": { "type": "string", - "description": "Human-readable name for the token", - "example": "CI deployment key" + "format": "uri", + "description": "URL to view this conversation in the Omni chat interface. Opens the chat session where the job actions and results are visible.", + "example": "https://my-org.omni.co/chat/660e8400-e29b-41d4-a716-446655440001" }, - "type": { + "organizationId": { + "type": "string", + "format": "uuid", + "description": "The organization that owns this job.", + "example": "880e8400-e29b-41d4-a716-446655440003" + }, + "progress": { + "type": [ + "object", + "null" + ], + "properties": { + "iteration": { + "type": "integer", + "description": "Current iteration number. The AI may take multiple iterations to refine queries and generate a complete answer.", + "example": 2 + }, + "message": { + "type": "string", + "description": "Human-readable status message describing what the AI is currently doing.", + "example": "Running query: Top products by revenue" + }, + "updatedAt": { + "type": "string", + "format": "date-time", + "description": "When this progress update was recorded.", + "example": "2025-01-15T10:00:08.000Z" + } + }, + "required": [ + "iteration", + "message", + "updatedAt" + ], + "description": "Real-time progress information. Only present in EXECUTING state. Null if no progress has been reported yet. Updated in real-time as the AI works through iterations." + }, + "prompt": { + "type": "string", + "description": "The natural language prompt that was submitted.", + "example": "What are the top 5 products by revenue?" + }, + "resultSummary": { + "type": "string", + "description": "Markdown-formatted summary of the job result. Only present in COMPLETE state. For the full result with query details and data, use GET /api/v1/ai/jobs/{jobId}/result.", + "example": "### Top 5 Products by Revenue\n\n1. **Sunglasses** - $678,994\n2. **Jeans** - $475,072" + }, + "state": { "type": "string", "enum": [ - "organization", - "personal", - "mcp" + "CANCELLED", + "COMPLETE", + "DELIVERING", + "EXECUTING", + "FAILED", + "QUEUED" ], - "description": "Token type: `organization` (org-level), `personal` (user-created personal access token), or `mcp` (MCP OAuth grant).", - "example": "organization" + "description": "Current state of the job. Terminal states are COMPLETE, FAILED, and CANCELLED. Poll until the job reaches a terminal state.", + "example": "QUEUED" + }, + "topicName": { + "type": [ + "string", + "null" + ], + "description": "Topic name used to scope query generation, or null if the AI selected the topic automatically.", + "example": "order_items" + }, + "updatedAt": { + "type": "string", + "format": "date-time", + "description": "When the job record was last modified.", + "example": "2025-01-15T10:00:05.000Z" + }, + "userId": { + "type": "string", + "format": "uuid", + "description": "The user ID who created (or is associated with) this job.", + "example": "990e8400-e29b-41d4-a716-446655440004" } }, "required": [ + "branchId", + "conversationId", "createdAt", - "enabled", "id", - "membershipId", - "name", - "type" + "modelId", + "omniChatUrl", + "organizationId", + "prompt", + "state", + "topicName", + "updatedAt", + "userId" ] }, - "ApiKeyUpdateBody": { - "type": "object", - "properties": { - "enabled": { - "type": "boolean", - "description": "Set to `false` to disable the token, `true` to re-enable it. Only organization-level tokens may be disabled; personal and MCP tokens do not support this.", - "example": false - } - }, - "required": [ - "enabled" - ], - "additionalProperties": false - }, - "ApiKeyDeleteResponse": { + "AiJobCancelResponse": { "type": "object", "properties": { - "message": { + "jobId": { "type": "string", - "description": "Human-readable description of the outcome", - "example": "API token revoked" + "format": "uuid", + "description": "The job ID that was requested to cancel.", + "example": "550e8400-e29b-41d4-a716-446655440000" }, - "success": { - "type": "boolean", + "state": { + "type": "string", "enum": [ - true + "CANCELLED", + "COMPLETE", + "DELIVERING", + "EXECUTING", + "FAILED", + "QUEUED" ], - "description": "Always `true` on a successful revocation" + "description": "The job state after the cancellation attempt. CANCELLED if the cancellation was successful. If the job was already in a terminal state (COMPLETE, FAILED, CANCELLED), the current state is returned unchanged — the endpoint is idempotent.", + "example": "CANCELLED" } }, "required": [ - "message", - "success" + "jobId", + "state" ] }, - "DbtEnvironmentListResponse": { + "AiJobResultResponse": { "type": "object", "properties": { - "pageInfo": { - "$ref": "#/components/schemas/PageInfo" - }, - "records": { + "actions": { "type": "array", "items": { - "$ref": "#/components/schemas/DbtEnvironmentItem" - } + "$ref": "#/components/schemas/AiJobAction" + }, + "description": "Ordered list of actions the AI took during execution. Each action represents a step such as generating a query, executing it, or synthesizing a final answer." + }, + "message": { + "type": "string", + "description": "The AI's final response message in Markdown format. This is the complete answer to the original prompt, incorporating data from all executed queries.", + "example": "### Top 5 Products by Revenue\n\n1. **Sunglasses** - $678,994\n2. **Jeans** - $475,072" + }, + "omniChatUrl": { + "type": "string", + "format": "uri", + "description": "URL to view this conversation in the Omni chat interface. Opens the chat session where the job actions and results are visible.", + "example": "https://my-org.omni.co/chat/660e8400-e29b-41d4-a716-446655440001" + }, + "resultSummary": { + "type": "string", + "description": "Summary of the job result. Typically matches the final message content.", + "example": "### Top 5 Products by Revenue\n\n1. **Sunglasses** - $678,994\n2. **Jeans** - $475,072" + }, + "topic": { + "type": "string", + "description": "The topic name used for query generation.", + "example": "order_items" + } + }, + "additionalProperties": {} + }, + "AiJobAction": { + "type": "object", + "properties": { + "message": { + "type": "string", + "description": "The AI's explanation of what it is doing in this step, written in natural language.", + "example": "I'll generate a query to find the top 5 products by total revenue." + }, + "result": { + "$ref": "#/components/schemas/AiJobActionQueryResult" + }, + "timestamp": { + "type": "string", + "description": "ISO 8601 timestamp when this action occurred.", + "example": "2025-01-15T10:00:10.000Z" + }, + "type": { + "type": "string", + "description": "The type of action. Common types include \"generate_query\" (query generation and execution) and \"summarize\" (final answer synthesis).", + "example": "generate_query" } }, "required": [ - "pageInfo", - "records" - ] + "message", + "timestamp", + "type" + ], + "additionalProperties": {} }, - "DbtEnvironmentItem": { + "AiJobActionQueryResult": { "type": "object", "properties": { - "id": { + "csvResult": { "type": "string", - "format": "uuid", - "description": "Unique environment identifier" + "description": "Query results formatted as CSV text.", + "example": "Name,Total Revenue\nRay-Ban Sunglasses,\"678,994.41\"\nLevi's 501 Jeans,\"475,072.00\"" }, - "isDefaultEnvironment": { + "csvResultWasTruncated": { "type": "boolean", - "description": "Whether this is the default environment" + "description": "Whether the CSV data was truncated due to size limits. If true, the full result set may contain additional rows not included in csvResult.", + "example": false }, - "name": { + "hasResults": { + "type": "boolean", + "description": "Whether the query returned any data rows.", + "example": true + }, + "query": { + "type": "object", + "additionalProperties": {}, + "description": "The semantic query definition that was executed. This can be used with the POST /api/v1/query/run endpoint to re-run the query." + }, + "queryName": { "type": "string", - "description": "Environment name" + "description": "Human-readable name describing what this query retrieves.", + "example": "Top 5 Products by Revenue" }, - "ownerId": { - "type": [ - "string", - "null" + "status": { + "type": "string", + "enum": [ + "success", + "error" ], - "description": "User ID of the environment owner, or null if not a personal environment" + "description": "Whether the query executed successfully.", + "example": "success" }, - "targetDatabase": { - "type": [ - "string", - "null" - ], - "description": "Target database override" + "totalRowCount": { + "type": "integer", + "description": "Total number of rows returned by the query.", + "example": 5 + } + }, + "required": [ + "csvResult", + "csvResultWasTruncated", + "hasResults", + "query", + "queryName", + "status", + "totalRowCount" + ], + "description": "Query result data. Only present for generate_query action types." + }, + "ApiError422": { + "type": "object", + "properties": { + "error": { + "type": "string", + "description": "Human-readable error message describing what went wrong.", + "example": "No Arrow IPC data available for visualization" + } + }, + "required": [ + "error" + ] + }, + "AiBrandingResponse": { + "type": "object", + "properties": { + "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." }, - "targetName": { - "type": [ - "string", - "null" - ], - "description": "Target name override" + "headline": { + "type": "string", + "description": "Short headline shown on AI helper landing surfaces.", + "example": "What would you like to know?" }, - "targetRole": { + "logoUrl": { "type": [ "string", "null" ], - "description": "Target role override" + "format": "uri", + "description": "Absolute URL to a custom AI helper logo. `null` when the org has not configured a custom logo — clients should render their default avatar (e.g. Blobby).", + "example": "https://example.com/blobby.png" }, - "targetSchema": { + "name": { "type": "string", - "description": "Target schema" + "description": "Display name for the AI helper. Defaults to `Omni Agent` when no custom branding is set.", + "example": "Blobby" }, - "variables": { + "placeholder": { + "type": "string", + "description": "Placeholder text for the AI helper's prompt input.", + "example": "Ask a question about your data..." + } + }, + "required": [ + "body", + "headline", + "logoUrl", + "name", + "placeholder" + ] + }, + "AiConversationsListResponse": { + "type": "object", + "properties": { + "pageInfo": { + "$ref": "#/components/schemas/PageInfo" + }, + "records": { "type": "array", "items": { - "$ref": "#/components/schemas/DbtEnvironmentResponseVariable" + "$ref": "#/components/schemas/AiConversation" }, - "description": "Environment variables" + "description": "Conversations ordered by updatedAt descending." } }, "required": [ - "id", - "isDefaultEnvironment", - "name", - "ownerId", - "targetDatabase", - "targetName", - "targetRole", - "targetSchema", - "variables" + "pageInfo", + "records" ] }, - "DbtEnvironmentResponseVariable": { + "PageInfo": { "type": "object", "properties": { - "id": { - "type": "string", - "format": "uuid", - "description": "Variable ID" - }, - "isSecret": { + "hasNextPage": { "type": "boolean", - "description": "Whether the variable value is secret" - }, - "name": { - "type": "string", - "description": "Variable name" + "description": "Whether more results are available" }, - "value": { + "nextCursor": { "type": [ "string", "null" ], - "description": "Variable value (null for secret variables)" + "description": "Cursor for fetching the next page" + }, + "pageSize": { + "type": "number", + "description": "Number of results per page" + }, + "totalRecords": { + "type": "number", + "description": "Total number of records matching the query" } }, "required": [ - "id", - "isSecret", - "name", - "value" + "hasNextPage", + "nextCursor", + "pageSize", + "totalRecords" ] }, - "DbtEnvironmentCreateBody": { + "AiConversation": { "type": "object", "properties": { - "name": { + "createdAt": { "type": "string", - "minLength": 1, - "description": "Environment name", - "example": "PR_1111_Expose" - }, - "ownerId": { - "type": [ - "string", - "null" - ], - "default": null, - "description": "User ID of the environment owner. Used to mark development environments belonging to a specific user.", - "example": null + "format": "date-time", + "description": "When the conversation was started.", + "example": "2025-01-15T10:00:00.000Z" }, - "targetDatabase": { - "type": [ - "string", - "null" - ], - "default": null, - "description": "Target database override", - "example": "analytics_dev" + "id": { + "type": "string", + "format": "uuid", + "description": "Conversation ID. Pass as conversationId on subsequent /api/v1/ai/jobs submissions to continue this conversation.", + "example": "660e8400-e29b-41d4-a716-446655440001" }, - "targetName": { + "lastPrompt": { "type": [ "string", "null" ], - "default": null, - "description": "Target name override", - "example": null + "description": "The most recent user prompt in this conversation, useful for displaying a one-line summary in a list.", + "example": "What were our top products last week?" }, - "targetRole": { + "name": { "type": [ "string", "null" ], - "default": null, - "description": "Target role override", - "example": null + "description": "Conversation title. Set by the AI after the first turn; null on brand-new sessions.", + "example": "Top products last week" }, - "targetSchema": { + "updatedAt": { "type": "string", - "minLength": 1, - "description": "Target schema for this environment", - "example": "PR_1111_Expose" - }, - "variables": { - "type": "array", - "items": { - "$ref": "#/components/schemas/DbtEnvironmentVariable" - }, - "default": [], - "description": "Environment variables" + "format": "date-time", + "description": "When the conversation was last touched (most recent prompt or AI activity).", + "example": "2025-01-15T10:01:30.000Z" } }, "required": [ + "createdAt", + "id", + "lastPrompt", "name", - "targetSchema" + "updatedAt" ] }, - "DbtEnvironmentVariable": { + "AiConversationDetailResponse": { "type": "object", "properties": { - "isSecret": { - "type": "boolean", - "description": "Whether the variable value is secret" + "createdAt": { + "type": "string", + "format": "date-time" }, - "name": { + "id": { "type": "string", - "minLength": 1, - "description": "Variable name" + "format": "uuid" }, - "value": { + "messages": { + "type": "array", + "items": { + "$ref": "#/components/schemas/AiConversationMessage" + }, + "description": "Messages in chronological order. Alternating user / assistant turns." + }, + "name": { + "type": [ + "string", + "null" + ] + }, + "updatedAt": { "type": "string", - "description": "Variable value" + "format": "date-time" } }, "required": [ - "isSecret", + "createdAt", + "id", + "messages", "name", - "value" + "updatedAt" ] }, - "DbtEnvironmentUpdateBody": { + "AiConversationMessage": { "type": "object", "properties": { - "name": { + "createdAt": { "type": "string", - "minLength": 1, - "description": "Environment name", - "example": "PR_1111_Expose" + "format": "date-time", + "description": "When this turn was recorded.", + "example": "2025-01-15T10:00:00.000Z" }, - "ownerId": { + "jobId": { "type": [ "string", "null" ], - "default": null, - "description": "User ID of the environment owner. Used to mark development environments belonging to a specific user.", - "example": null + "format": "uuid", + "description": "The agentic job that produced this assistant turn. Only set for assistant messages — clients use it to fetch the rendered chart via GET /api/v1/ai/jobs/{jobId}/vis. Null when the turn predates jobs or when we could not associate one.", + "example": "550e8400-e29b-41d4-a716-446655440000" }, - "targetDatabase": { + "omniChatUrl": { "type": [ "string", "null" ], - "default": null, - "description": "Target database override", - "example": "analytics_dev" + "format": "uri", + "description": "Deep link to the assistant turn in the Omni chat UI. Null for user turns, and for assistant turns produced outside the Agentic API (where no AgenticJob row exists).", + "example": "https://my-org.omni.co/chat/660e8400-e29b-41d4-a716-446655440001" }, - "targetName": { - "type": [ - "string", - "null" + "role": { + "type": "string", + "enum": [ + "user", + "assistant" ], - "default": null, - "description": "Target name override", - "example": null + "description": "Speaker — `user` for prompts the user submitted, `assistant` for Blobby's responses.", + "example": "user" }, - "targetRole": { + "text": { + "type": "string", + "description": "Markdown content of the message. For assistant turns this is the same string returned by /api/v1/ai/jobs/{jobId}/result#message.", + "example": "What were our top products last week?" + } + }, + "required": [ + "createdAt", + "jobId", + "omniChatUrl", + "role", + "text" + ] + }, + "ApiKeyListResponse": { + "type": "object", + "properties": { + "pageInfo": { + "$ref": "#/components/schemas/PageInfo" + }, + "records": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ApiKey" + } + } + }, + "required": [ + "pageInfo", + "records" + ] + }, + "ApiKey": { + "type": "object", + "properties": { + "createdAt": { + "type": "string", + "format": "date-time", + "description": "ISO 8601 timestamp of when the token was created", + "example": "2026-01-15T10:00:00.000Z" + }, + "enabled": { + "type": "boolean", + "description": "Whether the token can currently authenticate. A disabled token cannot authenticate but remains visible until deleted.", + "example": true + }, + "id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the token", + "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" + }, + "membershipId": { "type": [ "string", "null" ], - "default": null, - "description": "Target role override", - "example": null + "format": "uuid", + "description": "Membership ID of the user the token is scoped to. Null for organization-level tokens.", + "example": "b2c3d4e5-f6a7-8901-bcde-f12345678901" }, - "targetSchema": { + "name": { "type": "string", - "minLength": 1, - "description": "Target schema for this environment", - "example": "PR_1111_Expose" + "description": "Human-readable name for the token", + "example": "CI deployment key" }, - "variables": { - "type": "array", - "items": { - "$ref": "#/components/schemas/DbtEnvironmentVariableUpdateOrNew" - }, - "default": [], - "description": "Environment variables. Variables with an id update existing ones; variables without an id create new ones." + "type": { + "type": "string", + "enum": [ + "organization", + "personal", + "mcp" + ], + "description": "Token type: `organization` (org-level), `personal` (user-created personal access token), or `mcp` (MCP OAuth grant).", + "example": "organization" } }, "required": [ + "createdAt", + "enabled", + "id", + "membershipId", "name", - "targetSchema" + "type" ] }, - "DbtEnvironmentVariableUpdateOrNew": { - "oneOf": [ - { - "$ref": "#/components/schemas/DbtEnvironmentVariableUpdate" - }, - { - "$ref": "#/components/schemas/DbtEnvironmentVariable" + "ApiKeyUpdateBody": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "description": "Set to `false` to disable the token, `true` to re-enable it.", + "example": false } - ] + }, + "required": [ + "enabled" + ], + "additionalProperties": false }, - "DbtEnvironmentDeleteResponse": { + "ApiKeyDeleteResponse": { "type": "object", "properties": { "message": { "type": "string", - "description": "Confirmation message", - "example": "dbt environment deleted successfully" + "description": "Human-readable description of the outcome", + "example": "API token revoked" }, "success": { "type": "boolean", - "description": "Whether the deletion was successful", - "example": true + "enum": [ + true + ], + "description": "Always `true` on a successful revocation" } }, "required": [ @@ -1372,7 +1704,7 @@ "success" ] }, - "ContentListResponse": { + "DbtEnvironmentListResponse": { "type": "object", "properties": { "pageInfo": { @@ -1381,1175 +1713,23440 @@ "records": { "type": "array", "items": { - "oneOf": [ - { - "allOf": [ + "$ref": "#/components/schemas/DbtEnvironmentItem" + } + } + }, + "required": [ + "pageInfo", + "records" + ] + }, + "DbtEnvironmentItem": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "Unique environment identifier" + }, + "isDefaultEnvironment": { + "type": "boolean", + "description": "Whether this is the default environment" + }, + "isDeferralEnabled": { + "type": "boolean", + "description": "Whether dbt deferral is enabled for this environment. Always false for the default (production) environment — the backend rejects enabling it there." + }, + "name": { + "type": "string", + "description": "Environment name" + }, + "ownerId": { + "type": [ + "string", + "null" + ], + "description": "User ID of the environment owner, or null if not a personal environment" + }, + "targetDatabase": { + "type": [ + "string", + "null" + ], + "description": "Target database override" + }, + "targetName": { + "type": [ + "string", + "null" + ], + "description": "Target name override" + }, + "targetRole": { + "type": [ + "string", + "null" + ], + "description": "Target role override" + }, + "targetSchema": { + "type": "string", + "description": "Target schema" + }, + "variables": { + "type": "array", + "items": { + "$ref": "#/components/schemas/DbtEnvironmentResponseVariable" + }, + "description": "Environment variables" + } + }, + "required": [ + "id", + "isDefaultEnvironment", + "isDeferralEnabled", + "name", + "ownerId", + "targetDatabase", + "targetName", + "targetRole", + "targetSchema", + "variables" + ] + }, + "DbtEnvironmentResponseVariable": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "Variable ID" + }, + "isSecret": { + "type": "boolean", + "description": "Whether the variable value is secret" + }, + "name": { + "type": "string", + "description": "Variable name" + }, + "value": { + "type": [ + "string", + "null" + ], + "description": "Variable value (null for secret variables)" + } + }, + "required": [ + "id", + "isSecret", + "name", + "value" + ] + }, + "DbtEnvironmentCreateBody": { + "type": "object", + "properties": { + "isDeferralEnabled": { + "type": "boolean", + "default": false, + "description": "Whether to enable dbt deferral for this environment. Ignored (forced to false) for the default (production) environment.", + "example": false + }, + "name": { + "type": "string", + "minLength": 1, + "description": "Environment name", + "example": "PR_1111_Expose" + }, + "ownerId": { + "type": [ + "string", + "null" + ], + "default": null, + "description": "User ID of the environment owner. Used to mark development environments belonging to a specific user.", + "example": null + }, + "targetDatabase": { + "type": [ + "string", + "null" + ], + "default": null, + "description": "Target database override", + "example": "analytics_dev" + }, + "targetName": { + "type": [ + "string", + "null" + ], + "default": null, + "description": "Target name override", + "example": null + }, + "targetRole": { + "type": [ + "string", + "null" + ], + "default": null, + "description": "Target role override", + "example": null + }, + "targetSchema": { + "type": "string", + "minLength": 1, + "description": "Target schema for this environment", + "example": "PR_1111_Expose" + }, + "variables": { + "type": "array", + "items": { + "$ref": "#/components/schemas/DbtEnvironmentVariable" + }, + "default": [], + "description": "Environment variables" + } + }, + "required": [ + "name", + "targetSchema" + ] + }, + "DbtEnvironmentVariable": { + "type": "object", + "properties": { + "isSecret": { + "type": "boolean", + "description": "Whether the variable value is secret" + }, + "name": { + "type": "string", + "minLength": 1, + "description": "Variable name" + }, + "value": { + "type": "string", + "description": "Variable value" + } + }, + "required": [ + "isSecret", + "name", + "value" + ] + }, + "DbtEnvironmentUpdateBody": { + "type": "object", + "properties": { + "isDeferralEnabled": { + "type": "boolean", + "default": false, + "description": "Whether to enable dbt deferral for this environment. Ignored (forced to false) for the default (production) environment.", + "example": false + }, + "name": { + "type": "string", + "minLength": 1, + "description": "Environment name", + "example": "PR_1111_Expose" + }, + "ownerId": { + "type": [ + "string", + "null" + ], + "default": null, + "description": "User ID of the environment owner. Used to mark development environments belonging to a specific user.", + "example": null + }, + "targetDatabase": { + "type": [ + "string", + "null" + ], + "default": null, + "description": "Target database override", + "example": "analytics_dev" + }, + "targetName": { + "type": [ + "string", + "null" + ], + "default": null, + "description": "Target name override", + "example": null + }, + "targetRole": { + "type": [ + "string", + "null" + ], + "default": null, + "description": "Target role override", + "example": null + }, + "targetSchema": { + "type": "string", + "minLength": 1, + "description": "Target schema for this environment", + "example": "PR_1111_Expose" + }, + "variables": { + "type": "array", + "items": { + "$ref": "#/components/schemas/DbtEnvironmentVariableUpdateOrNew" + }, + "default": [], + "description": "Environment variables. Variables with an id update existing ones; variables without an id create new ones." + } + }, + "required": [ + "name", + "targetSchema" + ] + }, + "DbtEnvironmentVariableUpdateOrNew": { + "oneOf": [ + { + "$ref": "#/components/schemas/DbtEnvironmentVariableUpdate" + }, + { + "$ref": "#/components/schemas/DbtEnvironmentVariable" + } + ] + }, + "DbtEnvironmentDeleteResponse": { + "type": "object", + "properties": { + "message": { + "type": "string", + "description": "Confirmation message", + "example": "dbt environment deleted successfully" + }, + "success": { + "type": "boolean", + "description": "Whether the deletion was successful", + "example": true + } + }, + "required": [ + "message", + "success" + ] + }, + "ContentListResponse": { + "type": "object", + "properties": { + "pageInfo": { + "$ref": "#/components/schemas/PageInfo" + }, + "records": { + "type": "array", + "items": { + "oneOf": [ + { + "allOf": [ + { + "$ref": "#/components/schemas/ApiDocument" + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "document" + ] + } + }, + "required": [ + "type" + ] + } + ] + }, + { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique identifier" + }, + "name": { + "type": "string", + "minLength": 1, + "maxLength": 255, + "description": "Content name" + }, + "owner": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "User ID of the owner" + }, + "name": { + "type": "string", + "description": "Name of the owner" + } + }, + "required": [ + "id", + "name" + ], + "description": "Content owner" + }, + "scope": { + "type": "string", + "enum": [ + "restricted", + "organization" + ], + "description": "Content access scope" + }, + "_count": { + "type": "object", + "properties": { + "documents": { + "type": "number", + "description": "Number of documents" + }, + "favorites": { + "type": "number", + "description": "Number of users who favorited" + } + }, + "required": [ + "documents", + "favorites" + ], + "description": "Folder counts" + }, + "labels": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Labels" + }, + "path": { + "type": "string", + "description": "Full path to the folder", + "example": "sales-reports/q1-2026" + }, + "url": { + "type": "string", + "description": "URL to view the folder in the Omni UI.", + "example": "https://org.omni.co/f/sales-reports" + }, + "type": { + "type": "string", + "enum": [ + "folder" + ] + } + }, + "required": [ + "id", + "name", + "owner", + "scope", + "path", + "url", + "type" + ] + } + ] + } + } + }, + "required": [ + "pageInfo", + "records" + ] + }, + "OwnerInternal": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Owner membership ID" + }, + "name": { + "type": "string", + "description": "Owner display name" + } + }, + "required": [ + "id", + "name" + ], + "description": "Content owner" + }, + "ContentShareScope": { + "type": "string", + "enum": [ + "restricted", + "organization" + ], + "description": "Content access scope" + }, + "InternalFolder": { + "type": [ + "object", + "null" + ], + "properties": { + "id": { + "type": "string", + "description": "Folder ID" + }, + "name": { + "type": "string", + "minLength": 1, + "maxLength": 255, + "description": "Folder name" + }, + "path": { + "type": "string", + "description": "Folder path" + }, + "scope": { + "allOf": [ + { + "$ref": "#/components/schemas/ContentShareScope" + }, + { + "description": "Folder access scope" + } + ] + } + }, + "required": [ + "id", + "name", + "path", + "scope" + ], + "description": "Parent folder" + }, + "ApiDocument": { + "type": "object", + "properties": { + "name": { + "type": "string", + "minLength": 1, + "maxLength": 255, + "description": "Content name" + }, + "owner": { + "$ref": "#/components/schemas/OwnerInternal" + }, + "scope": { + "$ref": "#/components/schemas/ContentShareScope" + }, + "_count": { + "type": "object", + "properties": { + "favorites": { + "type": "number", + "description": "Number of users who favorited" + }, + "views": { + "type": "number", + "description": "Number of views" + } + }, + "required": [ + "favorites", + "views" + ], + "description": "Document counts" + }, + "connectionId": { + "type": "string", + "description": "Connection ID" + }, + "deleted": { + "type": "boolean", + "description": "Whether document is deleted" + }, + "description": { + "type": [ + "string", + "null" + ], + "description": "Document description" + }, + "folder": { + "$ref": "#/components/schemas/InternalFolder" + }, + "hasApp": { + "type": "boolean", + "description": "Whether document has an app" + }, + "hasDashboard": { + "type": "boolean", + "description": "Whether document has a dashboard" + }, + "identifier": { + "type": "string", + "description": "Document identifier" + }, + "labels": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Applied labels" + }, + "lastViewedAt": { + "type": [ + "string", + "null" + ], + "format": "date-time", + "description": "Last time the dashboard was viewed" + }, + "updatedAt": { + "type": [ + "string", + "null" + ], + "format": "date-time", + "description": "Last updated timestamp" + }, + "url": { + "type": "string", + "description": "URL to view the document. Returns the dashboard URL if it has a dashboard, the app URL if it has an app, otherwise the workbook URL.", + "example": "https://org.omni.co/dashboards/abc123" + }, + "visits": { + "type": [ + "number", + "null" + ], + "description": "Number of dashboard visits" + } + }, + "required": [ + "name", + "owner", + "scope", + "connectionId", + "deleted", + "folder", + "hasApp", + "hasDashboard", + "identifier", + "updatedAt", + "url" + ] + }, + "DashboardsDownloadResponse": { + "type": "object", + "properties": { + "job_id": { + "type": "string", + "format": "uuid", + "description": "ID of the download job. Use this to poll for download status.", + "example": "123e4567-e89b-12d3-a456-426614174000" + }, + "message": { + "type": "string", + "description": "Status message", + "example": "Download initiated successfully" + } + }, + "required": [ + "job_id", + "message" + ] + }, + "DashboardsDownloadBody": { + "type": "object", + "properties": { + "enableFormatting": { + "type": "boolean", + "default": false, + "description": "Compatible with csv, xlsx & json formats. If true, formatting will be enabled in the output. Note: If true for json format, a queryIdentifierMapKey is required.", + "example": false + }, + "expandTablesToShowAllRows": { + "type": "boolean", + "description": "Compatible with pdf and png formats. If true, up to 1,000 rows in table visualizations will be included in the delivery. Note: This parameter cannot be used when paperFormat: fit_page.", + "example": false + }, + "filterConfig": { + "description": "An object specifying the filter conditions to apply to the task. The filter key specified must already exist in the dashboard.", + "example": { + "status": [ + "active", + "pending" + ] + } + }, + "format": { + "type": "string", + "enum": [ + "pdf", + "png", + "csv", + "xlsx", + "json" + ], + "description": "Output format for the download: pdf, png, csv, xlsx, or json", + "example": "pdf" + }, + "hideHiddenFields": { + "type": "boolean", + "default": false, + "description": "Compatible with csv & xlsx formats. If true, fields marked as hidden won't be displayed in the output.", + "example": false + }, + "hideTitle": { + "type": "boolean", + "default": false, + "description": "Compatible with pdf & png formats. If true, the content's title will be hidden in the output.", + "example": false + }, + "maxRowLimit": { + "type": "number", + "minimum": 1, + "description": "Compatible with csv, json, & xlsx formats. Used with overrideRowLimit. Specifies the maximum number of rows.", + "example": 1000 + }, + "overrideRowLimit": { + "type": "boolean", + "default": false, + "description": "Compatible with csv, json, & xlsx formats. If true, the default row limit will be overridden. Note: If true for json and xlsx formats, a queryIdentifierMapKey is required.", + "example": false + }, + "paperFormat": { + "type": "string", + "enum": [ + "a3", + "a4", + "fit_page", + "legal", + "letter", + "tabloid" + ], + "description": "Compatible with pdf formats. Defines the paper format (size) of the resulting PDF. Must be one of: a3, a4, letter, legal, fit_page, tabloid.", + "example": "letter" + }, + "paperOrientation": { + "type": "string", + "enum": [ + "portrait", + "landscape" + ], + "description": "Compatible with pdf formats. Defines the paper orientation of the resulting PDF. Must be one of: portrait, landscape.", + "example": "landscape" + }, + "queryIdentifierMapKey": { + "type": "string", + "description": "Required for single tile tasks. The ID of the query to include in a single tile task. Must reference a valid query in the dashboard.", + "example": "Jmn2r3KV" + }, + "showContentLink": { + "type": "boolean", + "default": true, + "description": "Compatible with all formats except link_only. If true, a link to the content will be shown in the output.", + "example": true + }, + "showFilters": { + "type": "boolean", + "default": true, + "description": "Compatible with all formats except link_only & csv. If true, filters will be shown in the output.", + "example": true + }, + "singleColumnLayout": { + "type": "boolean", + "description": "Compatible with pdf and png formats. If true, dashboard tiles will be arranged into a single vertical column.", + "example": false + }, + "useCache": { + "type": "boolean", + "default": false, + "description": "If true, allow scheduled queries to use cached results instead of always running fresh queries.", + "example": false + }, + "filename": { + "type": "string", + "minLength": 1, + "maxLength": 255, + "description": "Custom filename for the downloaded file (without extension)", + "example": "monthly-report" + } + }, + "required": [ + "format" + ], + "additionalProperties": false + }, + "DashboardFiltersResponse": { + "type": "object", + "properties": { + "controls": { + "description": "Control configuration object. Keys are control IDs, values contain controlType, filterId, label, etc." + }, + "filterOrder": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Ordered list of filter IDs defining display order", + "example": [ + "filter_abc123", + "filter_def456" + ] + }, + "filters": { + "description": "Filter configuration object. Keys are filter IDs, values contain fieldName, viewName, kind, defaultValue, etc." + }, + "identifier": { + "type": "string", + "description": "Dashboard identifier", + "example": "12db1a0a" + } + }, + "required": [ + "filterOrder", + "identifier" + ] + }, + "DashboardsUpdateFiltersBody": { + "type": "object", + "properties": { + "clearExistingDraft": { + "type": "boolean", + "default": false, + "description": "When true, discards any existing draft before applying updates. Required when updating a published document that already has a draft." + }, + "controls": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": {}, + "additionalProperties": {} + }, + "description": "Partial control updates. Keys are control IDs that must exist in the dashboard." + }, + "filterOrder": { + "type": "array", + "items": { + "type": "string" + }, + "description": "New order for filters. All filter IDs must exist in the dashboard." + }, + "filters": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": {}, + "additionalProperties": {} + }, + "description": "Partial filter updates. Keys are filter IDs that must exist in the dashboard." + } + } + }, + "DocumentsListResponse": { + "type": "object", + "properties": { + "pageInfo": { + "allOf": [ + { + "$ref": "#/components/schemas/PageInfo" + }, + { + "description": "Pagination information" + } + ] + }, + "records": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Document" + }, + "description": "List of documents" + } + }, + "required": [ + "pageInfo", + "records" + ] + }, + "Document": { + "type": "object", + "properties": { + "_count": { + "type": "object", + "properties": { + "favorites": { + "type": "number", + "description": "Number of users who favorited this document" + }, + "views": { + "type": "number", + "description": "Number of views" + } + }, + "required": [ + "favorites", + "views" + ], + "description": "Document counts (included when _count is in include param)" + }, + "connectionId": { + "type": "string", + "description": "Connection ID the document is associated with" + }, + "deleted": { + "type": "boolean", + "description": "Whether the document is deleted (archived)" + }, + "description": { + "type": [ + "string", + "null" + ], + "description": "Document description" + }, + "folder": { + "$ref": "#/components/schemas/DocumentFolder" + }, + "hasApp": { + "type": "boolean", + "description": "Whether the document has an associated app" + }, + "hasDashboard": { + "type": "boolean", + "description": "Whether the document has an associated dashboard" + }, + "identifier": { + "type": "string", + "description": "Document identifier", + "example": "abc123" + }, + "labels": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Labels applied to the document (included when labels is in include param)" + }, + "name": { + "type": "string", + "description": "Document name" + }, + "owner": { + "$ref": "#/components/schemas/DocumentOwner" + }, + "scope": { + "type": "string", + "enum": [ + "restricted", + "organization" + ], + "description": "Document access scope" + }, + "type": { + "type": "string", + "enum": [ + "document" + ], + "description": "Content type" + }, + "updatedAt": { + "type": [ + "string", + "null" + ], + "format": "date-time", + "description": "Last updated timestamp" + }, + "url": { + "type": "string", + "description": "URL to view the document. Returns the dashboard URL if it has a dashboard, the app URL if it has an app, otherwise the workbook URL.", + "example": "https://org.omni.co/dashboards/abc123" + } + }, + "required": [ + "connectionId", + "deleted", + "folder", + "hasDashboard", + "identifier", + "name", + "owner", + "scope", + "type", + "updatedAt", + "url" + ] + }, + "DocumentFolder": { + "type": [ + "object", + "null" + ], + "properties": { + "id": { + "type": "string", + "description": "Folder ID" + }, + "name": { + "type": "string", + "description": "Folder name" + }, + "path": { + "type": "string", + "description": "Folder path" + }, + "scope": { + "type": "string", + "enum": [ + "restricted", + "organization" + ], + "description": "Folder access scope" + } + }, + "required": [ + "id", + "name", + "path", + "scope" + ], + "description": "Folder containing the document" + }, + "DocumentOwner": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Owner membership ID" + }, + "name": { + "type": "string", + "description": "Owner display name" + } + }, + "required": [ + "id", + "name" + ], + "description": "Document owner" + }, + "DocumentsCreateResponse": { + "type": "object", + "properties": { + "dashboard": { + "type": "object", + "properties": { + "dashboardId": { + "type": "string", + "description": "Dashboard ID" + }, + "id": { + "type": "string", + "description": "Dashboard ID" + } + }, + "required": [ + "dashboardId", + "id" + ], + "additionalProperties": {}, + "description": "Created dashboard" + }, + "workbook": { + "type": "object", + "properties": { + "documentId": { + "type": "string", + "description": "Document ID (deprecated)" + }, + "id": { + "type": "string", + "description": "Workbook ID" + } + }, + "required": [ + "documentId", + "id" + ], + "additionalProperties": {}, + "description": "Created workbook" + } + }, + "required": [ + "dashboard", + "workbook" + ] + }, + "DocumentsCreateBody": { + "type": "object", + "properties": { + "branchId": { + "type": "string", + "format": "uuid", + "description": "Optional branch ID to associate the document with a model branch", + "example": "123e4567-e89b-12d3-a456-426614174001" + }, + "description": { + "type": [ + "string", + "null" + ], + "description": "Document description" + }, + "facetFilters": { + "type": "boolean", + "description": "Enable facet filters on the dashboard" + }, + "filterConfig": { + "description": "Dashboard filter configuration" + }, + "filterOrder": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Order of filters in the dashboard" + }, + "identifier": { + "$ref": "#/components/schemas/DocumentIdentifier" + }, + "metadata": { + "description": "Dashboard metadata" + }, + "metadataVersion": { + "type": "string", + "description": "Dashboard metadata version (required when metadata is provided)" + }, + "modelId": { + "type": "string", + "description": "Shared model ID to base the document on" + }, + "name": { + "type": "string", + "description": "Document name" + }, + "queryPresentations": { + "type": "array", + "items": { + "type": "object", + "properties": { + "aiConfig": { + "description": "AI configuration" + }, + "chartType": { + "type": [ + "string", + "null" + ], + "description": "Chart type" + }, + "description": { + "type": "string", + "maxLength": 500, + "description": "Query presentation description" + }, + "name": { + "type": "string", + "minLength": 1, + "maxLength": 144, + "description": "Query presentation name" + }, + "prefersChart": { + "type": "boolean", + "description": "Whether to prefer chart view" + }, + "query": { + "type": "object", + "properties": { + "fields": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Query fields" + }, + "table": { + "type": "string", + "description": "Query table/topic" + } + }, + "required": [ + "fields", + "table" + ], + "additionalProperties": {}, + "description": "Query definition" + }, + "resultConfig": { + "description": "Result configuration" + }, + "subTitle": { + "type": "string", + "maxLength": 250, + "description": "Subtitle" + }, + "topicName": { + "type": [ + "string", + "null" + ], + "maxLength": 256, + "description": "Topic name. Omit or pass null for raw-SQL tiles or any tile with no semantic topic." + }, + "visConfig": { + "$ref": "#/components/schemas/ApiVisConfig" + } + }, + "required": [ + "name", + "query" + ] + }, + "description": "Query presentations for the document" + } + }, + "required": [ + "modelId", + "name" + ] + }, + "DocumentIdentifier": { + "type": "string", + "minLength": 2, + "maxLength": 48, + "description": "Optional document identifier. If omitted, an identifier is auto-generated. Must be unique within the organization." + }, + "ApiVisConfig": { + "type": [ + "object", + "null" + ], + "properties": { + "config": { + "type": "object", + "additionalProperties": {}, + "description": "Visualization spec (chart configuration)" + }, + "fields": { + "type": [ + "array", + "null" + ], + "items": { + "type": "string", + "minLength": 1 + }, + "description": "Field names used in the visualization" + }, + "visType": { + "type": "string", + "enum": [ + "vegalite", + "omni-ai-summary-markdown", + "basic", + "omni-kpi", + "map", + "omni-markdown", + "funnel", + "sankey", + "single-record", + "svg-map", + "omni-spreadsheet", + "spreadsheet-tab", + "summary-value", + "omni-table", + "app" + ], + "description": "Visualization type (e.g. basic, omni-markdown, omni-table)" + } + }, + "additionalProperties": {}, + "description": "Visualization configuration" + }, + "DocumentsGetResponse": { + "type": "object", + "properties": { + "description": { + "type": [ + "string", + "null" + ], + "description": "Document description" + }, + "documentMetadata": { + "description": "Document metadata" + }, + "facetFilters": { + "type": "boolean", + "description": "Whether facet filters are enabled" + }, + "filterConfig": { + "description": "Dashboard filter configuration" + }, + "filterOrder": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Order of filters" + }, + "modelId": { + "type": "string", + "description": "Model ID" + }, + "name": { + "type": "string", + "description": "Document name" + }, + "queryPresentations": { + "type": "array", + "items": {}, + "description": "Query presentations" + }, + "refreshInterval": { + "type": [ + "number", + "null" + ], + "description": "Auto-refresh interval in seconds" + } + }, + "required": [ + "facetFilters", + "filterOrder", + "modelId", + "name", + "queryPresentations", + "refreshInterval" + ] + }, + "DocumentsPutResponse": { + "type": "object", + "properties": { + "description": { + "type": [ + "string", + "null" + ], + "description": "Document description" + }, + "identifier": { + "type": "string", + "description": "Document identifier" + }, + "name": { + "type": "string", + "description": "Updated document name" + } + }, + "required": [ + "identifier", + "name" + ] + }, + "DocumentsPutBody": { + "type": "object", + "properties": { + "clearExistingDraft": { + "type": "boolean", + "default": false, + "description": "Clear existing draft before updating (for published documents with drafts)" + }, + "description": { + "type": [ + "string", + "null" + ], + "description": "Document description" + }, + "documentMetadata": { + "description": "Document presentation metadata" + }, + "facetFilters": { + "type": "boolean", + "description": "Enable facet filters" + }, + "filterConfig": { + "description": "Filter configuration" + }, + "filterOrder": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Order of filters" + }, + "modelId": { + "type": "string", + "description": "Model ID" + }, + "name": { + "type": "string", + "minLength": 1, + "maxLength": 254, + "description": "Document name" + }, + "queryPresentations": { + "type": "array", + "items": { + "$ref": "#/components/schemas/DocumentsPutQueryPresentation" + }, + "minItems": 1, + "description": "Query presentations (full replacement)" + }, + "refreshInterval": { + "type": [ + "integer", + "null" + ], + "minimum": 60, + "description": "Auto-refresh interval in seconds" + } + }, + "required": [ + "facetFilters", + "filterOrder", + "modelId", + "name", + "queryPresentations", + "refreshInterval" + ] + }, + "DocumentsPutQueryPresentation": { + "type": "object", + "properties": { + "aiConfig": { + "type": "object", + "properties": { + "description": { + "type": "object", + "properties": { + "aiContext": { + "type": "string" + }, + "enabled": { + "type": "boolean" + } + } + }, + "subTitle": { + "type": "object", + "properties": { + "aiContext": { + "type": "string" + }, + "enabled": { + "type": "boolean" + } + } + } + }, + "description": "AI configuration" + }, + "chartType": { + "type": [ + "string", + "null" + ], + "enum": [ + "auto", + "area", + "areaStacked", + "areaStackedPercentage", + "bar", + "barLine", + "barGrouped", + "barStacked", + "barStackedPercentage", + "boxplot", + "code", + "column", + "columnGrouped", + "columnStacked", + "columnStackedPercentage", + "heatmap", + "kpi", + "line", + "lineColor", + "map", + "regionMap", + "markdown", + "omni-ai-summary-markdown", + "pie", + "funnel", + "sankey", + "point", + "pointColor", + "pointSize", + "pointSizeColor", + "singleRecord", + "omni-spreadsheet", + "summaryValue", + "svgMap", + "table", + null + ], + "description": "Chart type" + }, + "description": { + "type": "string", + "maxLength": 500, + "description": "Description" + }, + "name": { + "type": "string", + "minLength": 1, + "maxLength": 144, + "description": "Query presentation name" + }, + "prefersChart": { + "type": "boolean", + "description": "Whether to prefer chart view" + }, + "query": { + "description": "Query definition" + }, + "queryIdentifierMapKey": { + "type": "string", + "pattern": "^[1-9][0-9]*$", + "description": "Round-trip preservation hint. When the value matches an existing key on the document, the tile keeps its map key (and dashboard containers stay attached). Omit for new tiles. Must be a positive integer string (e.g. \"1\", \"2\", \"10\")." + }, + "resultConfig": { + "description": "Result config" + }, + "subTitle": { + "type": "string", + "maxLength": 250, + "description": "Subtitle" + }, + "topicName": { + "type": [ + "string", + "null" + ], + "maxLength": 256, + "description": "Topic name. Omit or pass null for raw-SQL tiles or any tile with no semantic topic." + }, + "visConfig": { + "$ref": "#/components/schemas/ApiVisConfig" + } + }, + "required": [ + "name" + ] + }, + "DocumentsUpdateResponse": { + "type": "object", + "properties": { + "description": { + "type": [ + "string", + "null" + ], + "description": "Document description" + }, + "identifier": { + "type": "string", + "description": "Document identifier" + }, + "name": { + "type": "string", + "description": "Updated document name" + } + }, + "required": [ + "identifier", + "name" + ] + }, + "DocumentsUpdateBody": { + "type": "object", + "properties": { + "clearExistingDraft": { + "type": "boolean", + "default": false, + "description": "Clear existing draft before updating (for published documents with drafts)" + }, + "description": { + "type": [ + "string", + "null" + ], + "description": "Document description" + }, + "identifier": { + "allOf": [ + { + "$ref": "#/components/schemas/DocumentIdentifier" + }, + { + "description": "New identifier for the document. Must be unique within the organization. The previous identifier is retained in the document identifier history and continues to redirect." + } + ] + }, + "name": { + "type": "string", + "minLength": 1, + "maxLength": 254, + "description": "New document name" + } + } + }, + "SuccessResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "description": "Whether the operation was successful", + "example": true + } + }, + "required": [ + "success" + ] + }, + "DocumentsGetQueriesResponse": { + "type": "object", + "properties": { + "queries": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Query presentation ID" + }, + "name": { + "type": "string", + "description": "Query presentation name" + }, + "query": { + "description": "Query JSON definition" + }, + "queryIdentifierMapKey": { + "type": "string", + "description": "Key in the query identifier map" + }, + "url": { + "type": "string", + "description": "URL to view this specific query/sheet in the workbook.", + "example": "https://org.omni.co/w/abc123?key=1" + } + }, + "required": [ + "id", + "name", + "queryIdentifierMapKey", + "url" + ] + }, + "description": "List of queries in the document" + } + }, + "required": [ + "queries" + ] + }, + "DocumentsMoveBody": { + "type": "object", + "properties": { + "folderPath": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Destination folder path (null for root)" + }, + "scope": { + "type": "string", + "enum": [ + "restricted", + "organization" + ], + "description": "Access scope for the document" + } + }, + "required": [ + "folderPath" + ] + }, + "DocumentsGetPermissionsResponse": { + "type": "object", + "properties": { + "permits": { + "description": "User permits for the document" + } + } + }, + "DocumentsUpdatePermissionSettingsBody": { + "type": "object", + "properties": { + "canDownload": { + "type": "boolean", + "description": "Allow downloading" + }, + "canDrill": { + "type": "boolean", + "description": "Allow drill-down" + }, + "canSchedule": { + "type": "boolean", + "description": "Allow scheduling" + }, + "canUpload": { + "type": "boolean", + "description": "Allow uploads" + }, + "canUseDashboardAi": { + "type": "boolean", + "description": "Allow using dashboard AI" + }, + "canUseTimezoneOverride": { + "type": "boolean", + "description": "Allow timezone override" + }, + "canViewWorkbook": { + "type": "boolean", + "description": "Allow viewing workbook" + }, + "organizationAccessBoost": { + "type": "boolean", + "description": "Boost organization access" + }, + "organizationRole": { + "type": "string", + "enum": [ + "viewer", + "editor", + "manager", + "no_access" + ], + "description": "Organization-wide role for the document" + }, + "requirePullRequestToPublish": { + "type": "boolean", + "description": "Require pull request to publish changes" + } + } + }, + "DocumentsAddPermitsBody": { + "type": "object", + "properties": { + "accessBoost": { + "type": "boolean", + "default": false, + "description": "Grant access boost" + }, + "role": { + "type": "string", + "enum": [ + "NO_ACCESS", + "VIEWER", + "EXPLORER", + "EDITOR", + "MANAGER" + ], + "description": "Role to grant" + }, + "userGroupIds": { + "type": "array", + "items": { + "type": "string" + }, + "default": [], + "description": "User group IDs to grant access to" + }, + "userIds": { + "type": "array", + "items": { + "type": "string", + "format": "uuid" + }, + "default": [], + "description": "User membership IDs to grant access to" + } + }, + "required": [ + "role" + ] + }, + "DocumentsUpdatePermitsBody": { + "type": "object", + "properties": { + "accessBoost": { + "type": "boolean", + "description": "Access boost setting" + }, + "role": { + "type": "string", + "enum": [ + "NO_ACCESS", + "VIEWER", + "EXPLORER", + "EDITOR", + "MANAGER" + ], + "description": "Role to set" + }, + "userGroupIds": { + "type": "array", + "items": { + "type": "string" + }, + "default": [], + "description": "User group IDs to update" + }, + "userIds": { + "type": "array", + "items": { + "type": "string", + "format": "uuid" + }, + "default": [], + "description": "User membership IDs to update" + } + } + }, + "DocumentsRevokePermitsBody": { + "type": "object", + "properties": { + "userGroupIds": { + "type": "array", + "items": { + "type": "string" + }, + "default": [], + "description": "User group IDs to revoke access from" + }, + "userIds": { + "type": "array", + "items": { + "type": "string", + "format": "uuid" + }, + "default": [], + "description": "User membership IDs to revoke access from" + } + } + }, + "DocumentsCreateDraftResponse": { + "type": "object", + "properties": { + "identifier": { + "type": "string", + "description": "Draft document identifier" + } + }, + "required": [ + "identifier" + ] + }, + "DocumentsCreateDraftBody": { + "type": "object", + "properties": { + "branchId": { + "type": "string", + "format": "uuid", + "description": "Branch ID for the draft" + } + } + }, + "DocumentsDiscardDraftResponse": { + "type": "object", + "properties": { + "message": { + "type": "string", + "description": "Success message" + } + }, + "required": [ + "message" + ] + }, + "DocumentsDiscardDraftBody": { + "type": "object", + "properties": { + "branchId": { + "type": "string", + "format": "uuid", + "description": "Branch ID for the draft" + } + } + }, + "DocumentsListDraftsResponse": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ApiDraft" + } + }, + "ApiDraft": { + "type": "object", + "properties": { + "branch": { + "$ref": "#/components/schemas/ApiDraftBranch" + }, + "createdAt": { + "type": "string", + "format": "date-time", + "description": "When the draft was created" + }, + "createdBy": { + "$ref": "#/components/schemas/ApiDraftActor" + }, + "draftOutOfDate": { + "type": "boolean", + "description": "True when the published document was published more recently than the draft was created (the draft is based on a stale baseline)" + }, + "identifier": { + "type": "string", + "description": "Draft workbook identifier — use this to address the draft" + }, + "lastEditedBy": { + "allOf": [ + { + "$ref": "#/components/schemas/ApiDraftActor" + }, + { + "description": "User who most recently edited the draft" + } + ] + }, + "publishedIdentifier": { + "type": "string", + "description": "Identifier of the published document the draft is for" + }, + "status": { + "$ref": "#/components/schemas/ApiDraftStatus" + }, + "updatedAt": { + "type": "string", + "format": "date-time", + "description": "Most recent edit time on the draft workbook" + }, + "workbookModelId": { + "type": "string", + "format": "uuid", + "description": "omni_model ID for the draft workbook" + } + }, + "required": [ + "branch", + "createdAt", + "createdBy", + "draftOutOfDate", + "identifier", + "lastEditedBy", + "publishedIdentifier", + "status", + "updatedAt", + "workbookModelId" + ] + }, + "ApiDraftBranch": { + "type": [ + "object", + "null" + ], + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "Branch (omni model) ID" + }, + "name": { + "type": "string", + "description": "Branch name" + } + }, + "required": [ + "id", + "name" + ], + "description": "Branch the draft is attached to, or null for a draft on main" + }, + "ApiDraftActor": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Display name" + } + }, + "required": [ + "name" + ], + "description": "User who created the draft" + }, + "ApiDraftStatus": { + "type": "string", + "enum": [ + "active", + "archived" + ], + "description": "Lifecycle status: \"active\" for current drafts, \"archived\" for soft-deleted drafts (retained ~7 days)" + }, + "DocumentsDuplicateResponse": { + "type": "object", + "properties": { + "dashboardId": { + "type": "string", + "description": "New dashboard ID" + }, + "identifier": { + "type": "string", + "description": "New document identifier" + }, + "name": { + "type": "string", + "description": "Document name" + }, + "workbookId": { + "type": "string", + "description": "New workbook ID" + } + }, + "required": [ + "dashboardId", + "identifier", + "name", + "workbookId" + ] + }, + "DocumentsDuplicateBody": { + "type": "object", + "properties": { + "folderPath": { + "type": [ + "string", + "null" + ], + "description": "Destination folder path (null for root)" + }, + "name": { + "type": "string", + "minLength": 1, + "maxLength": 254, + "description": "Name for the duplicated document" + }, + "scope": { + "type": "string", + "enum": [ + "restricted", + "organization" + ], + "description": "Access scope for the duplicated document" + } + }, + "required": [ + "name" + ] + }, + "DocumentsBulkUpdateLabelsResponse": { + "type": "object", + "properties": { + "labels": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Updated list of labels on the document" + } + }, + "required": [ + "labels" + ] + }, + "DocumentsBulkUpdateLabelsBody": { + "type": "object", + "properties": { + "add": { + "type": "array", + "items": { + "type": "string" + }, + "default": [], + "description": "Labels to add" + }, + "remove": { + "type": "array", + "items": { + "type": "string" + }, + "default": [], + "description": "Labels to remove" + } + } + }, + "DocumentsTransferOwnershipBody": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "format": "uuid", + "description": "Membership ID of the new owner" + } + }, + "required": [ + "userId" + ] + }, + "DocumentsAccessListResponse": { + "type": "object", + "properties": { + "pageInfo": { + "allOf": [ + { + "$ref": "#/components/schemas/PageInfo" + }, + { + "description": "Pagination information" + } + ] + }, + "principals": { + "type": "array", + "items": {}, + "description": "List of users and groups with access" + } + }, + "required": [ + "pageInfo", + "principals" + ] + }, + "DocumentsListFavoritesResponse": { + "type": "object", + "properties": { + "pageInfo": { + "allOf": [ + { + "$ref": "#/components/schemas/PageInfo" + }, + { + "description": "Pagination information" + } + ] + }, + "records": { + "type": "array", + "items": { + "$ref": "#/components/schemas/DocumentFavoriteUser" + }, + "description": "Users who favorited this document" + } + }, + "required": [ + "pageInfo", + "records" + ] + }, + "DocumentFavoriteUser": { + "type": "object", + "properties": { + "email": { + "type": [ + "string", + "null" + ], + "description": "Favoriting user's email. Null when the user has no resolvable email — e.g. an embed-SSO favoriter whose embed session did not provide one." + }, + "favoritedAt": { + "type": "string", + "description": "ISO 8601 timestamp when the user favorited the document" + }, + "name": { + "type": "string", + "description": "Favoriting user's display name" + }, + "userId": { + "type": "string", + "description": "Membership ID of the user who favorited the document (use with other v1 endpoints' userId parameter)" + } + }, + "required": [ + "email", + "favoritedAt", + "name", + "userId" + ] + }, + "DocumentsV2CreateResponse": { + "type": "object", + "properties": { + "description": { + "type": [ + "string", + "null" + ], + "description": "Document description." + }, + "identifier": { + "type": "string", + "description": "Identifier of the newly created document." + }, + "name": { + "type": "string", + "description": "Document name." + } + }, + "required": [ + "description", + "identifier", + "name" + ] + }, + "DocumentsV2CreateBody": { + "type": "object", + "properties": { + "containers": { + "$ref": "#/components/schemas/Containers" + }, + "controls": { + "$ref": "#/components/schemas/ControlsPatchExternal" + }, + "description": { + "type": [ + "string", + "null" + ], + "description": "Document description." + }, + "folderId": { + "type": [ + "string", + "null" + ], + "format": "uuid", + "description": "Folder to create the document in. When omitted, defaults to the caller’s personal \"My documents\" (requires permission to save personal content — otherwise the request is rejected)." + }, + "identifier": { + "allOf": [ + { + "$ref": "#/components/schemas/DocumentIdentifier" + }, + { + "description": "Identifier for the new document. Must be unique within the organization. Auto-generated when omitted." + } + ] + }, + "modelId": { + "type": "string", + "format": "uuid", + "description": "Base workbook model the document is built on — a SHARED model, or a SHARED_EXTENSION with `allowAsWorkbookBase = true`." + }, + "name": { + "type": "string", + "minLength": 1, + "maxLength": 254, + "description": "Document name." + }, + "queryPresentations": { + "$ref": "#/components/schemas/QueryPresentationsPatchExternal" + }, + "settings": { + "$ref": "#/components/schemas/SettingsPatchExternal" + }, + "summary": { + "type": "string", + "minLength": 1, + "maxLength": 255, + "description": "Caller-supplied note describing the create, written to the history audit trail. Defaults to \"Created document\" when omitted." + } + }, + "required": [ + "modelId", + "name" + ], + "additionalProperties": false + }, + "Containers": { + "type": "array", + "items": { + "anyOf": [ + { + "$ref": "#/components/schemas/GridContainer" + }, + { + "$ref": "#/components/schemas/PageContainer" + }, + { + "$ref": "#/components/schemas/StackContainer" + } + ] + }, + "description": "Container layout array (grid / stack / page / reference containers, recursively nested). The server validates the full structure on apply." + }, + "GridContainer": { + "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" + } + ] + }, + "before": { + "anyOf": [ + { + "$ref": "#/components/schemas/StackContainer" + }, + { + "$ref": "#/components/schemas/ReferenceContainer" + } + ] + }, + "children": { + "type": "array", + "items": { + "anyOf": [ + { + "allOf": [ + { + "$ref": "#/components/schemas/ReferenceContainer" + }, + { + "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" + ] + } + ] + }, + { + "allOf": [ + { + "$ref": "#/components/schemas/StackContainer" + }, + { + "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" + ] + } + ] + }, + { + "allOf": [ + { + "$ref": "#/components/schemas/GridContainer" + }, + { + "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" + ] + } + ] + }, + { + "allOf": [ + { + "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" + }, + "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" + ] + } + }, + "required": [ + "instanceKey", + "id", + "type" + ] + }, + { + "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)" + }, + "appearance": { + "oneOf": [ + { + "type": "object", + "properties": { + "as": { + "type": "string", + "enum": [ + "inline" + ] + } + }, + "required": [ + "as" + ] + }, + { + "type": "object", + "properties": { + "as": { + "type": "string", + "enum": [ + "tooltip" + ] + } + }, + "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)" + }, + "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" + } + } + }, + "textAlign": { + "type": "string", + "enum": [ + "start", + "center", + "end" + ], + "description": "Text alignment: \"start\", \"center\", or \"end\"" + }, + "type": { + "type": "string", + "enum": [ + "inline-text" + ] + } + }, + "required": [ + "instanceKey", + "content", + "type" + ] + }, + { + "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)" + }, + "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" + } + } + } + }, + "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": [ + "inline-page-switcher" + ] + } + }, + "required": [ + "instanceKey", + "type" + ] + }, + { + "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)" + }, + "id": { + "type": "string", + "format": "uuid", + "description": "UUID of the rich text content block" + }, + "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": [ + "text" + ] + } + }, + "required": [ + "instanceKey", + "id", + "type" + ] + }, + { + "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)" + }, + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "control" + ] + }, + "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" + } + } + } + }, + "required": [ + "instanceKey", + "id", + "type" + ] + }, + { + "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)" + }, + "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" + } + } + } + }, + "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" + } + } + } + }, + "required": [ + "instanceKey", + "id", + "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": "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)." + } + }, + "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 + ] + }, + { + "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 + ] + } + ] + } + ] + } + ] + }, + "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" + }, + "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" + ] + } + }, + "required": [ + "instanceKey", + "id", + "type" + ] + }, + { + "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)" + }, + "appearance": { + "oneOf": [ + { + "type": "object", + "properties": { + "as": { + "type": "string", + "enum": [ + "inline" + ] + } + }, + "required": [ + "as" + ] + }, + { + "type": "object", + "properties": { + "as": { + "type": "string", + "enum": [ + "tooltip" + ] + } + }, + "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)" + }, + "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" + } + } + }, + "textAlign": { + "type": "string", + "enum": [ + "start", + "center", + "end" + ], + "description": "Text alignment: \"start\", \"center\", or \"end\"" + }, + "type": { + "type": "string", + "enum": [ + "inline-text" + ] + } + }, + "required": [ + "instanceKey", + "content", + "type" + ] + }, + { + "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)" + }, + "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" + } + } + } + }, + "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": [ + "inline-page-switcher" + ] + } + }, + "required": [ + "instanceKey", + "type" + ] + }, + { + "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)" + }, + "id": { + "type": "string", + "format": "uuid", + "description": "UUID of the rich text content block" + }, + "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": [ + "text" + ] + } + }, + "required": [ + "instanceKey", + "id", + "type" + ] + }, + { + "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)" + }, + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "control" + ] + }, + "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" + } + } + } + }, + "required": [ + "instanceKey", + "id", + "type" + ] + }, + { + "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)" + }, + "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" + } + } + } + }, + "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" + } + } + } + }, + "required": [ + "instanceKey", + "id", + "type" + ] + }, + { + "type": "object", + "properties": { + "instanceKey": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "required": [ + "instanceKey", + "type" + ], + "additionalProperties": {} + }, + { + "$ref": "#/components/schemas/ReferenceContainer" + }, + { + "$ref": "#/components/schemas/GridContainer" + }, + { + "$ref": "#/components/schemas/StackContainer" + } + ] + } + }, + "containerType": { + "type": "string", + "enum": [ + "stack" + ], + "description": "Stack containers lay out children sequentially in a direction (column or row)" + }, + "direction": { + "type": "string", + "enum": [ + "column", + "row" + ], + "description": "Layout direction: \"row\" lays out horizontally, \"column\" stacks vertically (default if not specified)" + }, + "gap": { + "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": "number", + "enum": [ + 9 + ] + }, + { + "type": "number", + "enum": [ + 10 + ] + }, + { + "type": "number", + "enum": [ + 11 + ] + }, + { + "type": "number", + "enum": [ + 12 + ] + }, + { + "type": "number", + "enum": [ + 13 + ] + }, + { + "type": "number", + "enum": [ + 14 + ] + }, + { + "type": "number", + "enum": [ + 15 + ] + }, + { + "type": "number", + "enum": [ + 16 + ] + } + ], + "description": "Space between children (CSS size value)" + }, + "justify": { + "type": "string", + "enum": [ + "flex-start", + "flex-end", + "center", + "space-between" + ], + "description": "Main-axis alignment of children (e.g., start, center, end)" + }, + "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)." + } + }, + "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 + ] + }, + { + "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 + ] + } + ] + } + ] + } + ] + }, + "style": { + "type": "string", + "pattern": "^[a-z0-9-]+$" + }, + "wrap": { + "type": "string", + "enum": [ + "nowrap", + "wrap" + ], + "description": "Whether flex items should wrap to new lines (defaults to nowrap if not specified)" + } + }, + "required": [ + "instanceKey", + "children", + "containerType" + ], + "description": "Stack container — an ordered list of nested children (content, grid, stack, or reference)." + }, + "ReferenceContainer": { + "type": "object", + "properties": { + "containerType": { + "type": "string", + "enum": [ + "reference" + ] + }, + "instanceKey": { + "type": "string" + }, + "referenceKey": { + "type": "string" + } + }, + "required": [ + "containerType", + "instanceKey", + "referenceKey" + ], + "description": "Reference container — points at another container in the collection by its instanceKey." + }, + "PageContainer": { + "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" + }, + "breakpoint": { + "type": "string", + "enum": [ + "desktop", + "mobile" + ] + }, + "container": { + "anyOf": [ + { + "$ref": "#/components/schemas/GridContainer" + }, + { + "$ref": "#/components/schemas/StackContainer" + }, + { + "$ref": "#/components/schemas/ReferenceContainer" + } + ] + }, + "containerType": { + "type": "string", + "enum": [ + "page" + ] + }, + "media": { + "type": "string", + "enum": [ + "screen", + "print" + ] + } + }, + "required": [ + "instanceKey", + "container", + "containerType" + ], + "description": "Page container — a top-level page wrapping a single grid, stack, or reference container, optionally per breakpoint/media." + }, + "ControlsPatchExternal": { + "type": "object", + "properties": { + "data": { + "type": "object", + "additionalProperties": { + "$ref": "#/components/schemas/ControlPatchExternal" + }, + "description": "Controls keyed by control ID. Shallow-merged by key — omitted keys are untouched; set to `null` to delete." + }, + "order": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Display order for controls. When present, replaces the existing order." + } + } + }, + "ControlPatchExternal": { + "type": [ + "object", + "null" + ], + "properties": { + "config": { + "oneOf": [ + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "case_insensitive": { + "type": "boolean" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "kind": { + "type": "string", + "enum": [ + "CONTAINS", + "ENDS_WITH", + "STARTS_WITH", + "EQUALS", + "IS_EMPTY", + "SQL_LIKE" + ] + }, + "type": { + "type": "string", + "enum": [ + "string" + ] + }, + "values": { + "type": "array", + "items": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "kind", + "type", + "values" + ], + "additionalProperties": {} + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "is_inclusive": { + "type": "boolean" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "kind": { + "type": "string", + "enum": [ + "LESS_THAN", + "GREATER_THAN", + "EQUALS", + "BETWEEN" + ] + }, + "type": { + "type": "string", + "enum": [ + "number" + ] + }, + "values": { + "type": "array", + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + } + ] + } + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "kind", + "type", + "values" + ], + "additionalProperties": {} + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "isFiscal": { + "type": "boolean" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "kind": { + "type": "string", + "enum": [ + "IS_ON_DAY_OF_WEEK", + "IS_ON_DAY_OF_QUARTER", + "IS_IN_MONTH_OF_YEAR", + "IS_ON_DAY_OF_YEAR", + "IS_AT_HOUR_OF_DAY", + "IS_IN_QUARTER_OF_YEAR", + "IS_IN_WEEK_OF_YEAR", + "IS_ON_DAY_OF_MONTH", + "BETWEEN", + "ON_OR_AFTER", + "BEFORE", + "TIME_FOR_INTERVAL_DURATION", + "TIME_FOR_UNIT_DURATION", + "QUERY_OFFSET" + ] + }, + "left_side": { + "type": [ + "string", + "null" + ] + }, + "offset_interval_string": { + "type": [ + "string", + "null" + ] + }, + "right_side": { + "type": [ + "string", + "null" + ] + }, + "type": { + "type": "string", + "enum": [ + "date" + ] + }, + "ui_type": { + "type": [ + "string", + "null" + ], + "enum": [ + "ANY_TIME", + "BEFORE", + "BETWEEN", + "MONTH_OF_YEAR", + "PAST", + "YEAR", + "DAY", + "IS_ON_DAY_OF_WEEK", + "ON_OR_AFTER", + "IS_IN_THE_MONTH", + "IS_IN_THE_QUARTER", + "IS_IN_THE_FISCAL_QUARTER", + "IS_IN_THE_FISCAL_YEAR", + "TIME_FOR_INTERVAL_DURATION", + "TIME_FOR_UNIT_DURATION", + "CUSTOM", + null + ] + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "kind", + "type" + ], + "additionalProperties": {} + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "type": { + "type": "string", + "enum": [ + "null" + ] + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "type" + ], + "additionalProperties": {} + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "treat_nulls_as_false": { + "type": "boolean" + }, + "type": { + "type": "string", + "enum": [ + "boolean" + ] + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "type" + ], + "additionalProperties": {} + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "disregard_limit": { + "type": "boolean" + }, + "field_name": { + "type": "string" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "query_id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "query" + ] + }, + "view_query": { + "type": "object", + "properties": { + "fields": { + "type": "array", + "items": { + "type": "string" + } + }, + "filters": { + "type": "object", + "additionalProperties": {}, + "default": {} + }, + "limit": { + "type": "number" + }, + "sorts": { + "type": "array", + "items": {}, + "default": [] + }, + "table": { + "type": "string" + } + }, + "required": [ + "fields" + ], + "additionalProperties": {} + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "type" + ], + "additionalProperties": {} + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "type": { + "type": "string", + "enum": [ + "user_attribute" + ] + }, + "user_attribute_name": { + "type": "string" + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "type", + "user_attribute_name" + ], + "additionalProperties": {} + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "conjunction": { + "type": "string", + "enum": [ + "OR", + "AND" + ] + }, + "filters": { + "type": "array", + "items": { + "$ref": "#/components/schemas/CompositeFilter" + } + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "type": { + "type": "string", + "enum": [ + "composite" + ] + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "conjunction", + "filters", + "type" + ], + "additionalProperties": {} + }, + { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "label": { + "type": "string" + }, + "display": { + "type": "string", + "enum": [ + "SELECT", + "BUTTON_TOGGLE" + ] + }, + "field": { + "type": "string" + }, + "kind": { + "type": "string", + "enum": [ + "FIELD", + "TIMEFRAME" + ] + }, + "options": { + "type": "array", + "items": { + "type": "object", + "properties": { + "isDimension": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "topicLabel": { + "type": "string" + }, + "value": { + "type": "string" + }, + "viewLabel": { + "type": "string" + } + }, + "required": [ + "label", + "value" + ] + } + }, + "type": { + "type": "string", + "enum": [ + "FIELD_SELECTION" + ] + } + }, + "required": [ + "id", + "field", + "kind", + "options", + "type" + ] + }, + { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "label": { + "type": "string" + }, + "display": { + "type": "string", + "enum": [ + "SELECT", + "BUTTON_TOGGLE" + ] + }, + "options": { + "type": "array", + "items": { + "type": "object", + "properties": { + "label": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "required": [ + "label", + "value" + ] + } + }, + "selectionMap": { + "type": "object", + "additionalProperties": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "type": { + "type": "string", + "enum": [ + "MULTI_FIELD_SELECTION" + ] + }, + "value": { + "type": "string" + } + }, + "required": [ + "id", + "options", + "selectionMap", + "type" + ] + }, + { + "type": "object", + "properties": { + "computations": { + "type": "array", + "items": { + "type": "object", + "properties": { + "filterId": { + "type": "string" + }, + "isDynamicPreviousPeriod": { + "type": "boolean" + }, + "periodsAgo": { + "type": [ + "number", + "null" + ] + }, + "timeUnitName": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "periodsAgo", + "timeUnitName" + ] + } + }, + "filterFieldName": { + "type": "string" + }, + "filterId": { + "type": "string" + }, + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "PERIOD_OVER_PERIOD" + ] + } + }, + "required": [ + "computations", + "filterFieldName", + "id", + "type" + ] + }, + { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "label": { + "type": "string" + }, + "options": { + "type": "array", + "items": { + "type": "object", + "properties": { + "isDimension": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "topicLabel": { + "type": "string" + }, + "value": { + "type": "string" + }, + "viewLabel": { + "type": "string" + } + }, + "required": [ + "label", + "value" + ] + } + }, + "type": { + "type": "string", + "enum": [ + "FIELD_PICKER" + ] + }, + "values": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "id", + "options", + "type" + ] + }, + { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "label": { + "type": "string" + }, + "conjunction": { + "type": "string", + "enum": [ + "OR" + ] + }, + "filters": { + "type": "array", + "items": { + "type": "object", + "properties": { + "fieldName": { + "type": "string" + }, + "filter": { + "$ref": "#/components/schemas/JsonValue" + }, + "id": { + "type": "string" + } + }, + "required": [ + "fieldName", + "filter", + "id" + ] + } + }, + "type": { + "type": "string", + "enum": [ + "MULTI_FIELD_FILTER" + ] + } + }, + "required": [ + "id", + "conjunction", + "filters", + "type" + ] + }, + { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "label": { + "type": "string" + }, + "fieldSelection": { + "oneOf": [ + { + "type": "object", + "properties": { + "mode": { + "type": "string", + "enum": [ + "full-model" + ] + } + }, + "required": [ + "mode" + ] + }, + { + "type": "object", + "properties": { + "mode": { + "type": "string", + "enum": [ + "auto" + ] + }, + "topics": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "mode", + "topics" + ] + }, + { + "type": "object", + "properties": { + "fields": { + "type": "array", + "items": { + "type": "object", + "properties": { + "fieldName": { + "type": "string" + }, + "topicName": { + "type": "string" + } + }, + "required": [ + "fieldName" + ] + } + }, + "mode": { + "type": "string", + "enum": [ + "specific" + ] + } + }, + "required": [ + "fields", + "mode" + ] + } + ] + }, + "includeViewNameInLabels": { + "type": "boolean" + }, + "type": { + "type": "string", + "enum": [ + "DYNAMIC_FILTER" + ] + } + }, + "required": [ + "id", + "fieldSelection", + "type" + ] + }, + { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "label": { + "type": "string" + }, + "defaultValue": { + "type": "integer", + "minimum": 1 + }, + "field": { + "type": "string" + }, + "max": { + "type": "integer", + "minimum": 1 + }, + "min": { + "type": "integer", + "minimum": 1 + }, + "type": { + "type": "string", + "enum": [ + "TOP_N" + ] + }, + "value": { + "type": "integer", + "minimum": 1 + } + }, + "required": [ + "id", + "defaultValue", + "field", + "type", + "value" + ] + } + ], + "description": "Filter or interactive control config. Discriminated by `type`: filter types (string, date, number, etc.) or control types (FIELD_SELECTION, PERIOD_OVER_PERIOD, etc.). Visibility is determined by placement in the filter-bar container." + }, + "map": { + "type": "object", + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "boolean", + "enum": [ + false + ] + } + ] + }, + "description": "Per-tile field overrides keyed by tab ID. Values are a field name (override) or false (exclude tile from control)." + } + }, + "required": [ + "config" + ] + }, + "JsonValue": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "type": "object", + "additionalProperties": { + "oneOf": [ + { + "$ref": "#/components/schemas/JsonValue" + }, + { + "type": "null" + } + ] + } + }, + { + "type": "array", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/JsonValue" + }, + { + "type": "null" + } + ] + } + } + ], + "description": "Arbitrary JSON value (string, number, boolean, null, object, or array)." + }, + "QueryPresentationsPatchExternal": { + "type": "object", + "properties": { + "data": { + "type": "object", + "additionalProperties": { + "$ref": "#/components/schemas/QueryPresentationPatchExternal" + }, + "description": "Query presentations keyed by tab ID. Shallow-merged by key — omitted keys are untouched; set to `null` to delete. Capped at 48 entries per patch. When the request carries no `containers` and the document has a dashboard layout, dashboard-eligible tiles added at new keys are auto-placed on the dashboard's first page (non-renderable types such as CSV / dataset / query-view / dbt tabs are stored but not placed), and containers created by auto-placement are removed when their tile is deleted — containers placed via an explicit `containers` write are left in the layout. When `containers` is present it fully defines the layout; on a workbook-only document (no layout yet) tiles are stored without placement." + }, + "order": { + "type": "array", + "items": { + "type": "string", + "pattern": "^[1-9][0-9]*$" + }, + "description": "Tab display order. When present, replaces the existing order." + } + } + }, + "QueryPresentationPatchExternal": { + "type": [ + "object", + "null" + ], + "properties": { + "aiConfig": { + "type": [ + "object", + "null" + ], + "properties": { + "description": { + "type": "object", + "properties": { + "aiContext": { + "type": "string" + }, + "enabled": { + "type": "boolean" + } + } + }, + "subTitle": { + "type": "object", + "properties": { + "aiContext": { + "type": "string" + }, + "enabled": { + "type": "boolean" + } + } + } + }, + "description": "AI-generated metadata config (subtitle/description auto-generation settings)." + }, + "automaticVis": { + "type": [ + "boolean", + "null" + ], + "description": "When true, the system automatically selects the best visualization type." + }, + "description": { + "type": [ + "string", + "null" + ], + "maxLength": 500, + "description": "User-provided tab description." + }, + "editingModelObjectName": { + "type": [ + "string", + "null" + ], + "description": "Model object (view/topic) currently being edited via the dataset/query-view editor. Applies only to dataset / query-view tabs — omitted from reads and rejected on patches for other tab types." + }, + "editingModelObjectNameChange": { + "type": [ + "string", + "null" + ], + "description": "Pending rename of the model object being edited. Applies only to dataset / query-view tabs — omitted from reads and rejected on patches for other tab types." + }, + "filterOrder": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Ordered list of filter field names controlling display order on this tab." + }, + "isSql": { + "type": [ + "boolean", + "null" + ], + "description": "Whether this tab is in raw SQL mode." + }, + "name": { + "type": "string", + "minLength": 1, + "maxLength": 144, + "description": "User-provided tab name." + }, + "prefersChart": { + "type": "boolean", + "description": "When true, the chart view is shown by default instead of the data table." + }, + "query": { + "type": [ + "object", + "null" + ], + "properties": { + "aiGenerated": { + "type": "boolean", + "description": "True when AI generated this query’s SQL; the AI SQL is shown in the advanced SQL box." + }, + "branch_id": { + "type": "string", + "description": "Branch model ID when querying against a model branch." + }, + "calculations": { + "type": "array", + "items": { + "type": "object", + "properties": { + "allow_refs_to_unselected_fields": { + "type": "boolean", + "description": "Set by the Kotlin parser when this calc references fields not selected at the top level (AI SQL-gen produces these; UI-authored calcs do not)." + }, + "calc_name": { + "type": "string", + "description": "Internal identifier for the calculation, used as the column alias." + }, + "description": { + "type": "string", + "description": "Description of the calculation." + }, + "format": { + "type": "string", + "description": "Number/date format string (e.g. \"#,##0.00\")." + }, + "label": { + "type": "string", + "description": "Display label shown in the UI." + }, + "original_formula": { + "type": "string", + "description": "The original Excel-style formula before parsing (e.g. \"=SUM(A1:A10)\")." + }, + "outside_pivot": { + "type": "boolean", + "description": "When true, the calculation is evaluated outside the pivot grouping." + }, + "pushdown": { + "type": [ + "boolean", + "null" + ], + "description": "Per-calc override for whether to evaluate before the row limit. `null` defers to the model-level default." + }, + "sql": { + "type": "string", + "description": "Compiled SQL string produced from the formula." + }, + "sql_expression": { + "description": "Parsed SQL expression tree (serialized)." + }, + "swallow_errors": { + "type": "boolean", + "description": "When true, calculation errors are silently swallowed instead of surfaced." + } + }, + "required": [ + "calc_name" + ], + "additionalProperties": {} + }, + "description": "Table calculations attached to this query." + }, + "column_limit": { + "type": "number", + "description": "Max number of pivot columns to return." + }, + "column_totals": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "aggregation" + ] + } + }, + "required": [ + "type" + ] + }, + "description": "Column-level aggregation totals, keyed by field name." + }, + "controls": { + "type": "array", + "items": { + "oneOf": [ + { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "hidden": { + "type": "boolean" + }, + "id": { + "type": "string" + }, + "label": { + "type": "string" + }, + "display": { + "type": "string", + "enum": [ + "SELECT", + "BUTTON_TOGGLE" + ] + }, + "field": { + "type": "string" + }, + "kind": { + "type": "string", + "enum": [ + "FIELD", + "TIMEFRAME" + ] + }, + "options": { + "type": "array", + "items": { + "type": "object", + "properties": { + "isDimension": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "topicLabel": { + "type": "string" + }, + "value": { + "type": "string" + }, + "viewLabel": { + "type": "string" + } + }, + "required": [ + "label", + "value" + ] + } + }, + "type": { + "type": "string", + "enum": [ + "FIELD_SELECTION" + ] + } + }, + "required": [ + "id", + "field", + "kind", + "options", + "type" + ] + }, + { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "hidden": { + "type": "boolean" + }, + "id": { + "type": "string" + }, + "label": { + "type": "string" + }, + "display": { + "type": "string", + "enum": [ + "SELECT", + "BUTTON_TOGGLE" + ] + }, + "options": { + "type": "array", + "items": { + "type": "object", + "properties": { + "label": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "required": [ + "label", + "value" + ] + } + }, + "selectionMap": { + "type": "object", + "additionalProperties": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "type": { + "type": "string", + "enum": [ + "MULTI_FIELD_SELECTION" + ] + }, + "value": { + "type": "string" + } + }, + "required": [ + "id", + "options", + "selectionMap", + "type" + ] + }, + { + "type": "object", + "properties": { + "computations": { + "type": "array", + "items": { + "type": "object", + "properties": { + "filterId": { + "type": "string" + }, + "isDynamicPreviousPeriod": { + "type": "boolean" + }, + "periodsAgo": { + "type": [ + "number", + "null" + ] + }, + "timeUnitName": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "periodsAgo", + "timeUnitName" + ] + } + }, + "filterFieldName": { + "type": "string" + }, + "filterId": { + "type": "string" + }, + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "PERIOD_OVER_PERIOD" + ] + } + }, + "required": [ + "computations", + "filterFieldName", + "id", + "type" + ] + }, + { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "hidden": { + "type": "boolean" + }, + "id": { + "type": "string" + }, + "label": { + "type": "string" + }, + "options": { + "type": "array", + "items": { + "type": "object", + "properties": { + "isDimension": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "topicLabel": { + "type": "string" + }, + "value": { + "type": "string" + }, + "viewLabel": { + "type": "string" + } + }, + "required": [ + "label", + "value" + ] + } + }, + "type": { + "type": "string", + "enum": [ + "FIELD_PICKER" + ] + }, + "values": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "id", + "options", + "type" + ] + }, + { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "hidden": { + "type": "boolean" + }, + "id": { + "type": "string" + }, + "label": { + "type": "string" + }, + "conjunction": { + "type": "string", + "enum": [ + "OR" + ] + }, + "filters": { + "type": "array", + "items": { + "type": "object", + "properties": { + "fieldName": { + "type": "string" + }, + "filter": { + "$ref": "#/components/schemas/JsonValue" + }, + "id": { + "type": "string" + } + }, + "required": [ + "fieldName", + "filter", + "id" + ] + } + }, + "type": { + "type": "string", + "enum": [ + "MULTI_FIELD_FILTER" + ] + } + }, + "required": [ + "id", + "conjunction", + "filters", + "type" + ] + }, + { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "hidden": { + "type": "boolean" + }, + "id": { + "type": "string" + }, + "label": { + "type": "string" + }, + "fieldSelection": { + "oneOf": [ + { + "type": "object", + "properties": { + "mode": { + "type": "string", + "enum": [ + "full-model" + ] + } + }, + "required": [ + "mode" + ] + }, + { + "type": "object", + "properties": { + "mode": { + "type": "string", + "enum": [ + "auto" + ] + }, + "topics": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "mode", + "topics" + ] + }, + { + "type": "object", + "properties": { + "fields": { + "type": "array", + "items": { + "type": "object", + "properties": { + "fieldName": { + "type": "string" + }, + "topicName": { + "type": "string" + } + }, + "required": [ + "fieldName" + ] + } + }, + "mode": { + "type": "string", + "enum": [ + "specific" + ] + } + }, + "required": [ + "fields", + "mode" + ] + } + ] + }, + "includeViewNameInLabels": { + "type": "boolean" + }, + "type": { + "type": "string", + "enum": [ + "DYNAMIC_FILTER" + ] + } + }, + "required": [ + "id", + "fieldSelection", + "type" + ] + }, + { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "hidden": { + "type": "boolean" + }, + "id": { + "type": "string" + }, + "label": { + "type": "string" + }, + "defaultValue": { + "type": "integer", + "minimum": 1 + }, + "field": { + "type": "string" + }, + "max": { + "type": "integer", + "minimum": 1 + }, + "min": { + "type": "integer", + "minimum": 1 + }, + "type": { + "type": "string", + "enum": [ + "TOP_N" + ] + }, + "value": { + "type": "integer", + "minimum": 1 + } + }, + "required": [ + "id", + "defaultValue", + "field", + "type", + "value" + ] + } + ] + }, + "description": "Interactive controls (field selectors, PoP controls) attached to this query." + }, + "cube_metadata": { + "type": "object", + "properties": { + "cube_name": { + "type": "string" + }, + "hash_key": { + "type": "string" + }, + "topic_name": { + "type": "string" + } + }, + "required": [ + "cube_name", + "hash_key", + "topic_name" + ], + "additionalProperties": {}, + "description": "Cube-specific metadata (topic name, cube name, hash key) for cube-backed queries." + }, + "custom_summary_types": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Per-field custom summary functions (e.g. SUM, AVG, COUNT)." + }, + "dbtFileName": { + "type": "string", + "description": "dbt file name when this query is backed by a dbt model." + }, + "dbtMode": { + "type": "boolean", + "description": "Whether this query is in dbt mode." + }, + "default_group_by": { + "type": "boolean", + "description": "When true, all dimensions are implicitly included in GROUP BY." + }, + "dimensionIndex": { + "type": "number", + "description": "Index of the primary dimension used for result ordering." + }, + "executableSQL": { + "type": "string", + "description": "Server-compiled SQL string (read-only, set by the backend)." + }, + "fields": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Model field names selected for the query (dimensions + measures)." + }, + "fill_fields": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Fields whose missing date/time values should be filled with nulls to create continuous series." + }, + "filters": { + "type": "object", + "additionalProperties": { + "oneOf": [ + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "case_insensitive": { + "type": "boolean" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "kind": { + "type": "string", + "enum": [ + "CONTAINS", + "ENDS_WITH", + "STARTS_WITH", + "EQUALS", + "IS_EMPTY", + "SQL_LIKE" + ] + }, + "type": { + "type": "string", + "enum": [ + "string" + ] + }, + "values": { + "type": "array", + "items": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "hidden": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "kind", + "type", + "values" + ], + "additionalProperties": {} + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "is_inclusive": { + "type": "boolean" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "kind": { + "type": "string", + "enum": [ + "LESS_THAN", + "GREATER_THAN", + "EQUALS", + "BETWEEN" + ] + }, + "type": { + "type": "string", + "enum": [ + "number" + ] + }, + "values": { + "type": "array", + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + } + ] + } + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "hidden": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "kind", + "type", + "values" + ], + "additionalProperties": {} + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "isFiscal": { + "type": "boolean" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "kind": { + "type": "string", + "enum": [ + "IS_ON_DAY_OF_WEEK", + "IS_ON_DAY_OF_QUARTER", + "IS_IN_MONTH_OF_YEAR", + "IS_ON_DAY_OF_YEAR", + "IS_AT_HOUR_OF_DAY", + "IS_IN_QUARTER_OF_YEAR", + "IS_IN_WEEK_OF_YEAR", + "IS_ON_DAY_OF_MONTH", + "BETWEEN", + "ON_OR_AFTER", + "BEFORE", + "TIME_FOR_INTERVAL_DURATION", + "TIME_FOR_UNIT_DURATION", + "QUERY_OFFSET" + ] + }, + "left_side": { + "type": [ + "string", + "null" + ] + }, + "offset_interval_string": { + "type": [ + "string", + "null" + ] + }, + "right_side": { + "type": [ + "string", + "null" + ] + }, + "type": { + "type": "string", + "enum": [ + "date" + ] + }, + "ui_type": { + "type": [ + "string", + "null" + ], + "enum": [ + "ANY_TIME", + "BEFORE", + "BETWEEN", + "MONTH_OF_YEAR", + "PAST", + "YEAR", + "DAY", + "IS_ON_DAY_OF_WEEK", + "ON_OR_AFTER", + "IS_IN_THE_MONTH", + "IS_IN_THE_QUARTER", + "IS_IN_THE_FISCAL_QUARTER", + "IS_IN_THE_FISCAL_YEAR", + "TIME_FOR_INTERVAL_DURATION", + "TIME_FOR_UNIT_DURATION", + "CUSTOM", + null + ] + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "hidden": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "kind", + "type" + ], + "additionalProperties": {} + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "type": { + "type": "string", + "enum": [ + "null" + ] + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "hidden": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "type" + ], + "additionalProperties": {} + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "treat_nulls_as_false": { + "type": "boolean" + }, + "type": { + "type": "string", + "enum": [ + "boolean" + ] + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "hidden": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "type" + ], + "additionalProperties": {} + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "disregard_limit": { + "type": "boolean" + }, + "field_name": { + "type": "string" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "query_id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "query" + ] + }, + "view_query": { + "type": "object", + "properties": { + "fields": { + "type": "array", + "items": { + "type": "string" + } + }, + "filters": { + "type": "object", + "additionalProperties": {}, + "default": {} + }, + "limit": { + "type": "number" + }, + "sorts": { + "type": "array", + "items": {}, + "default": [] + }, + "table": { + "type": "string" + } + }, + "required": [ + "fields" + ], + "additionalProperties": {} + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "hidden": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "type" + ], + "additionalProperties": {} + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "type": { + "type": "string", + "enum": [ + "user_attribute" + ] + }, + "user_attribute_name": { + "type": "string" + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "hidden": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "type", + "user_attribute_name" + ], + "additionalProperties": {} + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "conjunction": { + "type": "string", + "enum": [ + "OR", + "AND" + ] + }, + "filters": { + "type": "array", + "items": { + "$ref": "#/components/schemas/CompositeFilter" + } + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "type": { + "type": "string", + "enum": [ + "composite" + ] + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "hidden": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "conjunction", + "filters", + "type" + ], + "additionalProperties": {} + } + ] + }, + "description": "Query filters keyed by filter ID." + }, + "filtersUsedInSql": { + "type": "object", + "additionalProperties": { + "oneOf": [ + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "case_insensitive": { + "type": "boolean" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "kind": { + "type": "string", + "enum": [ + "CONTAINS", + "ENDS_WITH", + "STARTS_WITH", + "EQUALS", + "IS_EMPTY", + "SQL_LIKE" + ] + }, + "type": { + "type": "string", + "enum": [ + "string" + ] + }, + "values": { + "type": "array", + "items": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "hidden": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "kind", + "type", + "values" + ], + "additionalProperties": {} + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "is_inclusive": { + "type": "boolean" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "kind": { + "type": "string", + "enum": [ + "LESS_THAN", + "GREATER_THAN", + "EQUALS", + "BETWEEN" + ] + }, + "type": { + "type": "string", + "enum": [ + "number" + ] + }, + "values": { + "type": "array", + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + } + ] + } + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "hidden": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "kind", + "type", + "values" + ], + "additionalProperties": {} + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "isFiscal": { + "type": "boolean" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "kind": { + "type": "string", + "enum": [ + "IS_ON_DAY_OF_WEEK", + "IS_ON_DAY_OF_QUARTER", + "IS_IN_MONTH_OF_YEAR", + "IS_ON_DAY_OF_YEAR", + "IS_AT_HOUR_OF_DAY", + "IS_IN_QUARTER_OF_YEAR", + "IS_IN_WEEK_OF_YEAR", + "IS_ON_DAY_OF_MONTH", + "BETWEEN", + "ON_OR_AFTER", + "BEFORE", + "TIME_FOR_INTERVAL_DURATION", + "TIME_FOR_UNIT_DURATION", + "QUERY_OFFSET" + ] + }, + "left_side": { + "type": [ + "string", + "null" + ] + }, + "offset_interval_string": { + "type": [ + "string", + "null" + ] + }, + "right_side": { + "type": [ + "string", + "null" + ] + }, + "type": { + "type": "string", + "enum": [ + "date" + ] + }, + "ui_type": { + "type": [ + "string", + "null" + ], + "enum": [ + "ANY_TIME", + "BEFORE", + "BETWEEN", + "MONTH_OF_YEAR", + "PAST", + "YEAR", + "DAY", + "IS_ON_DAY_OF_WEEK", + "ON_OR_AFTER", + "IS_IN_THE_MONTH", + "IS_IN_THE_QUARTER", + "IS_IN_THE_FISCAL_QUARTER", + "IS_IN_THE_FISCAL_YEAR", + "TIME_FOR_INTERVAL_DURATION", + "TIME_FOR_UNIT_DURATION", + "CUSTOM", + null + ] + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "hidden": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "kind", + "type" + ], + "additionalProperties": {} + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "type": { + "type": "string", + "enum": [ + "null" + ] + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "hidden": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "type" + ], + "additionalProperties": {} + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "treat_nulls_as_false": { + "type": "boolean" + }, + "type": { + "type": "string", + "enum": [ + "boolean" + ] + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "hidden": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "type" + ], + "additionalProperties": {} + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "disregard_limit": { + "type": "boolean" + }, + "field_name": { + "type": "string" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "query_id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "query" + ] + }, + "view_query": { + "type": "object", + "properties": { + "fields": { + "type": "array", + "items": { + "type": "string" + } + }, + "filters": { + "type": "object", + "additionalProperties": {}, + "default": {} + }, + "limit": { + "type": "number" + }, + "sorts": { + "type": "array", + "items": {}, + "default": [] + }, + "table": { + "type": "string" + } + }, + "required": [ + "fields" + ], + "additionalProperties": {} + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "hidden": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "type" + ], + "additionalProperties": {} + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "type": { + "type": "string", + "enum": [ + "user_attribute" + ] + }, + "user_attribute_name": { + "type": "string" + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "hidden": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "type", + "user_attribute_name" + ], + "additionalProperties": {} + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "conjunction": { + "type": "string", + "enum": [ + "OR", + "AND" + ] + }, + "filters": { + "type": "array", + "items": { + "$ref": "#/components/schemas/CompositeFilter" + } + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "type": { + "type": "string", + "enum": [ + "composite" + ] + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "hidden": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "conjunction", + "filters", + "type" + ], + "additionalProperties": {} + } + ] + }, + "description": "Filters that were embedded directly in raw SQL (read-only)." + }, + "join_paths_from_topic_name": { + "type": "string", + "description": "Topic name that determines join path precedence for parsed SQL queries." + }, + "join_via_map": { + "type": "object", + "additionalProperties": { + "type": "array", + "items": { + "type": "string" + } + }, + "description": "Virtual topic join path overrides, keyed by view name to ordered join path." + }, + "limit": { + "type": "number", + "description": "Row limit for the query." + }, + "manualSort": { + "type": "boolean", + "description": "When true, the user has explicitly set a custom sort order." + }, + "metadata": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "format": { + "type": "string" + }, + "label": { + "type": "string" + }, + "order": { + "type": "number" + } + }, + "additionalProperties": {} + }, + "description": "Per-field display metadata (format, label, order)." + }, + "offset": { + "type": "number", + "description": "Row offset for pagination." + }, + "parsed": { + "type": "boolean", + "description": "Whether this raw SQL query has been parsed into a semantic query." + }, + "periodOverPeriodTransposed": { + "type": "boolean", + "description": "Whether the period-over-period comparison columns are transposed." + }, + "period_over_period_computations": { + "type": "array", + "items": { + "type": "object", + "properties": { + "date_filter_field_name": { + "type": "string", + "description": "The date dimension field this comparison is anchored to." + }, + "date_filter_id": { + "type": "string", + "description": "ID of the date filter being offset (if backed by a dashboard filter)." + }, + "is_dynamic_previous_period": { + "type": "boolean", + "description": "When true, the previous period is calculated dynamically relative to the current filter range." + }, + "periods_ago": { + "type": [ + "number", + "null" + ], + "description": "How many periods back to compare (e.g. 1 = previous period). Null if not set." + }, + "time_unit_name": { + "type": [ + "string", + "null" + ], + "description": "Time grain for the offset (e.g. \"month\", \"year\"). Null if not set." + } + }, + "required": [ + "date_filter_field_name", + "periods_ago", + "time_unit_name" + ], + "additionalProperties": {} + }, + "description": "Period-over-period comparison configurations." + }, + "pivots": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Field names to pivot on (columns become values)." + }, + "rewriteSql": { + "type": "boolean", + "description": "When true, the backend should rewrite/optimize the SQL." + }, + "row_totals": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "aggregation" + ] + } + }, + "required": [ + "type" + ] + }, + "description": "Row-level aggregation totals, keyed by field name." + }, + "sorts": { + "type": "array", + "items": { + "type": "object", + "properties": { + "column_name": { + "type": "string", + "description": "The model field name to sort by." + }, + "is_column_sort": { + "type": "boolean", + "description": "When true, this sort targets a pivoted column rather than a row dimension." + }, + "pivot_value_map": { + "type": "object", + "additionalProperties": { + "type": [ + "string", + "null" + ] + }, + "description": "Maps pivot field names to specific pivot values, scoping the sort to a single pivot column." + }, + "sort_descending": { + "type": "boolean", + "description": "When true, sort order is descending." + }, + "subtotal_sort": { + "type": "string", + "description": "Field name whose subtotal row should be used as the sort key." + } + }, + "required": [ + "column_name", + "sort_descending" + ], + "additionalProperties": {} + }, + "description": "Sort clauses applied to the query result set." + }, + "sqlSortsEnabled": { + "type": "boolean", + "description": "Whether user-created sorts are enabled on a raw SQL query." + }, + "staticQueryReferences": { + "type": "object", + "additionalProperties": {}, + "description": "Pre-computed query references for AI chat context. Inner shape is `OmniQuery & { model_id: string }`; left as `unknown` to avoid a recursive zod schema. Validated structurally by consumers when they execute the referenced sub-queries." + }, + "table": { + "type": "string", + "description": "Base view (table) name in the model." + }, + "transposed_measures": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Measure field names that have been transposed into rows." + }, + "userEditedSQL": { + "type": "string", + "description": "User-authored raw SQL (empty string when not in SQL mode)." + }, + "version": { + "type": "number", + "description": "Schema version for migration support." + } + }, + "required": [ + "calculations", + "column_totals", + "fields", + "fill_fields", + "filters", + "pivots", + "row_totals", + "sorts", + "table", + "userEditedSQL" + ], + "additionalProperties": {}, + "description": "The semantic query for this tab, minus the server-owned workbook model anchors (modelId / model_extension_id). Omitted on a no-op replay; the server anchors new/changed tiles to the draft." + }, + "resultConfig": { + "type": "object", + "additionalProperties": {}, + "description": "Result display configuration (column widths, frozen columns, conditional formatting, number formatting, etc.)." + }, + "subTitle": { + "type": [ + "string", + "null" + ], + "maxLength": 250, + "description": "User-provided tab subtitle." + }, + "topicName": { + "type": [ + "string", + "null" + ], + "description": "The topic (explore) this query is built on." + }, + "type": { + "type": "string", + "enum": [ + "blank", + "csv", + "query", + "dataset", + "spreadsheet", + "sql", + "dbt", + "query-view", + "linked", + "app" + ], + "description": "The query presentation type (e.g. SEMANTIC, SQL, LINKED, SPREADSHEET)." + }, + "visConfig": { + "type": [ + "object", + "null" + ], + "properties": { + "chartType": { + "type": [ + "string", + "null" + ], + "enum": [ + "auto", + "area", + "areaStacked", + "areaStackedPercentage", + "bar", + "barLine", + "barGrouped", + "barStacked", + "barStackedPercentage", + "boxplot", + "code", + "column", + "columnGrouped", + "columnStacked", + "columnStackedPercentage", + "heatmap", + "kpi", + "line", + "lineColor", + "map", + "regionMap", + "markdown", + "omni-ai-summary-markdown", + "pie", + "funnel", + "sankey", + "point", + "pointColor", + "pointSize", + "pointSizeColor", + "singleRecord", + "omni-spreadsheet", + "summaryValue", + "svgMap", + "table", + null + ], + "description": "High-level chart type (e.g. \"bar\", \"line\", \"area\")." + }, + "fields": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Field names used in the visualization axes/series." + }, + "version": { + "type": "number", + "description": "Schema version for vis config migration." + }, + "visConfig": { + "type": "object", + "properties": { + "visType": { + "type": [ + "string", + "null" + ], + "enum": [ + "vegalite", + "omni-ai-summary-markdown", + "basic", + "omni-kpi", + "map", + "omni-markdown", + "funnel", + "sankey", + "single-record", + "svg-map", + "omni-spreadsheet", + "spreadsheet-tab", + "summary-value", + "omni-table", + "app", + null + ], + "description": "The visualization type (e.g. \"basic\", \"omni-table\")." + } + }, + "additionalProperties": {}, + "description": "Inner visualization config — structure varies by visType." + } + }, + "additionalProperties": {}, + "description": "Visualization configuration for the tile." + }, + "sourceQueryPresentationKey": { + "type": [ + "string", + "null" + ], + "pattern": "^[1-9][0-9]*$", + "description": "For LINKED-type tabs, the record key — the same identifier used as a `queryPresentations.data` key — of the source tile whose query this tab reuses. Null for all other tab types. This is a tile record key, NOT a positional index into `order`." + } + }, + "required": [ + "type" + ], + "additionalProperties": false + }, + "SettingsPatchExternal": { + "type": "object", + "properties": { + "crossfilterEnabled": { + "type": "boolean", + "description": "When true, clicking a value in one tile filters all other tiles on the dashboard." + }, + "customText": { + "type": [ + "object", + "null" + ], + "properties": { + "queryError": { + "type": "string", + "description": "Custom text shown when a query errors, replacing the default error text." + }, + "queryNoResults": { + "type": "string", + "description": "Custom text shown when a query returns no results, replacing the default empty state." + } + }, + "description": "Custom text replacing default UI strings on the dashboard, e.g. when queries error or return no results." + }, + "facetFilters": { + "type": "boolean", + "description": "When true, dashboard filters are applied per-facet when faceting is active." + }, + "refreshInterval": { + "type": [ + "number", + "null" + ], + "description": "Auto-refresh interval in seconds. Null disables auto-refresh." + }, + "runQueriesOn": { + "type": [ + "string", + "null" + ], + "enum": [ + "current-page", + "all-pages", + null + ], + "description": "Controls whether dashboard queries execute on the visible page or across all pages." + } + }, + "description": "Document settings. Shallow-merged with the existing settings." + }, + "DocumentsV2ReadResponse": { + "type": "object", + "properties": { + "containers": { + "$ref": "#/components/schemas/Containers" + }, + "controls": { + "$ref": "#/components/schemas/ControlsReadExternal" + }, + "description": { + "type": [ + "string", + "null" + ], + "description": "Document description." + }, + "name": { + "type": "string", + "maxLength": 254, + "description": "Document name." + }, + "queryPresentations": { + "$ref": "#/components/schemas/QueryPresentationsReadExternal" + }, + "settings": { + "$ref": "#/components/schemas/SettingsReadExternal" + } + }, + "required": [ + "description", + "name", + "queryPresentations" + ] + }, + "ControlsReadExternal": { + "type": "object", + "properties": { + "data": { + "type": "object", + "additionalProperties": { + "$ref": "#/components/schemas/ControlReadExternal" + }, + "description": "Controls keyed by control ID." + }, + "order": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Display order for controls." + } + }, + "required": [ + "data", + "order" + ] + }, + "ControlReadExternal": { + "type": "object", + "properties": { + "config": { + "oneOf": [ + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "case_insensitive": { + "type": "boolean" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "kind": { + "type": "string", + "enum": [ + "CONTAINS", + "ENDS_WITH", + "STARTS_WITH", + "EQUALS", + "IS_EMPTY", + "SQL_LIKE" + ] + }, + "type": { + "type": "string", + "enum": [ + "string" + ] + }, + "values": { + "type": "array", + "items": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "kind", + "type", + "values" + ], + "additionalProperties": {} + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "is_inclusive": { + "type": "boolean" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "kind": { + "type": "string", + "enum": [ + "LESS_THAN", + "GREATER_THAN", + "EQUALS", + "BETWEEN" + ] + }, + "type": { + "type": "string", + "enum": [ + "number" + ] + }, + "values": { + "type": "array", + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + } + ] + } + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "kind", + "type", + "values" + ], + "additionalProperties": {} + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "isFiscal": { + "type": "boolean" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "kind": { + "type": "string", + "enum": [ + "IS_ON_DAY_OF_WEEK", + "IS_ON_DAY_OF_QUARTER", + "IS_IN_MONTH_OF_YEAR", + "IS_ON_DAY_OF_YEAR", + "IS_AT_HOUR_OF_DAY", + "IS_IN_QUARTER_OF_YEAR", + "IS_IN_WEEK_OF_YEAR", + "IS_ON_DAY_OF_MONTH", + "BETWEEN", + "ON_OR_AFTER", + "BEFORE", + "TIME_FOR_INTERVAL_DURATION", + "TIME_FOR_UNIT_DURATION", + "QUERY_OFFSET" + ] + }, + "left_side": { + "type": [ + "string", + "null" + ] + }, + "offset_interval_string": { + "type": [ + "string", + "null" + ] + }, + "right_side": { + "type": [ + "string", + "null" + ] + }, + "type": { + "type": "string", + "enum": [ + "date" + ] + }, + "ui_type": { + "type": [ + "string", + "null" + ], + "enum": [ + "ANY_TIME", + "BEFORE", + "BETWEEN", + "MONTH_OF_YEAR", + "PAST", + "YEAR", + "DAY", + "IS_ON_DAY_OF_WEEK", + "ON_OR_AFTER", + "IS_IN_THE_MONTH", + "IS_IN_THE_QUARTER", + "IS_IN_THE_FISCAL_QUARTER", + "IS_IN_THE_FISCAL_YEAR", + "TIME_FOR_INTERVAL_DURATION", + "TIME_FOR_UNIT_DURATION", + "CUSTOM", + null + ] + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "kind", + "type" + ], + "additionalProperties": {} + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "type": { + "type": "string", + "enum": [ + "null" + ] + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "type" + ], + "additionalProperties": {} + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "treat_nulls_as_false": { + "type": "boolean" + }, + "type": { + "type": "string", + "enum": [ + "boolean" + ] + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "type" + ], + "additionalProperties": {} + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "disregard_limit": { + "type": "boolean" + }, + "field_name": { + "type": "string" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "query_id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "query" + ] + }, + "view_query": { + "type": "object", + "properties": { + "fields": { + "type": "array", + "items": { + "type": "string" + } + }, + "filters": { + "type": "object", + "additionalProperties": {}, + "default": {} + }, + "limit": { + "type": "number" + }, + "sorts": { + "type": "array", + "items": {}, + "default": [] + }, + "table": { + "type": "string" + } + }, + "required": [ + "fields" + ], + "additionalProperties": {} + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "type" + ], + "additionalProperties": {} + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "type": { + "type": "string", + "enum": [ + "user_attribute" + ] + }, + "user_attribute_name": { + "type": "string" + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "type", + "user_attribute_name" + ], + "additionalProperties": {} + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "conjunction": { + "type": "string", + "enum": [ + "OR", + "AND" + ] + }, + "filters": { + "type": "array", + "items": { + "$ref": "#/components/schemas/CompositeFilter" + } + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "type": { + "type": "string", + "enum": [ + "composite" + ] + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "conjunction", + "filters", + "type" + ], + "additionalProperties": {} + }, + { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "label": { + "type": "string" + }, + "display": { + "type": "string", + "enum": [ + "SELECT", + "BUTTON_TOGGLE" + ] + }, + "field": { + "type": "string" + }, + "kind": { + "type": "string", + "enum": [ + "FIELD", + "TIMEFRAME" + ] + }, + "options": { + "type": "array", + "items": { + "type": "object", + "properties": { + "isDimension": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "topicLabel": { + "type": "string" + }, + "value": { + "type": "string" + }, + "viewLabel": { + "type": "string" + } + }, + "required": [ + "label", + "value" + ] + } + }, + "type": { + "type": "string", + "enum": [ + "FIELD_SELECTION" + ] + } + }, + "required": [ + "id", + "field", + "kind", + "options", + "type" + ] + }, + { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "label": { + "type": "string" + }, + "display": { + "type": "string", + "enum": [ + "SELECT", + "BUTTON_TOGGLE" + ] + }, + "options": { + "type": "array", + "items": { + "type": "object", + "properties": { + "label": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "required": [ + "label", + "value" + ] + } + }, + "selectionMap": { + "type": "object", + "additionalProperties": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "type": { + "type": "string", + "enum": [ + "MULTI_FIELD_SELECTION" + ] + }, + "value": { + "type": "string" + } + }, + "required": [ + "id", + "options", + "selectionMap", + "type" + ] + }, + { + "type": "object", + "properties": { + "computations": { + "type": "array", + "items": { + "type": "object", + "properties": { + "filterId": { + "type": "string" + }, + "isDynamicPreviousPeriod": { + "type": "boolean" + }, + "periodsAgo": { + "type": [ + "number", + "null" + ] + }, + "timeUnitName": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "periodsAgo", + "timeUnitName" + ] + } + }, + "filterFieldName": { + "type": "string" + }, + "filterId": { + "type": "string" + }, + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "PERIOD_OVER_PERIOD" + ] + } + }, + "required": [ + "computations", + "filterFieldName", + "id", + "type" + ] + }, + { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "label": { + "type": "string" + }, + "options": { + "type": "array", + "items": { + "type": "object", + "properties": { + "isDimension": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "topicLabel": { + "type": "string" + }, + "value": { + "type": "string" + }, + "viewLabel": { + "type": "string" + } + }, + "required": [ + "label", + "value" + ] + } + }, + "type": { + "type": "string", + "enum": [ + "FIELD_PICKER" + ] + }, + "values": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "id", + "options", + "type" + ] + }, + { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "label": { + "type": "string" + }, + "conjunction": { + "type": "string", + "enum": [ + "OR" + ] + }, + "filters": { + "type": "array", + "items": { + "type": "object", + "properties": { + "fieldName": { + "type": "string" + }, + "filter": { + "$ref": "#/components/schemas/JsonValue" + }, + "id": { + "type": "string" + } + }, + "required": [ + "fieldName", + "filter", + "id" + ] + } + }, + "type": { + "type": "string", + "enum": [ + "MULTI_FIELD_FILTER" + ] + } + }, + "required": [ + "id", + "conjunction", + "filters", + "type" + ] + }, + { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "label": { + "type": "string" + }, + "fieldSelection": { + "oneOf": [ + { + "type": "object", + "properties": { + "mode": { + "type": "string", + "enum": [ + "full-model" + ] + } + }, + "required": [ + "mode" + ] + }, + { + "type": "object", + "properties": { + "mode": { + "type": "string", + "enum": [ + "auto" + ] + }, + "topics": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "mode", + "topics" + ] + }, + { + "type": "object", + "properties": { + "fields": { + "type": "array", + "items": { + "type": "object", + "properties": { + "fieldName": { + "type": "string" + }, + "topicName": { + "type": "string" + } + }, + "required": [ + "fieldName" + ] + } + }, + "mode": { + "type": "string", + "enum": [ + "specific" + ] + } + }, + "required": [ + "fields", + "mode" + ] + } + ] + }, + "includeViewNameInLabels": { + "type": "boolean" + }, + "type": { + "type": "string", + "enum": [ + "DYNAMIC_FILTER" + ] + } + }, + "required": [ + "id", + "fieldSelection", + "type" + ] + }, + { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "label": { + "type": "string" + }, + "defaultValue": { + "type": "integer", + "minimum": 1 + }, + "field": { + "type": "string" + }, + "max": { + "type": "integer", + "minimum": 1 + }, + "min": { + "type": "integer", + "minimum": 1 + }, + "type": { + "type": "string", + "enum": [ + "TOP_N" + ] + }, + "value": { + "type": "integer", + "minimum": 1 + } + }, + "required": [ + "id", + "defaultValue", + "field", + "type", + "value" + ] + } + ], + "description": "Filter or interactive control config. Discriminated by `type`: filter types (string, date, number, etc.) or control types (FIELD_SELECTION, PERIOD_OVER_PERIOD, etc.). Visibility is determined by placement in the filter-bar container." + }, + "map": { + "type": "object", + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "boolean", + "enum": [ + false + ] + } + ] + }, + "description": "Per-tile field overrides keyed by tab ID. Values are a field name (override) or false (exclude tile from control)." + } + }, + "required": [ + "config" + ] + }, + "QueryPresentationsReadExternal": { + "type": "object", + "properties": { + "data": { + "type": "object", + "additionalProperties": { + "$ref": "#/components/schemas/QueryPresentationReadExternal" + }, + "description": "Query presentations keyed by tab ID." + }, + "order": { + "type": "array", + "items": { + "type": "string", + "pattern": "^[1-9][0-9]*$" + }, + "description": "Tab display order." + } + }, + "required": [ + "data", + "order" + ] + }, + "QueryPresentationReadExternal": { + "type": "object", + "properties": { + "aiConfig": { + "type": [ + "object", + "null" + ], + "properties": { + "description": { + "type": "object", + "properties": { + "aiContext": { + "type": "string" + }, + "enabled": { + "type": "boolean" + } + } + }, + "subTitle": { + "type": "object", + "properties": { + "aiContext": { + "type": "string" + }, + "enabled": { + "type": "boolean" + } + } + } + }, + "description": "AI-generated metadata config (subtitle/description auto-generation settings)." + }, + "automaticVis": { + "type": [ + "boolean", + "null" + ], + "description": "When true, the system automatically selects the best visualization type." + }, + "description": { + "type": [ + "string", + "null" + ], + "maxLength": 500, + "description": "User-provided tab description." + }, + "editingModelObjectName": { + "type": [ + "string", + "null" + ], + "description": "Model object (view/topic) currently being edited via the dataset/query-view editor. Applies only to dataset / query-view tabs — omitted from reads and rejected on patches for other tab types." + }, + "editingModelObjectNameChange": { + "type": [ + "string", + "null" + ], + "description": "Pending rename of the model object being edited. Applies only to dataset / query-view tabs — omitted from reads and rejected on patches for other tab types." + }, + "filterOrder": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Ordered list of filter field names controlling display order on this tab." + }, + "isSql": { + "type": [ + "boolean", + "null" + ], + "description": "Whether this tab is in raw SQL mode." + }, + "name": { + "type": "string", + "minLength": 1, + "maxLength": 144, + "description": "User-provided tab name." + }, + "prefersChart": { + "type": "boolean", + "description": "When true, the chart view is shown by default instead of the data table." + }, + "query": { + "type": [ + "object", + "null" + ], + "properties": { + "aiGenerated": { + "type": "boolean", + "description": "True when AI generated this query’s SQL; the AI SQL is shown in the advanced SQL box." + }, + "branch_id": { + "type": "string", + "description": "Branch model ID when querying against a model branch." + }, + "calculations": { + "type": "array", + "items": { + "type": "object", + "properties": { + "allow_refs_to_unselected_fields": { + "type": "boolean", + "description": "Set by the Kotlin parser when this calc references fields not selected at the top level (AI SQL-gen produces these; UI-authored calcs do not)." + }, + "calc_name": { + "type": "string", + "description": "Internal identifier for the calculation, used as the column alias." + }, + "description": { + "type": "string", + "description": "Description of the calculation." + }, + "format": { + "type": "string", + "description": "Number/date format string (e.g. \"#,##0.00\")." + }, + "label": { + "type": "string", + "description": "Display label shown in the UI." + }, + "original_formula": { + "type": "string", + "description": "The original Excel-style formula before parsing (e.g. \"=SUM(A1:A10)\")." + }, + "outside_pivot": { + "type": "boolean", + "description": "When true, the calculation is evaluated outside the pivot grouping." + }, + "pushdown": { + "type": [ + "boolean", + "null" + ], + "description": "Per-calc override for whether to evaluate before the row limit. `null` defers to the model-level default." + }, + "sql": { + "type": "string", + "description": "Compiled SQL string produced from the formula." + }, + "sql_expression": { + "description": "Parsed SQL expression tree (serialized)." + }, + "swallow_errors": { + "type": "boolean", + "description": "When true, calculation errors are silently swallowed instead of surfaced." + } + }, + "required": [ + "calc_name" + ], + "additionalProperties": {} + }, + "description": "Table calculations attached to this query." + }, + "column_limit": { + "type": "number", + "description": "Max number of pivot columns to return." + }, + "column_totals": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "aggregation" + ] + } + }, + "required": [ + "type" + ] + }, + "description": "Column-level aggregation totals, keyed by field name." + }, + "controls": { + "type": "array", + "items": { + "oneOf": [ + { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "hidden": { + "type": "boolean" + }, + "id": { + "type": "string" + }, + "label": { + "type": "string" + }, + "display": { + "type": "string", + "enum": [ + "SELECT", + "BUTTON_TOGGLE" + ] + }, + "field": { + "type": "string" + }, + "kind": { + "type": "string", + "enum": [ + "FIELD", + "TIMEFRAME" + ] + }, + "options": { + "type": "array", + "items": { + "type": "object", + "properties": { + "isDimension": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "topicLabel": { + "type": "string" + }, + "value": { + "type": "string" + }, + "viewLabel": { + "type": "string" + } + }, + "required": [ + "label", + "value" + ] + } + }, + "type": { + "type": "string", + "enum": [ + "FIELD_SELECTION" + ] + } + }, + "required": [ + "id", + "field", + "kind", + "options", + "type" + ] + }, + { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "hidden": { + "type": "boolean" + }, + "id": { + "type": "string" + }, + "label": { + "type": "string" + }, + "display": { + "type": "string", + "enum": [ + "SELECT", + "BUTTON_TOGGLE" + ] + }, + "options": { + "type": "array", + "items": { + "type": "object", + "properties": { + "label": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "required": [ + "label", + "value" + ] + } + }, + "selectionMap": { + "type": "object", + "additionalProperties": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "type": { + "type": "string", + "enum": [ + "MULTI_FIELD_SELECTION" + ] + }, + "value": { + "type": "string" + } + }, + "required": [ + "id", + "options", + "selectionMap", + "type" + ] + }, + { + "type": "object", + "properties": { + "computations": { + "type": "array", + "items": { + "type": "object", + "properties": { + "filterId": { + "type": "string" + }, + "isDynamicPreviousPeriod": { + "type": "boolean" + }, + "periodsAgo": { + "type": [ + "number", + "null" + ] + }, + "timeUnitName": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "periodsAgo", + "timeUnitName" + ] + } + }, + "filterFieldName": { + "type": "string" + }, + "filterId": { + "type": "string" + }, + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "PERIOD_OVER_PERIOD" + ] + } + }, + "required": [ + "computations", + "filterFieldName", + "id", + "type" + ] + }, + { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "hidden": { + "type": "boolean" + }, + "id": { + "type": "string" + }, + "label": { + "type": "string" + }, + "options": { + "type": "array", + "items": { + "type": "object", + "properties": { + "isDimension": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "topicLabel": { + "type": "string" + }, + "value": { + "type": "string" + }, + "viewLabel": { + "type": "string" + } + }, + "required": [ + "label", + "value" + ] + } + }, + "type": { + "type": "string", + "enum": [ + "FIELD_PICKER" + ] + }, + "values": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "id", + "options", + "type" + ] + }, + { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "hidden": { + "type": "boolean" + }, + "id": { + "type": "string" + }, + "label": { + "type": "string" + }, + "conjunction": { + "type": "string", + "enum": [ + "OR" + ] + }, + "filters": { + "type": "array", + "items": { + "type": "object", + "properties": { + "fieldName": { + "type": "string" + }, + "filter": { + "$ref": "#/components/schemas/JsonValue" + }, + "id": { + "type": "string" + } + }, + "required": [ + "fieldName", + "filter", + "id" + ] + } + }, + "type": { + "type": "string", + "enum": [ + "MULTI_FIELD_FILTER" + ] + } + }, + "required": [ + "id", + "conjunction", + "filters", + "type" + ] + }, + { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "hidden": { + "type": "boolean" + }, + "id": { + "type": "string" + }, + "label": { + "type": "string" + }, + "fieldSelection": { + "oneOf": [ + { + "type": "object", + "properties": { + "mode": { + "type": "string", + "enum": [ + "full-model" + ] + } + }, + "required": [ + "mode" + ] + }, + { + "type": "object", + "properties": { + "mode": { + "type": "string", + "enum": [ + "auto" + ] + }, + "topics": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "mode", + "topics" + ] + }, + { + "type": "object", + "properties": { + "fields": { + "type": "array", + "items": { + "type": "object", + "properties": { + "fieldName": { + "type": "string" + }, + "topicName": { + "type": "string" + } + }, + "required": [ + "fieldName" + ] + } + }, + "mode": { + "type": "string", + "enum": [ + "specific" + ] + } + }, + "required": [ + "fields", + "mode" + ] + } + ] + }, + "includeViewNameInLabels": { + "type": "boolean" + }, + "type": { + "type": "string", + "enum": [ + "DYNAMIC_FILTER" + ] + } + }, + "required": [ + "id", + "fieldSelection", + "type" + ] + }, + { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "hidden": { + "type": "boolean" + }, + "id": { + "type": "string" + }, + "label": { + "type": "string" + }, + "defaultValue": { + "type": "integer", + "minimum": 1 + }, + "field": { + "type": "string" + }, + "max": { + "type": "integer", + "minimum": 1 + }, + "min": { + "type": "integer", + "minimum": 1 + }, + "type": { + "type": "string", + "enum": [ + "TOP_N" + ] + }, + "value": { + "type": "integer", + "minimum": 1 + } + }, + "required": [ + "id", + "defaultValue", + "field", + "type", + "value" + ] + } + ] + }, + "description": "Interactive controls (field selectors, PoP controls) attached to this query." + }, + "cube_metadata": { + "type": "object", + "properties": { + "cube_name": { + "type": "string" + }, + "hash_key": { + "type": "string" + }, + "topic_name": { + "type": "string" + } + }, + "required": [ + "cube_name", + "hash_key", + "topic_name" + ], + "additionalProperties": {}, + "description": "Cube-specific metadata (topic name, cube name, hash key) for cube-backed queries." + }, + "custom_summary_types": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Per-field custom summary functions (e.g. SUM, AVG, COUNT)." + }, + "dbtFileName": { + "type": "string", + "description": "dbt file name when this query is backed by a dbt model." + }, + "dbtMode": { + "type": "boolean", + "description": "Whether this query is in dbt mode." + }, + "default_group_by": { + "type": "boolean", + "description": "When true, all dimensions are implicitly included in GROUP BY." + }, + "dimensionIndex": { + "type": "number", + "description": "Index of the primary dimension used for result ordering." + }, + "executableSQL": { + "type": "string", + "description": "Server-compiled SQL string (read-only, set by the backend)." + }, + "fields": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Model field names selected for the query (dimensions + measures)." + }, + "fill_fields": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Fields whose missing date/time values should be filled with nulls to create continuous series." + }, + "filters": { + "type": "object", + "additionalProperties": { + "oneOf": [ + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "case_insensitive": { + "type": "boolean" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "kind": { + "type": "string", + "enum": [ + "CONTAINS", + "ENDS_WITH", + "STARTS_WITH", + "EQUALS", + "IS_EMPTY", + "SQL_LIKE" + ] + }, + "type": { + "type": "string", + "enum": [ + "string" + ] + }, + "values": { + "type": "array", + "items": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "hidden": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "kind", + "type", + "values" + ], + "additionalProperties": {} + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "is_inclusive": { + "type": "boolean" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "kind": { + "type": "string", + "enum": [ + "LESS_THAN", + "GREATER_THAN", + "EQUALS", + "BETWEEN" + ] + }, + "type": { + "type": "string", + "enum": [ + "number" + ] + }, + "values": { + "type": "array", + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + } + ] + } + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "hidden": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "kind", + "type", + "values" + ], + "additionalProperties": {} + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "isFiscal": { + "type": "boolean" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "kind": { + "type": "string", + "enum": [ + "IS_ON_DAY_OF_WEEK", + "IS_ON_DAY_OF_QUARTER", + "IS_IN_MONTH_OF_YEAR", + "IS_ON_DAY_OF_YEAR", + "IS_AT_HOUR_OF_DAY", + "IS_IN_QUARTER_OF_YEAR", + "IS_IN_WEEK_OF_YEAR", + "IS_ON_DAY_OF_MONTH", + "BETWEEN", + "ON_OR_AFTER", + "BEFORE", + "TIME_FOR_INTERVAL_DURATION", + "TIME_FOR_UNIT_DURATION", + "QUERY_OFFSET" + ] + }, + "left_side": { + "type": [ + "string", + "null" + ] + }, + "offset_interval_string": { + "type": [ + "string", + "null" + ] + }, + "right_side": { + "type": [ + "string", + "null" + ] + }, + "type": { + "type": "string", + "enum": [ + "date" + ] + }, + "ui_type": { + "type": [ + "string", + "null" + ], + "enum": [ + "ANY_TIME", + "BEFORE", + "BETWEEN", + "MONTH_OF_YEAR", + "PAST", + "YEAR", + "DAY", + "IS_ON_DAY_OF_WEEK", + "ON_OR_AFTER", + "IS_IN_THE_MONTH", + "IS_IN_THE_QUARTER", + "IS_IN_THE_FISCAL_QUARTER", + "IS_IN_THE_FISCAL_YEAR", + "TIME_FOR_INTERVAL_DURATION", + "TIME_FOR_UNIT_DURATION", + "CUSTOM", + null + ] + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "hidden": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "kind", + "type" + ], + "additionalProperties": {} + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "type": { + "type": "string", + "enum": [ + "null" + ] + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "hidden": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "type" + ], + "additionalProperties": {} + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "treat_nulls_as_false": { + "type": "boolean" + }, + "type": { + "type": "string", + "enum": [ + "boolean" + ] + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "hidden": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "type" + ], + "additionalProperties": {} + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "disregard_limit": { + "type": "boolean" + }, + "field_name": { + "type": "string" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "query_id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "query" + ] + }, + "view_query": { + "type": "object", + "properties": { + "fields": { + "type": "array", + "items": { + "type": "string" + } + }, + "filters": { + "type": "object", + "additionalProperties": {}, + "default": {} + }, + "limit": { + "type": "number" + }, + "sorts": { + "type": "array", + "items": {}, + "default": [] + }, + "table": { + "type": "string" + } + }, + "required": [ + "fields" + ], + "additionalProperties": {} + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "hidden": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "type" + ], + "additionalProperties": {} + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "type": { + "type": "string", + "enum": [ + "user_attribute" + ] + }, + "user_attribute_name": { + "type": "string" + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "hidden": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "type", + "user_attribute_name" + ], + "additionalProperties": {} + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "conjunction": { + "type": "string", + "enum": [ + "OR", + "AND" + ] + }, + "filters": { + "type": "array", + "items": { + "$ref": "#/components/schemas/CompositeFilter" + } + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "type": { + "type": "string", + "enum": [ + "composite" + ] + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "hidden": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "conjunction", + "filters", + "type" + ], + "additionalProperties": {} + } + ] + }, + "description": "Query filters keyed by filter ID." + }, + "filtersUsedInSql": { + "type": "object", + "additionalProperties": { + "oneOf": [ + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "case_insensitive": { + "type": "boolean" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "kind": { + "type": "string", + "enum": [ + "CONTAINS", + "ENDS_WITH", + "STARTS_WITH", + "EQUALS", + "IS_EMPTY", + "SQL_LIKE" + ] + }, + "type": { + "type": "string", + "enum": [ + "string" + ] + }, + "values": { + "type": "array", + "items": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "hidden": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "kind", + "type", + "values" + ], + "additionalProperties": {} + }, { - "$ref": "#/components/schemas/ApiDocument" + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "is_inclusive": { + "type": "boolean" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "kind": { + "type": "string", + "enum": [ + "LESS_THAN", + "GREATER_THAN", + "EQUALS", + "BETWEEN" + ] + }, + "type": { + "type": "string", + "enum": [ + "number" + ] + }, + "values": { + "type": "array", + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + } + ] + } + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "hidden": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "kind", + "type", + "values" + ], + "additionalProperties": {} }, { "type": "object", "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "isFiscal": { + "type": "boolean" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "kind": { + "type": "string", + "enum": [ + "IS_ON_DAY_OF_WEEK", + "IS_ON_DAY_OF_QUARTER", + "IS_IN_MONTH_OF_YEAR", + "IS_ON_DAY_OF_YEAR", + "IS_AT_HOUR_OF_DAY", + "IS_IN_QUARTER_OF_YEAR", + "IS_IN_WEEK_OF_YEAR", + "IS_ON_DAY_OF_MONTH", + "BETWEEN", + "ON_OR_AFTER", + "BEFORE", + "TIME_FOR_INTERVAL_DURATION", + "TIME_FOR_UNIT_DURATION", + "QUERY_OFFSET" + ] + }, + "left_side": { + "type": [ + "string", + "null" + ] + }, + "offset_interval_string": { + "type": [ + "string", + "null" + ] + }, + "right_side": { + "type": [ + "string", + "null" + ] + }, "type": { "type": "string", "enum": [ - "document" + "date" + ] + }, + "ui_type": { + "type": [ + "string", + "null" + ], + "enum": [ + "ANY_TIME", + "BEFORE", + "BETWEEN", + "MONTH_OF_YEAR", + "PAST", + "YEAR", + "DAY", + "IS_ON_DAY_OF_WEEK", + "ON_OR_AFTER", + "IS_IN_THE_MONTH", + "IS_IN_THE_QUARTER", + "IS_IN_THE_FISCAL_QUARTER", + "IS_IN_THE_FISCAL_YEAR", + "TIME_FOR_INTERVAL_DURATION", + "TIME_FOR_UNIT_DURATION", + "CUSTOM", + null + ] + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "hidden": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "kind", + "type" + ], + "additionalProperties": {} + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "type": { + "type": "string", + "enum": [ + "null" + ] + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "hidden": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "type" + ], + "additionalProperties": {} + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "treat_nulls_as_false": { + "type": "boolean" + }, + "type": { + "type": "string", + "enum": [ + "boolean" + ] + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "hidden": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "type" + ], + "additionalProperties": {} + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "disregard_limit": { + "type": "boolean" + }, + "field_name": { + "type": "string" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "query_id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "query" + ] + }, + "view_query": { + "type": "object", + "properties": { + "fields": { + "type": "array", + "items": { + "type": "string" + } + }, + "filters": { + "type": "object", + "additionalProperties": {}, + "default": {} + }, + "limit": { + "type": "number" + }, + "sorts": { + "type": "array", + "items": {}, + "default": [] + }, + "table": { + "type": "string" + } + }, + "required": [ + "fields" + ], + "additionalProperties": {} + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } ] + }, + "hidden": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } } }, "required": [ "type" - ] - } - ] - }, - { - "type": "object", - "properties": { - "id": { - "type": "string", - "description": "Unique identifier" - }, - "name": { - "type": "string", - "minLength": 1, - "maxLength": 255, - "description": "Content name" + ], + "additionalProperties": {} }, - "owner": { + { "type": "object", "properties": { - "id": { - "type": "string", - "description": "User ID of the owner" + "cancel_query_filter": { + "type": "boolean" }, - "name": { + "ignore_if_unjoinable": { + "type": "boolean" + }, + "type": { "type": "string", - "description": "Name of the owner" + "enum": [ + "user_attribute" + ] + }, + "user_attribute_name": { + "type": "string" + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "hidden": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } } }, "required": [ - "id", - "name" - ], - "description": "Content owner" - }, - "scope": { - "type": "string", - "enum": [ - "restricted", - "organization" + "type", + "user_attribute_name" ], - "description": "Content access scope" + "additionalProperties": {} }, - "_count": { + { "type": "object", "properties": { - "documents": { - "type": "number", - "description": "Number of documents" + "cancel_query_filter": { + "type": "boolean" }, - "favorites": { - "type": "number", - "description": "Number of users who favorited" + "ignore_if_unjoinable": { + "type": "boolean" + }, + "conjunction": { + "type": "string", + "enum": [ + "OR", + "AND" + ] + }, + "filters": { + "type": "array", + "items": { + "$ref": "#/components/schemas/CompositeFilter" + } + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "type": { + "type": "string", + "enum": [ + "composite" + ] + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "hidden": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } } }, "required": [ - "documents", - "favorites" + "conjunction", + "filters", + "type" ], - "description": "Folder counts" + "additionalProperties": {} + } + ] + }, + "description": "Filters that were embedded directly in raw SQL (read-only)." + }, + "join_paths_from_topic_name": { + "type": "string", + "description": "Topic name that determines join path precedence for parsed SQL queries." + }, + "join_via_map": { + "type": "object", + "additionalProperties": { + "type": "array", + "items": { + "type": "string" + } + }, + "description": "Virtual topic join path overrides, keyed by view name to ordered join path." + }, + "limit": { + "type": "number", + "description": "Row limit for the query." + }, + "manualSort": { + "type": "boolean", + "description": "When true, the user has explicitly set a custom sort order." + }, + "metadata": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "format": { + "type": "string" }, - "labels": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Labels" + "label": { + "type": "string" }, - "path": { + "order": { + "type": "number" + } + }, + "additionalProperties": {} + }, + "description": "Per-field display metadata (format, label, order)." + }, + "offset": { + "type": "number", + "description": "Row offset for pagination." + }, + "parsed": { + "type": "boolean", + "description": "Whether this raw SQL query has been parsed into a semantic query." + }, + "periodOverPeriodTransposed": { + "type": "boolean", + "description": "Whether the period-over-period comparison columns are transposed." + }, + "period_over_period_computations": { + "type": "array", + "items": { + "type": "object", + "properties": { + "date_filter_field_name": { "type": "string", - "description": "Full path to the folder", - "example": "sales-reports/q1-2026" + "description": "The date dimension field this comparison is anchored to." }, - "url": { + "date_filter_id": { "type": "string", - "description": "URL to view the folder in the Omni UI.", - "example": "https://org.omni.co/f/sales-reports" + "description": "ID of the date filter being offset (if backed by a dashboard filter)." + }, + "is_dynamic_previous_period": { + "type": "boolean", + "description": "When true, the previous period is calculated dynamically relative to the current filter range." + }, + "periods_ago": { + "type": [ + "number", + "null" + ], + "description": "How many periods back to compare (e.g. 1 = previous period). Null if not set." }, + "time_unit_name": { + "type": [ + "string", + "null" + ], + "description": "Time grain for the offset (e.g. \"month\", \"year\"). Null if not set." + } + }, + "required": [ + "date_filter_field_name", + "periods_ago", + "time_unit_name" + ], + "additionalProperties": {} + }, + "description": "Period-over-period comparison configurations." + }, + "pivots": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Field names to pivot on (columns become values)." + }, + "rewriteSql": { + "type": "boolean", + "description": "When true, the backend should rewrite/optimize the SQL." + }, + "row_totals": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { "type": { "type": "string", "enum": [ - "folder" + "aggregation" ] } }, "required": [ - "id", - "name", - "owner", - "scope", - "path", - "url", - "type" - ] - } - ] - } - } - }, - "required": [ - "pageInfo", - "records" - ] - }, - "OwnerInternal": { - "type": "object", - "properties": { - "id": { - "type": "string", - "description": "Owner membership ID" + "type" + ] + }, + "description": "Row-level aggregation totals, keyed by field name." + }, + "sorts": { + "type": "array", + "items": { + "type": "object", + "properties": { + "column_name": { + "type": "string", + "description": "The model field name to sort by." + }, + "is_column_sort": { + "type": "boolean", + "description": "When true, this sort targets a pivoted column rather than a row dimension." + }, + "pivot_value_map": { + "type": "object", + "additionalProperties": { + "type": [ + "string", + "null" + ] + }, + "description": "Maps pivot field names to specific pivot values, scoping the sort to a single pivot column." + }, + "sort_descending": { + "type": "boolean", + "description": "When true, sort order is descending." + }, + "subtotal_sort": { + "type": "string", + "description": "Field name whose subtotal row should be used as the sort key." + } + }, + "required": [ + "column_name", + "sort_descending" + ], + "additionalProperties": {} + }, + "description": "Sort clauses applied to the query result set." + }, + "sqlSortsEnabled": { + "type": "boolean", + "description": "Whether user-created sorts are enabled on a raw SQL query." + }, + "staticQueryReferences": { + "type": "object", + "additionalProperties": {}, + "description": "Pre-computed query references for AI chat context. Inner shape is `OmniQuery & { model_id: string }`; left as `unknown` to avoid a recursive zod schema. Validated structurally by consumers when they execute the referenced sub-queries." + }, + "table": { + "type": "string", + "description": "Base view (table) name in the model." + }, + "transposed_measures": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Measure field names that have been transposed into rows." + }, + "userEditedSQL": { + "type": "string", + "description": "User-authored raw SQL (empty string when not in SQL mode)." + }, + "version": { + "type": "number", + "description": "Schema version for migration support." + } + }, + "required": [ + "calculations", + "column_totals", + "fields", + "fill_fields", + "filters", + "pivots", + "row_totals", + "sorts", + "table", + "userEditedSQL" + ], + "additionalProperties": {}, + "description": "The semantic query for this tab, minus the server-owned workbook model anchors (modelId / model_extension_id). For LINKED-type tabs this field is read-only." }, - "name": { - "type": "string", - "description": "Owner display name" - } - }, - "required": [ - "id", - "name" - ], - "description": "Content owner" - }, - "ContentShareScope": { - "type": "string", - "enum": [ - "restricted", - "organization" - ], - "description": "Content access scope" - }, - "InternalFolder": { - "type": [ - "object", - "null" - ], - "properties": { - "id": { - "type": "string", - "description": "Folder ID" + "resultConfig": { + "type": "object", + "additionalProperties": {}, + "description": "Result display configuration (column widths, frozen columns, conditional formatting, number formatting, etc.)." }, - "name": { - "type": "string", - "minLength": 1, - "maxLength": 255, - "description": "Folder name" + "subTitle": { + "type": [ + "string", + "null" + ], + "maxLength": 250, + "description": "User-provided tab subtitle." }, - "path": { + "topicName": { + "type": [ + "string", + "null" + ], + "description": "The topic (explore) this query is built on." + }, + "type": { "type": "string", - "description": "Folder path" + "enum": [ + "blank", + "csv", + "query", + "dataset", + "spreadsheet", + "sql", + "dbt", + "query-view", + "linked", + "app" + ], + "description": "The query presentation type (e.g. SEMANTIC, SQL, LINKED, SPREADSHEET)." }, - "scope": { - "allOf": [ - { - "$ref": "#/components/schemas/ContentShareScope" + "visConfig": { + "type": [ + "object", + "null" + ], + "properties": { + "chartType": { + "type": [ + "string", + "null" + ], + "enum": [ + "auto", + "area", + "areaStacked", + "areaStackedPercentage", + "bar", + "barLine", + "barGrouped", + "barStacked", + "barStackedPercentage", + "boxplot", + "code", + "column", + "columnGrouped", + "columnStacked", + "columnStackedPercentage", + "heatmap", + "kpi", + "line", + "lineColor", + "map", + "regionMap", + "markdown", + "omni-ai-summary-markdown", + "pie", + "funnel", + "sankey", + "point", + "pointColor", + "pointSize", + "pointSizeColor", + "singleRecord", + "omni-spreadsheet", + "summaryValue", + "svgMap", + "table", + null + ], + "description": "High-level chart type (e.g. \"bar\", \"line\", \"area\")." }, - { - "description": "Folder access scope" + "fields": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Field names used in the visualization axes/series." + }, + "version": { + "type": "number", + "description": "Schema version for vis config migration." + }, + "visConfig": { + "type": "object", + "properties": { + "visType": { + "type": [ + "string", + "null" + ], + "enum": [ + "vegalite", + "omni-ai-summary-markdown", + "basic", + "omni-kpi", + "map", + "omni-markdown", + "funnel", + "sankey", + "single-record", + "svg-map", + "omni-spreadsheet", + "spreadsheet-tab", + "summary-value", + "omni-table", + "app", + null + ], + "description": "The visualization type (e.g. \"basic\", \"omni-table\")." + } + }, + "additionalProperties": {}, + "description": "Inner visualization config — structure varies by visType." } - ] + }, + "additionalProperties": {}, + "description": "Visualization configuration for the tile." + }, + "sourceQueryPresentationKey": { + "type": [ + "string", + "null" + ], + "pattern": "^[1-9][0-9]*$", + "description": "For LINKED-type tabs, the record key — the same identifier used as a `queryPresentations.data` key — of the source tile whose query this tab reuses. Null for all other tab types. This is a tile record key, NOT a positional index into `order`." } }, "required": [ - "id", + "aiConfig", + "automaticVis", + "description", + "filterOrder", + "isSql", "name", - "path", - "scope" - ], - "description": "Parent folder" + "prefersChart", + "query", + "resultConfig", + "subTitle", + "topicName", + "type", + "visConfig", + "sourceQueryPresentationKey" + ] }, - "ApiDocument": { + "SettingsReadExternal": { "type": "object", "properties": { - "name": { - "type": "string", - "minLength": 1, - "maxLength": 255, - "description": "Content name" - }, - "owner": { - "$ref": "#/components/schemas/OwnerInternal" - }, - "scope": { - "$ref": "#/components/schemas/ContentShareScope" + "crossfilterEnabled": { + "type": "boolean", + "description": "When true, clicking a value in one tile filters all other tiles on the dashboard." }, - "_count": { - "type": "object", + "customText": { + "type": [ + "object", + "null" + ], "properties": { - "favorites": { - "type": "number", - "description": "Number of users who favorited" + "queryError": { + "type": "string", + "description": "Custom text shown when a query errors, replacing the default error text." }, - "views": { - "type": "number", - "description": "Number of views" + "queryNoResults": { + "type": "string", + "description": "Custom text shown when a query returns no results, replacing the default empty state." } }, - "required": [ - "favorites", - "views" - ], - "description": "Document counts" - }, - "connectionId": { - "type": "string", - "description": "Connection ID" + "description": "Custom text replacing default UI strings on the dashboard, e.g. when queries error or return no results." }, - "deleted": { + "facetFilters": { "type": "boolean", - "description": "Whether document is deleted" + "description": "When true, dashboard filters are applied per-facet when faceting is active." + }, + "refreshInterval": { + "type": [ + "number", + "null" + ], + "description": "Auto-refresh interval in seconds. Null disables auto-refresh." }, + "runQueriesOn": { + "type": [ + "string", + "null" + ], + "enum": [ + "current-page", + "all-pages", + null + ], + "description": "Controls whether dashboard queries execute on the visible page or across all pages." + } + }, + "required": [ + "crossfilterEnabled", + "customText", + "facetFilters", + "refreshInterval", + "runQueriesOn" + ] + }, + "DocumentsV2PatchDraftResponse": { + "type": "object", + "properties": { "description": { "type": [ "string", "null" ], - "description": "Document description" - }, - "folder": { - "$ref": "#/components/schemas/InternalFolder" + "description": "Document description." }, - "hasDashboard": { - "type": "boolean", - "description": "Whether document has a dashboard" + "draftIdentifier": { + "type": "string", + "description": "Identifier of the draft the patch was applied to." }, "identifier": { "type": "string", - "description": "Document identifier" + "description": "Published document identifier the draft targets." + }, + "name": { + "type": "string", + "description": "Document name." + } + }, + "required": [ + "description", + "draftIdentifier", + "identifier", + "name" + ] + }, + "DocumentsV2CreateDraftBody": { + "allOf": [ + { + "$ref": "#/components/schemas/DocumentsV2PatchDraftBody" + }, + { + "type": "object", + "properties": { + "branchId": { + "type": "string", + "format": "uuid", + "description": "Branch the draft is created on. Omit for a draft on the main (unpublished) workspace." + } + }, + "additionalProperties": false + } + ] + }, + "DocumentsV2PatchDraftBody": { + "type": "object", + "properties": { + "containers": { + "allOf": [ + { + "$ref": "#/components/schemas/Containers" + }, + { + "description": "Container layout. When present, fully replaces the existing layout and disables automatic tile placement for the request." + } + ] }, - "labels": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Applied labels" + "controls": { + "$ref": "#/components/schemas/ControlsPatchExternal" }, - "lastViewedAt": { + "description": { "type": [ "string", "null" - ], - "format": "date-time", - "description": "Last time the dashboard was viewed" + ] }, - "updatedAt": { + "name": { + "type": "string", + "minLength": 1, + "maxLength": 254, + "description": "Document name." + }, + "queryPresentations": { + "$ref": "#/components/schemas/QueryPresentationsPatchExternal" + }, + "settings": { + "$ref": "#/components/schemas/SettingsPatchExternal" + }, + "summary": { + "type": "string", + "minLength": 1, + "maxLength": 255, + "description": "Caller-supplied description of what this patch changes, written to the history audit trail. When absent, the server generates one from the touched sections." + } + }, + "additionalProperties": false + }, + "DocumentsV2PublishDraftResponse": { + "type": "object", + "properties": { + "description": { "type": [ "string", "null" ], - "format": "date-time", - "description": "Last updated timestamp" + "description": "Document description." }, - "url": { + "identifier": { "type": "string", - "description": "URL to view the document. Returns dashboard URL if document has a dashboard, otherwise workbook URL.", - "example": "https://org.omni.co/dashboards/abc123" + "description": "Published document identifier." }, - "visits": { - "type": [ - "number", - "null" - ], - "description": "Number of dashboard visits" + "name": { + "type": "string", + "description": "Document name." } }, "required": [ - "name", - "owner", - "scope", - "connectionId", - "deleted", - "folder", - "hasDashboard", + "description", "identifier", - "updatedAt", - "url" + "name" ] }, - "DashboardsDownloadResponse": { + "EmbedSsoGenerateSessionResponse": { "type": "object", "properties": { - "job_id": { - "type": "string", - "format": "uuid", - "description": "ID of the download job. Use this to poll for download status.", - "example": "123e4567-e89b-12d3-a456-426614174000" - }, - "message": { + "sessionId": { "type": "string", - "description": "Status message", - "example": "Download initiated successfully" + "description": "Session ID to use for embedding Omni content" } }, "required": [ - "job_id", - "message" + "sessionId" ] }, - "DashboardsDownloadBody": { + "EmbedSsoGenerateSessionBody": { "type": "object", "properties": { - "enableFormatting": { - "type": "boolean", - "default": false, - "description": "Compatible with csv, xlsx & json formats. If true, formatting will be enabled in the output. Note: If true for json format, a queryIdentifierMapKey is required.", - "example": false - }, - "expandTablesToShowAllRows": { - "type": "boolean", - "description": "Compatible with pdf and png formats. If true, up to 1,000 rows in table visualizations will be included in the delivery. Note: This parameter cannot be used when paperFormat: fit_page.", - "example": false + "externalId": { + "type": "string", + "description": "External identifier for the user (from your system)", + "example": "user-123" }, - "filterConfig": { - "description": "An object specifying the filter conditions to apply to the task. The filter key specified must already exist in the dashboard.", - "example": { - "status": [ - "active", - "pending" - ] - } + "groups": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Optional list of group names to assign to the user", + "example": [ + "engineering", + "sales" + ] }, - "format": { + "name": { "type": "string", - "enum": [ - "pdf", - "png", - "csv", - "xlsx", - "json" - ], - "description": "Output format for the download: pdf, png, csv, xlsx, or json", - "example": "pdf" + "description": "Display name for the user", + "example": "John Doe" }, - "hideHiddenFields": { - "type": "boolean", - "default": false, - "description": "Compatible with csv & xlsx formats. If true, fields marked as hidden won't be displayed in the output.", - "example": false + "userAttributes": { + "type": "object", + "additionalProperties": {}, + "description": "Optional user attributes for row-level security" + } + }, + "required": [ + "externalId", + "name" + ] + }, + "EvalPromptSetsListResponse": { + "type": "object", + "properties": { + "prompt_sets": { + "type": "array", + "items": { + "$ref": "#/components/schemas/EvalPromptSetListItem" + }, + "description": "Prompt sets matching the query, sorted alphabetically by name." + } + }, + "required": [ + "prompt_sets" + ] + }, + "EvalPromptSetListItem": { + "type": "object", + "properties": { + "created_at": { + "type": [ + "string", + "null" + ], + "description": "ISO 8601 timestamp when the prompt set was created.", + "example": "2025-01-15T10:00:00.000Z" }, - "hideTitle": { - "type": "boolean", - "default": false, - "description": "Compatible with pdf & png formats. If true, the content's title will be hidden in the output.", - "example": false + "description": { + "type": [ + "string", + "null" + ], + "description": "Optional human-readable description of the prompt set.", + "example": "Regression suite for the orders topic" }, - "maxRowLimit": { - "type": "number", - "minimum": 1, - "description": "Compatible with csv, json, & xlsx formats. Used with overrideRowLimit. Specifies the maximum number of rows.", - "example": 1000 + "id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the prompt set.", + "example": "550e8400-e29b-41d4-a716-446655440000" }, - "overrideRowLimit": { + "is_archived": { "type": "boolean", - "default": false, - "description": "Compatible with csv, json, & xlsx formats. If true, the default row limit will be overridden. Note: If true for json and xlsx formats, a queryIdentifierMapKey is required.", + "description": "Whether the prompt set has been archived.", "example": false }, - "paperFormat": { + "model_id": { "type": "string", - "enum": [ - "a3", - "a4", - "fit_page", - "legal", - "letter", - "tabloid" - ], - "description": "Compatible with pdf formats. Defines the paper format (size) of the resulting PDF. Must be one of: a3, a4, letter, legal, fit_page, tabloid.", - "example": "letter" + "format": "uuid", + "description": "The shared model this prompt set is bound to.", + "example": "880e8400-e29b-41d4-a716-446655440003" }, - "paperOrientation": { + "name": { "type": "string", - "enum": [ - "portrait", - "landscape" - ], - "description": "Compatible with pdf formats. Defines the paper orientation of the resulting PDF. Must be one of: portrait, landscape.", - "example": "landscape" + "description": "Human-readable name for the prompt set.", + "example": "Orders regression" }, - "queryIdentifierMapKey": { + "slug": { "type": "string", - "description": "Required for single tile tasks. The ID of the query to include in a single tile task. Must reference a valid query in the dashboard.", - "example": "Jmn2r3KV" - }, - "showContentLink": { - "type": "boolean", - "default": true, - "description": "Compatible with all formats except link_only. If true, a link to the content will be shown in the output.", - "example": true + "description": "URL-safe identifier for the prompt set. Unique per `model_id`.", + "example": "orders-regression" }, - "showFilters": { - "type": "boolean", - "default": true, - "description": "Compatible with all formats except link_only & csv. If true, filters will be shown in the output.", - "example": true - }, - "singleColumnLayout": { - "type": "boolean", - "description": "Compatible with pdf and png formats. If true, dashboard tiles will be arranged into a single vertical column.", - "example": false + "updated_at": { + "type": [ + "string", + "null" + ], + "description": "ISO 8601 timestamp when the prompt set was last updated.", + "example": "2025-01-15T10:00:00.000Z" }, - "useCache": { - "type": "boolean", - "default": false, - "description": "If true, allow scheduled queries to use cached results instead of always running fresh queries.", - "example": false + "latest_run_at": { + "type": [ + "string", + "null" + ], + "description": "ISO 8601 timestamp of the most recent run on this prompt set, if any.", + "example": "2025-01-15T10:05:00.000Z" }, - "filename": { + "prompt_count": { + "type": "integer", + "description": "Number of prompts in the set.", + "example": 12 + } + }, + "required": [ + "created_at", + "description", + "id", + "is_archived", + "model_id", + "name", + "slug", + "updated_at", + "latest_run_at", + "prompt_count" + ] + }, + "EvalApiError400": { + "type": "object", + "properties": { + "detail": { "type": "string", - "minLength": 1, - "maxLength": 255, - "description": "Custom filename for the downloaded file (without extension)", - "example": "monthly-report" + "description": "Human-readable error message describing what went wrong.", + "example": "Bad Request: name: Required" + }, + "status": { + "type": "integer", + "description": "HTTP status code of the error.", + "example": 400 } }, "required": [ - "format" - ], - "additionalProperties": false + "detail", + "status" + ] }, - "DashboardFiltersResponse": { + "EvalApiError401": { "type": "object", "properties": { - "controls": { - "description": "Control configuration object. Keys are control IDs, values contain controlType, filterId, label, etc." - }, - "filterOrder": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Ordered list of filter IDs defining display order", - "example": [ - "filter_abc123", - "filter_def456" - ] - }, - "filters": { - "description": "Filter configuration object. Keys are filter IDs, values contain fieldName, viewName, kind, defaultValue, etc." - }, - "identifier": { + "detail": { "type": "string", - "description": "Dashboard identifier", - "example": "12db1a0a" + "description": "Human-readable error message describing what went wrong.", + "example": "Unauthorized: Missing or invalid API key" + }, + "status": { + "type": "integer", + "description": "HTTP status code of the error.", + "example": 401 } }, "required": [ - "filterOrder", - "identifier" + "detail", + "status" ] }, - "DashboardsUpdateFiltersBody": { + "EvalApiError403": { "type": "object", "properties": { - "clearExistingDraft": { - "type": "boolean", - "default": false, - "description": "When true, discards any existing draft before applying updates. Required when updating a published document that already has a draft." - }, - "controls": { - "type": "object", - "additionalProperties": { - "type": "object", - "properties": {}, - "additionalProperties": {} - }, - "description": "Partial control updates. Keys are control IDs that must exist in the dashboard." - }, - "filterOrder": { - "type": "array", - "items": { - "type": "string" - }, - "description": "New order for filters. All filter IDs must exist in the dashboard." + "detail": { + "type": "string", + "description": "Human-readable error message describing what went wrong.", + "example": "AI eval requires at least Querier access on the model" }, - "filters": { - "type": "object", - "additionalProperties": { - "type": "object", - "properties": {}, - "additionalProperties": {} - }, - "description": "Partial filter updates. Keys are filter IDs that must exist in the dashboard." + "status": { + "type": "integer", + "description": "HTTP status code of the error.", + "example": 403 } - } + }, + "required": [ + "detail", + "status" + ] }, - "DocumentsListResponse": { + "EvalApiError404": { "type": "object", "properties": { - "pageInfo": { - "allOf": [ - { - "$ref": "#/components/schemas/PageInfo" - }, - { - "description": "Pagination information" - } - ] + "detail": { + "type": "string", + "description": "Human-readable error message describing what went wrong.", + "example": "Prompt set not found" }, - "records": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Document" - }, - "description": "List of documents" + "status": { + "type": "integer", + "description": "HTTP status code of the error.", + "example": 404 } }, "required": [ - "pageInfo", - "records" + "detail", + "status" ] }, - "Document": { + "EvalPromptSetsCreateResponse": { "type": "object", "properties": { - "_count": { - "type": "object", - "properties": { - "favorites": { - "type": "number", - "description": "Number of users who favorited this document" - }, - "views": { - "type": "number", - "description": "Number of views" - } - }, - "required": [ - "favorites", - "views" + "prompt_set": { + "$ref": "#/components/schemas/EvalPromptSet" + } + }, + "required": [ + "prompt_set" + ] + }, + "EvalPromptSet": { + "type": "object", + "properties": { + "created_at": { + "type": [ + "string", + "null" ], - "description": "Document counts (included when _count is in include param)" - }, - "connectionId": { - "type": "string", - "description": "Connection ID the document is associated with" - }, - "deleted": { - "type": "boolean", - "description": "Whether the document is deleted (archived)" + "description": "ISO 8601 timestamp when the prompt set was created.", + "example": "2025-01-15T10:00:00.000Z" }, "description": { "type": [ "string", "null" ], - "description": "Document description" + "description": "Optional human-readable description of the prompt set.", + "example": "Regression suite for the orders topic" }, - "folder": { - "$ref": "#/components/schemas/DocumentFolder" + "id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the prompt set.", + "example": "550e8400-e29b-41d4-a716-446655440000" }, - "hasDashboard": { + "is_archived": { "type": "boolean", - "description": "Whether the document has an associated dashboard" + "description": "Whether the prompt set has been archived.", + "example": false }, - "identifier": { + "model_id": { "type": "string", - "description": "Document identifier", - "example": "abc123" + "format": "uuid", + "description": "The shared model this prompt set is bound to.", + "example": "880e8400-e29b-41d4-a716-446655440003" }, - "labels": { + "name": { + "type": "string", + "description": "Human-readable name for the prompt set.", + "example": "Orders regression" + }, + "prompts": { "type": "array", "items": { - "type": "string" + "$ref": "#/components/schemas/EvalPrompt" }, - "description": "Labels applied to the document (included when labels is in include param)" + "description": "Prompts that make up the set." }, - "name": { + "slug": { "type": "string", - "description": "Document name" + "description": "URL-safe identifier for the prompt set. Unique per `model_id`.", + "example": "orders-regression" }, - "owner": { - "$ref": "#/components/schemas/DocumentOwner" - }, - "scope": { - "type": "string", - "enum": [ - "restricted", - "organization" + "updated_at": { + "type": [ + "string", + "null" ], - "description": "Document access scope" - }, - "type": { - "type": "string", - "enum": [ - "document" + "description": "ISO 8601 timestamp when the prompt set was last updated.", + "example": "2025-01-15T10:00:00.000Z" + } + }, + "required": [ + "created_at", + "description", + "id", + "is_archived", + "model_id", + "name", + "prompts", + "slug", + "updated_at" + ] + }, + "EvalPrompt": { + "type": "object", + "properties": { + "created_at": { + "type": [ + "string", + "null" ], - "description": "Content type" + "description": "ISO 8601 timestamp when the prompt was created.", + "example": "2025-01-15T10:00:00.000Z" }, - "updatedAt": { + "expectation": { "type": [ "string", "null" ], - "format": "date-time", - "description": "Last updated timestamp" + "description": "The expectation the analysis judge scores the analysis against, or null when none was set.", + "example": "The top product by revenue should be Aniseed Syrup." }, - "url": { + "id": { "type": "string", - "description": "URL to view the document. Returns dashboard URL if document has a dashboard, otherwise workbook URL.", - "example": "https://org.omni.co/dashboards/abc123" + "format": "uuid", + "description": "Unique identifier for the prompt.", + "example": "770e8400-e29b-41d4-a716-446655440002" + }, + "prompt_text": { + "type": "string", + "description": "The natural language prompt text the AI is evaluated on.", + "example": "What are the top 5 products by revenue?" + }, + "updated_at": { + "type": [ + "string", + "null" + ], + "description": "ISO 8601 timestamp when the prompt was last updated.", + "example": "2025-01-15T10:00:00.000Z" } }, "required": [ - "connectionId", - "deleted", - "folder", - "hasDashboard", - "identifier", - "name", - "owner", - "scope", - "type", - "updatedAt", - "url" + "created_at", + "expectation", + "id", + "prompt_text", + "updated_at" ] }, - "DocumentFolder": { - "type": [ - "object", - "null" - ], + "EvalPromptSetsCreateBody": { + "type": "object", "properties": { - "id": { + "description": { + "type": [ + "string", + "null" + ], + "maxLength": 1024, + "description": "Optional human-readable description of the prompt set. Max 1024 characters.", + "example": "Regression suite for the orders topic" + }, + "model_id": { "type": "string", - "description": "Folder ID" + "format": "uuid", + "description": "The shared model this prompt set is bound to.", + "example": "880e8400-e29b-41d4-a716-446655440003" }, "name": { "type": "string", - "description": "Folder name" + "minLength": 1, + "maxLength": 255, + "description": "Human-readable name for the prompt set. 255 characters or fewer.", + "example": "Orders regression" }, - "path": { - "type": "string", - "description": "Folder path" + "prompts": { + "type": "array", + "items": { + "type": "object", + "properties": { + "expectation": { + "type": [ + "string", + "null" + ], + "maxLength": 16000, + "description": "Optional expectation the analysis judge scores the analysis against. Max 16000 characters.", + "example": "The top product by revenue should be Aniseed Syrup." + }, + "prompt_text": { + "type": "string", + "minLength": 1, + "maxLength": 8000, + "description": "The natural language prompt text. Max 8000 characters.", + "example": "What are the top 5 products by revenue?" + } + }, + "required": [ + "prompt_text" + ] + }, + "maxItems": 25, + "default": [], + "description": "Initial prompts for the set. Defaults to an empty list. At most 25 prompts." }, - "scope": { + "slug": { "type": "string", - "enum": [ - "restricted", - "organization" - ], - "description": "Folder access scope" + "maxLength": 255, + "pattern": "^[a-z][a-z0-9-]*$", + "description": "URL-safe identifier for the prompt set. Must be unique per `model_id` and match `^[a-z][a-z0-9-]*$`. Max 255 characters.", + "example": "orders-regression" } }, "required": [ - "id", + "model_id", "name", - "path", - "scope" - ], - "description": "Folder containing the document" + "slug" + ] }, - "DocumentOwner": { + "EvalPromptSetsGetResponse": { "type": "object", "properties": { - "id": { - "type": "string", - "description": "Owner membership ID" - }, - "name": { - "type": "string", - "description": "Owner display name" + "prompt_set": { + "$ref": "#/components/schemas/EvalPromptSet" } }, "required": [ - "id", - "name" - ], - "description": "Document owner" + "prompt_set" + ] }, - "DocumentsCreateResponse": { + "EvalPromptSetsUpdateResponse": { "type": "object", "properties": { - "dashboard": { - "type": "object", - "properties": { - "dashboardId": { - "type": "string", - "description": "Dashboard ID" - }, - "id": { - "type": "string", - "description": "Dashboard ID" - } - }, - "required": [ - "dashboardId", - "id" - ], - "additionalProperties": {}, - "description": "Created dashboard" - }, - "workbook": { - "type": "object", - "properties": { - "documentId": { - "type": "string", - "description": "Document ID (deprecated)" - }, - "id": { - "type": "string", - "description": "Workbook ID" - } - }, - "required": [ - "documentId", - "id" - ], - "additionalProperties": {}, - "description": "Created workbook" + "prompt_set": { + "$ref": "#/components/schemas/EvalPromptSet" } }, "required": [ - "dashboard", - "workbook" + "prompt_set" ] }, - "DocumentsCreateBody": { + "EvalApiError422": { "type": "object", "properties": { - "branchId": { + "detail": { "type": "string", - "format": "uuid", - "description": "Optional branch ID to associate the document with a model branch", - "example": "123e4567-e89b-12d3-a456-426614174001" + "description": "Human-readable error message describing what went wrong.", + "example": "A prompt being updated does not belong to this prompt set" }, + "status": { + "type": "integer", + "description": "HTTP status code of the error.", + "example": 422 + } + }, + "required": [ + "detail", + "status" + ] + }, + "EvalPromptSetsUpdateBody": { + "type": "object", + "properties": { "description": { "type": [ "string", "null" ], - "description": "Document description" - }, - "facetFilters": { - "type": "boolean", - "description": "Enable facet filters on the dashboard" - }, - "filterConfig": { - "description": "Dashboard filter configuration" - }, - "filterOrder": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Order of filters in the dashboard" - }, - "identifier": { - "$ref": "#/components/schemas/DocumentIdentifier" - }, - "metadata": { - "description": "Dashboard metadata" - }, - "metadataVersion": { - "type": "string", - "description": "Dashboard metadata version (required when metadata is provided)" - }, - "modelId": { - "type": "string", - "description": "Shared model ID to base the document on" + "maxLength": 1024, + "description": "New description for the prompt set. Pass `null` to clear. Max 1024 characters." }, "name": { "type": "string", - "description": "Document name" + "minLength": 1, + "maxLength": 255, + "description": "New human-readable name for the prompt set. 255 characters or fewer." }, - "queryPresentations": { + "prompts": { "type": "array", "items": { "type": "object", "properties": { - "aiConfig": { - "description": "AI configuration" - }, - "chartType": { + "expectation": { "type": [ "string", "null" ], - "description": "Chart type" - }, - "description": { - "type": "string", - "description": "Query presentation description" - }, - "name": { - "type": "string", - "description": "Query presentation name" - }, - "prefersChart": { - "type": "boolean", - "description": "Whether to prefer chart view" - }, - "query": { - "type": "object", - "properties": { - "fields": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Query fields" - }, - "table": { - "type": "string", - "description": "Query table/topic" - } - }, - "required": [ - "fields", - "table" - ], - "additionalProperties": {}, - "description": "Query definition" - }, - "resultConfig": { - "description": "Result configuration" + "maxLength": 16000, + "description": "Optional expectation the analysis judge scores the analysis against. Pass `null` to clear. Max 16000 characters.", + "example": "The top product by revenue should be Aniseed Syrup." }, - "subTitle": { + "id": { "type": "string", - "description": "Subtitle" + "format": "uuid", + "description": "Existing prompt id. When provided, updates that prompt; when omitted, a new prompt is created. Prompts not included in this list are removed." }, - "topicName": { + "prompt_text": { "type": "string", - "description": "Topic name" - }, - "visConfig": { - "$ref": "#/components/schemas/ApiVisConfig" + "minLength": 1, + "maxLength": 8000, + "description": "Updated or new prompt text. Max 8000 characters.", + "example": "What are the top 10 products by revenue this quarter?" } }, "required": [ - "name", - "query" + "prompt_text" ] }, - "description": "Query presentations for the document" + "maxItems": 25, + "description": "Full desired set of prompts after the update. Prompts omitted from this list are deleted; new prompts (no `id`) are appended in body order. Existing prompts retain their original position — reordering is not supported on this endpoint. At most 25 prompts total." + } + } + }, + "EvalPromptSetsDeleteResponse": { + "type": "object", + "properties": { + "cancelled_job_count": { + "type": "integer", + "description": "Number of in-flight agentic jobs associated with this prompt set that were cancelled as part of the archive.", + "example": 0 + }, + "is_archived": { + "type": "boolean", + "enum": [ + true + ], + "description": "Always `true` on success — archives the prompt set." } }, "required": [ - "modelId", - "name" + "cancelled_job_count", + "is_archived" ] }, - "DocumentIdentifier": { - "type": "string", - "minLength": 2, - "maxLength": 48, - "description": "Optional document identifier. If omitted, an identifier is auto-generated. Must be unique within the organization." + "EvalApiError500": { + "type": "object", + "properties": { + "detail": { + "type": "string", + "description": "Human-readable error message describing what went wrong.", + "example": "Archive committed but a run-cancellation failed; retry to complete" + }, + "status": { + "type": "integer", + "description": "HTTP status code of the error.", + "example": 500 + } + }, + "required": [ + "detail", + "status" + ] }, - "ApiVisConfig": { + "EvalPromptSetsUnarchiveResponse": { "type": "object", "properties": { - "config": { - "type": "object", - "additionalProperties": {}, - "description": "Visualization spec (chart configuration)" + "prompt_set": { + "$ref": "#/components/schemas/EvalPromptSet" + } + }, + "required": [ + "prompt_set" + ] + }, + "EvalRunsListResponse": { + "type": "object", + "properties": { + "runs": { + "type": "array", + "items": { + "$ref": "#/components/schemas/EvalRunListItem" + }, + "description": "Runs for the prompt set, newest first, filtered to those whose model the caller can access." + } + }, + "required": [ + "runs" + ] + }, + "EvalRunListItem": { + "type": "object", + "properties": { + "branch_id": { + "type": [ + "string", + "null" + ], + "format": "uuid", + "description": "Optional branch ID the run was executed against. Null when run against the main shared model.", + "example": null }, - "fields": { + "branch_name": { "type": [ - "array", + "string", "null" ], - "items": { - "type": "string", - "minLength": 1 - }, - "description": "Field names used in the visualization" + "description": "Display name for the branch, if `branch_id` is set.", + "example": null }, - "visType": { - "type": "string", - "enum": [ - "vegalite", - "omni-ai-summary-markdown", - "basic", - "omni-kpi", - "map", - "omni-markdown", - "funnel", - "sankey", - "single-record", - "svg-map", - "omni-spreadsheet", - "spreadsheet-tab", - "summary-value", - "omni-table", - "app" + "completed_at": { + "type": [ + "string", + "null" ], - "description": "Visualization type (e.g. basic, omni-markdown, omni-table)" - } - }, - "additionalProperties": {}, - "description": "Visualization configuration" - }, - "DocumentsGetResponse": { - "type": "object", - "properties": { + "description": "ISO 8601 timestamp when the run reached a terminal state.", + "example": null + }, + "created_at": { + "type": [ + "string", + "null" + ], + "description": "ISO 8601 timestamp when the run was created.", + "example": "2025-01-15T10:00:00.000Z" + }, "description": { "type": [ "string", "null" ], - "description": "Document description" + "description": "Optional human-readable description for the run.", + "example": null }, - "documentMetadata": { - "description": "Document metadata" + "id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the run.", + "example": "660e8400-e29b-41d4-a716-446655440001" }, - "facetFilters": { + "is_archived": { "type": "boolean", - "description": "Whether facet filters are enabled" - }, - "filterConfig": { - "description": "Dashboard filter configuration" - }, - "filterOrder": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Order of filters" + "description": "Whether the run has been archived.", + "example": false }, - "modelId": { + "model_id": { "type": "string", - "description": "Model ID" + "format": "uuid", + "description": "The shared model this run was executed against.", + "example": "880e8400-e29b-41d4-a716-446655440003" }, - "name": { + "prompt_set_id": { "type": "string", - "description": "Document name" + "format": "uuid", + "description": "The prompt set this run was created from.", + "example": "550e8400-e29b-41d4-a716-446655440000" }, - "queryPresentations": { - "type": "array", - "items": {}, - "description": "Query presentations" + "run_number": { + "type": "integer", + "description": "Sequential, per-prompt-set run number.", + "example": 3 }, - "refreshInterval": { - "type": [ - "number", - "null" + "stats": { + "$ref": "#/components/schemas/EvalRunStats" + }, + "status": { + "type": "string", + "enum": [ + "RUNNING", + "COMPLETE", + "CANCELLED" ], - "description": "Auto-refresh interval in seconds" + "description": "Run-level lifecycle. Flips to a terminal state (COMPLETE or CANCELLED) exactly once.", + "example": "RUNNING" } }, "required": [ - "facetFilters", - "filterOrder", - "modelId", - "name", - "queryPresentations", - "refreshInterval" + "branch_id", + "branch_name", + "completed_at", + "created_at", + "description", + "id", + "is_archived", + "model_id", + "prompt_set_id", + "run_number", + "stats", + "status" ] }, - "DocumentsPutResponse": { + "EvalRunStats": { "type": "object", "properties": { - "description": { - "type": [ - "string", - "null" - ], - "description": "Document description" + "terminal": { + "type": "integer", + "description": "Number of per-prompt jobs that have reached a terminal state (COMPLETE, FAILED, or CANCELLED).", + "example": 8 }, - "identifier": { - "type": "string", - "description": "Document identifier" + "total": { + "type": "integer", + "description": "Total number of per-prompt jobs in the run.", + "example": 12 + } + }, + "required": [ + "terminal", + "total" + ] + }, + "EvalRunsCreateResponse": { + "type": "object", + "properties": { + "job_count": { + "type": "integer", + "description": "Number of per-prompt agentic jobs created for this run (one per prompt that fanned out successfully). Enqueue onto the work queue happens after creation and is best-effort, so this count reflects jobs created, not necessarily those successfully enqueued.", + "example": 12 }, - "name": { - "type": "string", - "description": "Updated document name" + "run": { + "$ref": "#/components/schemas/EvalRunDetail" } }, "required": [ - "identifier", - "name" + "job_count", + "run" ] }, - "DocumentsPutBody": { + "EvalRunDetail": { "type": "object", "properties": { - "clearExistingDraft": { - "type": "boolean", - "default": false, - "description": "Clear existing draft before updating (for published documents with drafts)" + "branch_id": { + "type": [ + "string", + "null" + ], + "format": "uuid", + "description": "Optional branch ID the run was executed against. Null when run against the main shared model.", + "example": null + }, + "branch_name": { + "type": [ + "string", + "null" + ], + "description": "Display name for the branch, if `branch_id` is set.", + "example": null + }, + "completed_at": { + "type": [ + "string", + "null" + ], + "description": "ISO 8601 timestamp when the run reached a terminal state.", + "example": null + }, + "created_at": { + "type": [ + "string", + "null" + ], + "description": "ISO 8601 timestamp when the run was created.", + "example": "2025-01-15T10:00:00.000Z" }, "description": { "type": [ "string", "null" ], - "description": "Document description" + "description": "Optional human-readable description for the run.", + "example": null }, - "documentMetadata": { - "description": "Document presentation metadata" + "id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the run.", + "example": "660e8400-e29b-41d4-a716-446655440001" }, - "facetFilters": { + "is_archived": { "type": "boolean", - "description": "Enable facet filters" + "description": "Whether the run has been archived.", + "example": false }, - "filterConfig": { - "description": "Filter configuration" + "model_id": { + "type": "string", + "format": "uuid", + "description": "The shared model this run was executed against.", + "example": "880e8400-e29b-41d4-a716-446655440003" }, - "filterOrder": { + "prompt_set_id": { + "type": "string", + "format": "uuid", + "description": "The prompt set this run was created from.", + "example": "550e8400-e29b-41d4-a716-446655440000" + }, + "results": { "type": "array", "items": { - "type": "string" + "$ref": "#/components/schemas/EvalRunResult" }, - "description": "Order of filters" + "description": "Per-prompt results for this run, ordered by their creation order in the prompt set." }, - "modelId": { + "run_number": { + "type": "integer", + "description": "Sequential, per-prompt-set run number.", + "example": 3 + }, + "status": { "type": "string", - "description": "Model ID" + "enum": [ + "RUNNING", + "COMPLETE", + "CANCELLED" + ], + "description": "Run-level lifecycle. Flips to a terminal state (COMPLETE or CANCELLED) exactly once.", + "example": "RUNNING" + } + }, + "required": [ + "branch_id", + "branch_name", + "completed_at", + "created_at", + "description", + "id", + "is_archived", + "model_id", + "prompt_set_id", + "results", + "run_number", + "status" + ], + "description": "The newly created run with its initial results." + }, + "EvalRunResult": { + "type": "object", + "properties": { + "agentic_job": { + "$ref": "#/components/schemas/EvalRunResultAgenticJob" }, - "name": { + "cost": { + "type": [ + "number", + "null" + ], + "description": "Total LLM cost (USD) for this prompt, if available.", + "example": 0.0021 + }, + "error_reason": { + "type": [ + "string", + "null" + ], + "description": "Failure reason string for prompts whose underlying job failed.", + "example": null + }, + "expectation": { + "type": [ + "string", + "null" + ], + "description": "The prompt's expectation as of run creation (snapshotted, so later prompt edits don't change past runs), or null when none was set. The analysis judge scores the analysis against it.", + "example": "The top product by revenue should be Aniseed Syrup." + }, + "id": { "type": "string", - "minLength": 1, - "maxLength": 254, - "description": "Document name" + "format": "uuid", + "description": "Unique identifier for the run result row.", + "example": "aa0e8400-e29b-41d4-a716-446655440005" }, - "queryPresentations": { - "type": "array", - "items": { - "$ref": "#/components/schemas/DocumentsPutQueryPresentation" - }, - "minItems": 1, - "description": "Query presentations (full replacement)" + "prompt": { + "type": "string", + "description": "The prompt text that was evaluated.", + "example": "What are the top 5 products by revenue?" }, - "refreshInterval": { + "score": { + "type": [ + "number", + "null" + ], + "description": "Numeric judge score for this prompt result, if scoring ran.", + "example": 0.9 + }, + "scoring_cost": { + "type": [ + "number", + "null" + ], + "description": "Total LLM cost (USD) for scoring this prompt result.", + "example": 0.0004 + }, + "timing_ms": { "type": [ "integer", "null" ], - "minimum": 60, - "description": "Auto-refresh interval in seconds" + "description": "Wall-clock duration of the underlying job in milliseconds.", + "example": 4321 } }, "required": [ - "facetFilters", - "filterOrder", - "modelId", - "name", - "queryPresentations", - "refreshInterval" + "agentic_job", + "cost", + "error_reason", + "expectation", + "id", + "prompt", + "score", + "scoring_cost", + "timing_ms" ] }, - "DocumentsPutQueryPresentation": { + "EvalRunResultAgenticJob": { "type": "object", "properties": { - "aiConfig": { - "type": "object", - "properties": { - "description": { - "type": "object", - "properties": { - "aiContext": { - "type": "string" - }, - "enabled": { - "type": "boolean" - } - } - }, - "subTitle": { - "type": "object", - "properties": { - "aiContext": { - "type": "string" - }, - "enabled": { - "type": "boolean" - } - } - } - }, - "description": "AI configuration" - }, - "chartType": { + "conversation_id": { "type": [ "string", "null" ], - "enum": [ - "auto", - "area", - "areaStacked", - "areaStackedPercentage", - "bar", - "barLine", - "barGrouped", - "barStacked", - "barStackedPercentage", - "boxplot", - "code", - "column", - "columnGrouped", - "columnStacked", - "columnStackedPercentage", - "heatmap", - "kpi", - "line", - "lineColor", - "map", - "regionMap", - "markdown", - "omni-ai-summary-markdown", - "pie", - "funnel", - "sankey", - "point", - "pointColor", - "pointSize", - "pointSizeColor", - "singleRecord", - "omni-spreadsheet", - "summaryValue", - "svgMap", - "table", - null - ], - "description": "Chart type" + "format": "uuid", + "description": "Conversation the agentic job belongs to.", + "example": "770e8400-e29b-41d4-a716-446655440002" }, - "description": { + "id": { "type": "string", - "description": "Description" + "format": "uuid", + "description": "Agentic job identifier.", + "example": "990e8400-e29b-41d4-a716-446655440004" }, - "name": { + "state": { "type": "string", - "description": "Query presentation name" - }, - "prefersChart": { - "type": "boolean", - "description": "Whether to prefer chart view" - }, - "query": { - "description": "Query definition" - }, - "resultConfig": { - "description": "Result config" - }, - "subTitle": { + "enum": [ + "CANCELLED", + "COMPLETE", + "DELIVERING", + "EXECUTING", + "FAILED", + "QUEUED" + ], + "description": "Current state of the agentic job that ran this prompt.", + "example": "COMPLETE" + } + }, + "required": [ + "conversation_id", + "id", + "state" + ] + }, + "EvalApiError429": { + "type": "object", + "properties": { + "detail": { "type": "string", - "description": "Subtitle" + "description": "Human-readable error message describing what went wrong.", + "example": "Too many active runs; wait for an in-flight run to finish" }, - "topicName": { + "status": { + "type": "integer", + "description": "HTTP status code of the error.", + "example": 429 + } + }, + "required": [ + "detail", + "status" + ] + }, + "EvalApiError503": { + "type": "object", + "properties": { + "detail": { "type": "string", - "description": "Topic name" + "description": "Human-readable error message describing what went wrong.", + "example": "AI eval is paused for this organization" }, - "visConfig": { - "$ref": "#/components/schemas/ApiVisConfig" + "status": { + "type": "integer", + "description": "HTTP status code of the error.", + "example": 503 } }, "required": [ - "name" + "detail", + "status" ] }, - "DocumentsUpdateResponse": { + "EvalRunsCreateBody": { "type": "object", "properties": { "description": { @@ -2557,4053 +25154,4320 @@ "string", "null" ], - "description": "Document description" + "maxLength": 1024, + "description": "Optional human-readable description for the run. Pass `null` to clear (or omit). Max 1024 characters.", + "example": "Re-running after switching to gpt-4o for query generation" }, - "identifier": { + "prompt_set_id": { "type": "string", - "description": "Document identifier" + "format": "uuid", + "description": "The prompt set to execute.", + "example": "550e8400-e29b-41d4-a716-446655440000" }, - "name": { - "type": "string", - "description": "Updated document name" + "run_config": { + "type": "object", + "properties": { + "branch_id": { + "type": "string", + "format": "uuid", + "description": "Optional branch ID to run against. Must be a branch of the prompt set's model.", + "example": "440e8400-e29b-41d4-a716-446655440006" + } + }, + "description": "Per-run configuration. Optional — omit if no overrides." } }, "required": [ - "identifier", - "name" + "prompt_set_id" ] }, - "DocumentsUpdateBody": { + "EvalRunsGetResponse": { "type": "object", "properties": { - "clearExistingDraft": { + "run": { + "$ref": "#/components/schemas/EvalRunDetail" + } + }, + "required": [ + "run" + ] + }, + "EvalRunsDeleteResponse": { + "type": "object", + "properties": { + "is_archived": { "type": "boolean", - "default": false, - "description": "Clear existing draft before updating (for published documents with drafts)" - }, - "description": { - "type": [ - "string", - "null" + "enum": [ + true ], - "description": "Document description" + "description": "Always `true` on success — the run has been archived." + } + }, + "required": [ + "is_archived" + ] + }, + "EvalRunsCancelResponse": { + "type": "object", + "properties": { + "cancelled": { + "type": "integer", + "description": "Number of per-prompt agentic jobs that were cancelled by this request.", + "example": 4 }, - "identifier": { + "run": { "allOf": [ { - "$ref": "#/components/schemas/DocumentIdentifier" + "$ref": "#/components/schemas/EvalRunDetail" }, { - "description": "New identifier for the document. Must be unique within the organization. The previous identifier is retained in the document identifier history and continues to redirect." + "description": "The cancelled run. `status: CANCELLED` and `is_archived: true` after this call." } ] }, - "name": { - "type": "string", - "minLength": 1, - "maxLength": 254, - "description": "New document name" + "total": { + "type": "integer", + "description": "Total number of per-prompt jobs in the run.", + "example": 12 } - } + }, + "required": [ + "cancelled", + "run", + "total" + ] }, - "SuccessResponse": { + "EvalRunsUnarchiveResponse": { "type": "object", "properties": { - "success": { + "is_archived": { "type": "boolean", - "description": "Whether the operation was successful", - "example": true + "enum": [ + false + ], + "description": "Always `false` on success — the run has been unarchived." } }, "required": [ - "success" + "is_archived" ] }, - "DocumentsGetQueriesResponse": { + "FoldersListResponse": { "type": "object", "properties": { - "queries": { + "pageInfo": { + "allOf": [ + { + "$ref": "#/components/schemas/PageInfo" + }, + { + "description": "Pagination information" + } + ] + }, + "records": { "type": "array", "items": { "type": "object", "properties": { + "_count": { + "type": "object", + "properties": { + "documents": { + "type": "number", + "description": "Number of documents in the folder" + }, + "favorites": { + "type": "number", + "description": "Number of users who have favorited this folder" + } + }, + "required": [ + "documents", + "favorites" + ], + "description": "Count statistics for the folder" + }, "id": { "type": "string", - "description": "Query presentation ID" + "format": "uuid", + "description": "Unique folder identifier" + }, + "labels": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Labels associated with the folder" }, "name": { "type": "string", - "description": "Query presentation name" + "description": "Name of the folder", + "example": "My Reports" }, - "query": { - "description": "Query JSON definition" + "ownerId": { + "type": "string", + "format": "uuid", + "description": "User ID of the folder owner" }, - "queryIdentifierMapKey": { + "path": { "type": "string", - "description": "Key in the query identifier map" + "description": "Full path to the folder", + "example": "/shared/reports/my-reports" }, "url": { "type": "string", - "description": "URL to view this specific query/sheet in the workbook.", - "example": "https://org.omni.co/w/abc123?key=1" + "description": "URL to view the folder in the Omni UI.", + "example": "https://org.omni.co/f/my-reports" } }, "required": [ "id", "name", - "queryIdentifierMapKey", + "ownerId", + "path", "url" ] }, - "description": "List of queries in the document" + "description": "List of folders" } }, "required": [ - "queries" + "pageInfo", + "records" ] }, - "DocumentsMoveBody": { + "FoldersCreateResponse": { "type": "object", "properties": { - "folderPath": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "Destination folder path (null for root)" - }, - "scope": { + "id": { "type": "string", - "enum": [ - "restricted", - "organization" - ], - "description": "Access scope for the document" - } - }, - "required": [ - "folderPath" - ] - }, - "DocumentsGetPermissionsResponse": { - "type": "object", - "properties": { - "permits": { - "description": "User permits for the document" - } - } - }, - "DocumentsUpdatePermissionSettingsBody": { - "type": "object", - "properties": { - "canDownload": { - "type": "boolean", - "description": "Allow downloading" - }, - "canDrill": { - "type": "boolean", - "description": "Allow drill-down" - }, - "canSchedule": { - "type": "boolean", - "description": "Allow scheduling" - }, - "canUpload": { - "type": "boolean", - "description": "Allow uploads" - }, - "canUseDashboardAi": { - "type": "boolean", - "description": "Allow using dashboard AI" - }, - "canViewWorkbook": { - "type": "boolean", - "description": "Allow viewing workbook" + "format": "uuid", + "description": "ID of the created folder" }, - "organizationAccessBoost": { - "type": "boolean", - "description": "Boost organization access" + "name": { + "type": "string", + "description": "Name of the created folder" }, - "organizationRole": { + "ownerId": { "type": "string", - "enum": [ - "viewer", - "editor", - "manager", - "no_access" - ], - "description": "Organization-wide role for the document" + "format": "uuid", + "description": "User ID of the folder owner" }, - "requirePullRequestToPublish": { - "type": "boolean", - "description": "Require pull request to publish changes" - } - } - }, - "DocumentsAddPermitsBody": { - "type": "object", - "properties": { - "accessBoost": { - "type": "boolean", - "default": false, - "description": "Grant access boost" + "path": { + "type": "string", + "description": "Full path to the folder" }, - "role": { + "scope": { "type": "string", "enum": [ - "NO_ACCESS", - "VIEWER", - "EXPLORER", - "EDITOR", - "MANAGER" + "organization", + "restricted" ], - "description": "Role to grant" - }, - "userGroupIds": { - "type": "array", - "items": { - "type": "string" - }, - "default": [], - "description": "User group IDs to grant access to" - }, - "userIds": { - "type": "array", - "items": { - "type": "string", - "format": "uuid" - }, - "default": [], - "description": "User membership IDs to grant access to" + "description": "Share scope of the folder" } }, "required": [ - "role" + "id", + "name", + "ownerId", + "path", + "scope" ] }, - "DocumentsUpdatePermitsBody": { + "FoldersCreateBody": { "type": "object", "properties": { - "accessBoost": { - "type": "boolean", - "description": "Access boost setting" + "name": { + "type": "string", + "minLength": 1, + "description": "Name of the folder to create", + "example": "My New Folder" }, - "role": { + "parentFolderId": { + "type": "string", + "format": "uuid", + "description": "Parent folder ID (omit to create at root level)" + }, + "scope": { "type": "string", "enum": [ - "NO_ACCESS", - "VIEWER", - "EXPLORER", - "EDITOR", - "MANAGER" + "organization", + "restricted" ], - "description": "Role to set" - }, - "userGroupIds": { - "type": "array", - "items": { - "type": "string" - }, - "default": [], - "description": "User group IDs to update" - }, - "userIds": { - "type": "array", - "items": { - "type": "string", - "format": "uuid" - }, - "default": [], - "description": "User membership IDs to update" - } - } - }, - "DocumentsRevokePermitsBody": { - "type": "object", - "properties": { - "userGroupIds": { - "type": "array", - "items": { - "type": "string" - }, - "default": [], - "description": "User group IDs to revoke access from" + "description": "Share scope for the folder" }, - "userIds": { - "type": "array", - "items": { - "type": "string", - "format": "uuid" - }, - "default": [], - "description": "User membership IDs to revoke access from" - } - } - }, - "DocumentsCreateDraftResponse": { - "type": "object", - "properties": { - "identifier": { + "userId": { "type": "string", - "description": "Draft document identifier" + "format": "uuid", + "description": "User ID to create the folder as (for org-scoped API keys only)" } }, "required": [ - "identifier" + "name" ] }, - "DocumentsCreateDraftBody": { - "type": "object", - "properties": { - "branchId": { - "type": "string", - "format": "uuid", - "description": "Branch ID for the draft" - } - } - }, - "DocumentsDiscardDraftResponse": { + "FoldersDeleteResponse": { "type": "object", "properties": { - "message": { - "type": "string", - "description": "Success message" + "success": { + "type": "boolean", + "description": "Whether the folder was deleted successfully" } }, "required": [ - "message" + "success" ] }, - "DocumentsDiscardDraftBody": { - "type": "object", - "properties": { - "branchId": { - "type": "string", - "format": "uuid", - "description": "Branch ID for the draft" - } - } - }, - "DocumentsDuplicateResponse": { + "FoldersUpdateResponse": { "type": "object", "properties": { - "dashboardId": { - "type": "string", - "description": "New dashboard ID" - }, - "identifier": { + "id": { "type": "string", - "description": "New document identifier" + "format": "uuid", + "description": "Folder ID" }, "name": { "type": "string", - "description": "Document name" + "description": "Updated folder name" }, - "workbookId": { + "path": { "type": "string", - "description": "New workbook ID" + "description": "Updated URL path segment for the folder (the folder's own segment only)" } }, "required": [ - "dashboardId", - "identifier", + "id", "name", - "workbookId" + "path" ] }, - "DocumentsDuplicateBody": { + "FoldersUpdateBody": { "type": "object", "properties": { - "folderPath": { - "type": [ - "string", - "null" - ], - "description": "Destination folder path (null for root)" - }, "name": { "type": "string", "minLength": 1, - "maxLength": 254, - "description": "Name for the duplicated document" + "description": "New display name for the folder", + "example": "Q1 Reports" }, - "scope": { + "path": { "type": "string", - "enum": [ - "restricted", - "organization" - ], - "description": "Access scope for the duplicated document" + "minLength": 1, + "pattern": "^[a-zA-Z0-9-]+$", + "description": "New URL path segment for the folder (alphanumeric and dashes only). This is only the folder's own segment, not the full hierarchical path.", + "example": "q1-reports" + }, + "resolvePathConflict": { + "type": "boolean", + "default": false, + "description": "When true, automatically resolves path collisions with existing folders by appending a numeric suffix (e.g., my-path-1). When false (default), returns 409 Conflict if the path is already taken. Does not apply to reserved paths, which are always rejected with 400." } - }, - "required": [ - "name" - ] + } }, - "DocumentsBulkUpdateLabelsResponse": { + "FoldersGetPermissionsResponse": { "type": "object", "properties": { - "labels": { + "permits": { "type": "array", "items": { - "type": "string" + "type": "object", + "properties": { + "accessBoost": { + "type": "boolean", + "description": "Whether access boost is enabled for this permit" + }, + "role": { + "type": "string", + "description": "Content role (e.g., VIEWER, EDITOR, MANAGER)", + "example": "VIEWER" + }, + "userGroupId": { + "type": "string", + "description": "User group ID if this is a group permit" + }, + "userId": { + "type": "string", + "format": "uuid", + "description": "User ID if this is a user permit" + } + }, + "required": [ + "role" + ] }, - "description": "Updated list of labels on the document" + "description": "List of permission permits for the folder" } }, "required": [ - "labels" + "permits" ] }, - "DocumentsBulkUpdateLabelsBody": { + "FoldersAddPermissionsResponse": { "type": "object", "properties": { - "add": { + "success": { + "type": "boolean", + "description": "Whether the permissions were added successfully" + } + }, + "required": [ + "success" + ] + }, + "FoldersAddPermissionsBody": { + "type": "object", + "properties": { + "accessBoost": { + "type": "boolean", + "default": false, + "description": "Whether to grant access boost" + }, + "role": { + "type": "string", + "enum": [ + "NO_ACCESS", + "VIEWER", + "EXPLORER", + "EDITOR", + "MANAGER" + ], + "description": "Content role to assign (VIEWER, EDITOR, or MANAGER)", + "example": "VIEWER" + }, + "userGroupIds": { "type": "array", "items": { "type": "string" }, "default": [], - "description": "Labels to add" + "description": "User group IDs to grant permission to" }, - "remove": { + "userIds": { "type": "array", "items": { - "type": "string" + "type": "string", + "format": "uuid" }, "default": [], - "description": "Labels to remove" + "description": "User IDs to grant permission to" } - } + }, + "required": [ + "role" + ], + "additionalProperties": false }, - "DocumentsTransferOwnershipBody": { + "FoldersUpdatePermissionsResponse": { "type": "object", "properties": { - "userId": { - "type": "string", - "format": "uuid", - "description": "Membership ID of the new owner" + "success": { + "type": "boolean", + "description": "Whether the permissions were updated successfully" } }, "required": [ - "userId" + "success" ] }, - "DocumentsAccessListResponse": { + "FoldersUpdatePermissionsBody": { "type": "object", "properties": { - "pageInfo": { - "allOf": [ - { - "$ref": "#/components/schemas/PageInfo" - }, - { - "description": "Pagination information" - } - ] + "accessBoost": { + "type": "boolean", + "description": "Whether to grant access boost" }, - "principals": { + "role": { + "type": "string", + "enum": [ + "NO_ACCESS", + "VIEWER", + "EXPLORER", + "EDITOR", + "MANAGER" + ], + "description": "New content role to assign" + }, + "userGroupIds": { "type": "array", - "items": {}, - "description": "List of users and groups with access" + "items": { + "type": "string" + }, + "default": [], + "description": "User group IDs to update permissions for" + }, + "userIds": { + "type": "array", + "items": { + "type": "string", + "format": "uuid" + }, + "default": [], + "description": "User IDs to update permissions for" } }, - "required": [ - "pageInfo", - "principals" - ] + "additionalProperties": false }, - "EmbedSsoGenerateSessionResponse": { + "FoldersRevokePermissionsResponse": { "type": "object", "properties": { - "sessionId": { - "type": "string", - "description": "Session ID to use for embedding Omni content" + "success": { + "type": "boolean", + "description": "Whether the permissions were revoked successfully" } }, "required": [ - "sessionId" + "success" ] }, - "EmbedSsoGenerateSessionBody": { + "FoldersRevokePermissionsBody": { "type": "object", "properties": { - "externalId": { - "type": "string", - "description": "External identifier for the user (from your system)", - "example": "user-123" - }, - "groups": { + "userGroupIds": { "type": "array", "items": { "type": "string" }, - "description": "Optional list of group names to assign to the user", - "example": [ - "engineering", - "sales" - ] - }, - "name": { - "type": "string", - "description": "Display name for the user", - "example": "John Doe" + "default": [], + "description": "User group IDs to revoke permissions from" }, - "userAttributes": { - "type": "object", - "additionalProperties": {}, - "description": "Optional user attributes for row-level security" + "userIds": { + "type": "array", + "items": { + "type": "string", + "format": "uuid" + }, + "default": [], + "description": "User IDs to revoke permissions from" } }, - "required": [ - "externalId", - "name" - ] + "additionalProperties": false }, - "FoldersListResponse": { + "LabelsListResponse": { "type": "object", - "properties": { - "pageInfo": { - "allOf": [ - { - "$ref": "#/components/schemas/PageInfo" - }, - { - "description": "Pagination information" - } - ] - }, - "records": { + "properties": { + "labels": { "type": "array", "items": { "type": "object", "properties": { - "_count": { - "type": "object", - "properties": { - "documents": { - "type": "number", - "description": "Number of documents in the folder" - }, - "favorites": { - "type": "number", - "description": "Number of users who have favorited this folder" - } - }, - "required": [ - "documents", - "favorites" + "color": { + "type": [ + "string", + "null" ], - "description": "Count statistics for the folder" + "maxLength": 9, + "description": "Hex color for the label (e.g. #0366d6)", + "example": "#0366d6" }, - "id": { - "type": "string", - "format": "uuid", - "description": "Unique folder identifier" + "description": { + "type": [ + "string", + "null" + ], + "maxLength": 500, + "description": "Label description", + "example": "Important items that need attention" }, - "labels": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Labels associated with the folder" + "homepage": { + "type": "boolean", + "description": "Whether label is shown on homepage" }, "name": { "type": "string", - "description": "Name of the folder", - "example": "My Reports" - }, - "ownerId": { - "type": "string", - "format": "uuid", - "description": "User ID of the folder owner" + "description": "Label name", + "example": "verified" }, - "path": { - "type": "string", - "description": "Full path to the folder", - "example": "/shared/reports/my-reports" + "usage_count": { + "type": "number", + "description": "Number of documents with this label" }, - "url": { - "type": "string", - "description": "URL to view the folder in the Omni UI.", - "example": "https://org.omni.co/f/my-reports" + "verified": { + "type": "boolean", + "description": "Whether label is verified" } }, "required": [ - "id", + "color", + "description", + "homepage", "name", - "ownerId", - "path", - "url" + "usage_count", + "verified" ] }, - "description": "List of folders" + "description": "List of labels" } }, "required": [ - "pageInfo", - "records" + "labels" ] }, - "FoldersCreateResponse": { + "LabelsCreateResponse": { "type": "object", "properties": { - "id": { - "type": "string", - "format": "uuid", - "description": "ID of the created folder" + "color": { + "type": [ + "string", + "null" + ], + "maxLength": 9, + "description": "Hex color for the label (e.g. #0366d6)", + "example": "#0366d6" }, - "name": { - "type": "string", - "description": "Name of the created folder" + "description": { + "type": [ + "string", + "null" + ], + "maxLength": 500, + "description": "Label description", + "example": "Important items that need attention" }, - "ownerId": { - "type": "string", - "format": "uuid", - "description": "User ID of the folder owner" + "homepage": { + "type": "boolean", + "description": "Whether label is shown on homepage" }, - "path": { + "name": { "type": "string", - "description": "Full path to the folder" + "description": "Label name", + "example": "verified" }, - "scope": { - "type": "string", - "enum": [ - "organization", - "restricted" - ], - "description": "Share scope of the folder" + "usage_count": { + "type": "number", + "description": "Number of documents with this label" + }, + "verified": { + "type": "boolean", + "description": "Whether label is verified" } }, "required": [ - "id", + "color", + "description", + "homepage", "name", - "ownerId", - "path", - "scope" + "usage_count", + "verified" ] }, - "FoldersCreateBody": { + "LabelsCreateBody": { "type": "object", "properties": { + "color": { + "type": [ + "string", + "null" + ], + "maxLength": 9, + "default": null, + "description": "Hex color for the label (e.g. #0366d6)", + "example": "#0366d6" + }, + "description": { + "type": [ + "string", + "null" + ], + "maxLength": 500, + "default": null, + "description": "Label description", + "example": "Important items that need attention" + }, + "homepage": { + "type": "boolean", + "default": false, + "description": "Show label on homepage. Requires admin permissions." + }, "name": { "type": "string", - "minLength": 1, - "description": "Name of the folder to create", - "example": "My New Folder" + "minLength": 2, + "maxLength": 25, + "description": "Label name", + "example": "important" }, - "parentFolderId": { - "type": "string", - "format": "uuid", - "description": "Parent folder ID (omit to create at root level)" + "verified": { + "type": "boolean", + "default": false, + "description": "Mark as verified label. Requires admin permissions." + } + }, + "required": [ + "name" + ] + }, + "LabelsGetResponse": { + "type": "object", + "properties": { + "color": { + "type": [ + "string", + "null" + ], + "maxLength": 9, + "description": "Hex color for the label (e.g. #0366d6)", + "example": "#0366d6" }, - "scope": { - "type": "string", - "enum": [ - "organization", - "restricted" + "description": { + "type": [ + "string", + "null" ], - "description": "Share scope for the folder" + "maxLength": 500, + "description": "Label description", + "example": "Important items that need attention" }, - "userId": { + "homepage": { + "type": "boolean", + "description": "Whether label is shown on homepage" + }, + "name": { "type": "string", - "format": "uuid", - "description": "User ID to create the folder as (for org-scoped API keys only)" + "description": "Label name", + "example": "verified" + }, + "usage_count": { + "type": "number", + "description": "Number of documents with this label" + }, + "verified": { + "type": "boolean", + "description": "Whether label is verified" } }, "required": [ - "name" + "color", + "description", + "homepage", + "name", + "usage_count", + "verified" ] }, - "FoldersDeleteResponse": { + "LabelsUpdateResponse": { "type": "object", "properties": { - "success": { + "color": { + "type": [ + "string", + "null" + ], + "maxLength": 9, + "description": "Hex color for the label (e.g. #0366d6)", + "example": "#0366d6" + }, + "description": { + "type": [ + "string", + "null" + ], + "maxLength": 500, + "description": "Label description", + "example": "Important items that need attention" + }, + "homepage": { "type": "boolean", - "description": "Whether the folder was deleted successfully" - } - }, - "required": [ - "success" - ] - }, - "FoldersUpdateResponse": { - "type": "object", - "properties": { - "id": { - "type": "string", - "format": "uuid", - "description": "Folder ID" + "description": "Whether label is shown on homepage" }, "name": { "type": "string", - "description": "Updated folder name" + "description": "Label name", + "example": "verified" }, - "path": { - "type": "string", - "description": "Updated URL path segment for the folder (the folder's own segment only)" + "usage_count": { + "type": "number", + "description": "Number of documents with this label" + }, + "verified": { + "type": "boolean", + "description": "Whether label is verified" } }, "required": [ - "id", + "color", + "description", + "homepage", "name", - "path" + "usage_count", + "verified" ] }, - "FoldersUpdateBody": { + "LabelsUpdateBody": { "type": "object", "properties": { - "name": { - "type": "string", - "minLength": 1, - "description": "New display name for the folder", - "example": "Q1 Reports" + "color": { + "type": [ + "string", + "null" + ], + "maxLength": 9, + "description": "Hex color for the label (e.g. #0366d6)", + "example": "#0366d6" }, - "path": { + "description": { + "type": [ + "string", + "null" + ], + "maxLength": 500, + "description": "Label description", + "example": "Important items that need attention" + }, + "homepage": { + "type": "boolean", + "description": "Show label on homepage. Requires admin permissions to modify." + }, + "name": { "type": "string", - "minLength": 1, - "pattern": "^[a-zA-Z0-9-]+$", - "description": "New URL path segment for the folder (alphanumeric and dashes only). This is only the folder's own segment, not the full hierarchical path.", - "example": "q1-reports" + "minLength": 2, + "maxLength": 25, + "description": "Label name", + "example": "important" }, - "resolvePathConflict": { + "verified": { "type": "boolean", - "default": false, - "description": "When true, automatically resolves path collisions with existing folders by appending a numeric suffix (e.g., my-path-1). When false (default), returns 409 Conflict if the path is already taken. Does not apply to reserved paths, which are always rejected with 400." + "description": "Mark as verified label. Requires admin permissions to modify." } } }, - "FoldersGetPermissionsResponse": { + "ModelsListResponse": { "type": "object", "properties": { - "permits": { + "pageInfo": { + "allOf": [ + { + "$ref": "#/components/schemas/PageInfo" + }, + { + "description": "Pagination information" + } + ] + }, + "records": { "type": "array", "items": { "type": "object", "properties": { - "accessBoost": { - "type": "boolean", - "description": "Whether access boost is enabled for this permit" + "baseModelId": { + "type": [ + "string", + "null" + ], + "description": "Base model ID for branch/extension models" }, - "role": { + "branches": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Branch ID" + }, + "name": { + "type": "string", + "description": "Branch name" + } + }, + "required": [ + "id", + "name" + ] + }, + "description": "Active branches (if include=activeBranches)" + }, + "connectionId": { + "type": [ + "string", + "null" + ], + "description": "Connection ID" + }, + "createdAt": { "type": "string", - "description": "Content role (e.g., VIEWER, EDITOR, MANAGER)", - "example": "VIEWER" + "description": "Creation timestamp" }, - "userGroupId": { + "deletedAt": { + "type": [ + "string", + "null" + ], + "description": "Deletion timestamp" + }, + "id": { "type": "string", - "description": "User group ID if this is a group permit" + "description": "Model ID" }, - "userId": { + "modelKind": { + "type": [ + "string", + "null" + ], + "description": "Model kind" + }, + "name": { + "type": [ + "string", + "null" + ], + "description": "Model name" + }, + "updatedAt": { "type": "string", - "format": "uuid", - "description": "User ID if this is a user permit" + "description": "Last update timestamp" } }, "required": [ - "role" + "baseModelId", + "connectionId", + "createdAt", + "deletedAt", + "id", + "modelKind", + "name", + "updatedAt" ] }, - "description": "List of permission permits for the folder" + "description": "List of model records" + } + }, + "required": [ + "pageInfo", + "records" + ] + }, + "CreateModelSchemaBase": { + "type": "object", + "properties": { + "accessGrants": { + "type": "array", + "items": { + "type": "object", + "properties": { + "accessBoostable": { + "type": "boolean" + }, + "allowedValues": { + "type": "array", + "items": { + "type": "string" + } + }, + "codeComments": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "ignored": { + "type": "boolean" + }, + "name": { + "type": "string" + }, + "userAttribute": { + "type": "string" + } + }, + "required": [ + "accessBoostable", + "name" + ] + }, + "description": "Access grants for the model" + }, + "allowAsWorkbookBase": { + "type": "boolean", + "description": "Allow this model as a workbook base" + }, + "baseModelId": { + "type": "string", + "description": "Base model ID for extension or branch models" + }, + "connectionId": { + "type": "string", + "description": "Connection ID for the model" + }, + "modelKind": { + "anyOf": [ + { + "type": "string", + "enum": [ + "SCHEMA" + ] + }, + { + "type": "string", + "enum": [ + "SHARED" + ] + }, + { + "type": "string", + "enum": [ + "SHARED_EXTENSION" + ] + }, + { + "type": "string", + "enum": [ + "BRANCH" + ] + } + ], + "default": "SCHEMA", + "description": "Kind of model to create" + }, + "modelName": { + "type": "string", + "description": "Name for the model" + }, + "usesIsolatedBranches": { + "type": "boolean", + "description": "For SHARED_EXTENSION models, controls if branches are shown on extension model page instead of parent shared model" } }, "required": [ - "permits" + "connectionId" ] }, - "FoldersAddPermissionsResponse": { + "ModelsUpdateResponse": { "type": "object", "properties": { + "model": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "Model ID" + }, + "name": { + "type": "string", + "description": "Updated model name" + } + }, + "required": [ + "id", + "name" + ], + "description": "Updated model details" + }, "success": { "type": "boolean", - "description": "Whether the permissions were added successfully" + "description": "Whether the operation succeeded" } }, "required": [ + "model", "success" ] }, - "FoldersAddPermissionsBody": { + "ModelsUpdateBody": { "type": "object", "properties": { - "accessBoost": { - "type": "boolean", - "default": false, - "description": "Whether to grant access boost" - }, - "role": { + "name": { "type": "string", - "enum": [ - "NO_ACCESS", - "VIEWER", - "EXPLORER", - "EDITOR", - "MANAGER" - ], - "description": "Content role to assign (VIEWER, EDITOR, or MANAGER)", - "example": "VIEWER" - }, - "userGroupIds": { - "type": "array", - "items": { - "type": "string" - }, - "default": [], - "description": "User group IDs to grant permission to" - }, - "userIds": { - "type": "array", - "items": { - "type": "string", - "format": "uuid" - }, - "default": [], - "description": "User IDs to grant permission to" - } - }, - "required": [ - "role" - ], - "additionalProperties": false - }, - "FoldersUpdatePermissionsResponse": { - "type": "object", - "properties": { - "success": { - "type": "boolean", - "description": "Whether the permissions were updated successfully" + "minLength": 1, + "description": "New name for the model", + "example": "My Renamed Model" } }, "required": [ - "success" + "name" ] }, - "FoldersUpdatePermissionsBody": { + "JobsGetStatusResponse": { "type": "object", "properties": { - "accessBoost": { - "type": "boolean", - "description": "Whether to grant access boost" + "job_id": { + "type": "string", + "description": "The job ID", + "example": "550e8400-e29b-41d4-a716-446655440000" }, - "role": { + "job_type": { + "type": "string", + "description": "The type of job (e.g., REFRESH_SCHEMA)", + "example": "REFRESH_SCHEMA" + }, + "status": { "type": "string", "enum": [ - "NO_ACCESS", - "VIEWER", - "EXPLORER", - "EDITOR", - "MANAGER" + "IN_PROGRESS", + "COMPLETED", + "FAILED" ], - "description": "New content role to assign" - }, - "userGroupIds": { - "type": "array", - "items": { - "type": "string" - }, - "default": [], - "description": "User group IDs to update permissions for" - }, - "userIds": { - "type": "array", - "items": { - "type": "string", - "format": "uuid" - }, - "default": [], - "description": "User IDs to update permissions for" - } - }, - "additionalProperties": false - }, - "FoldersRevokePermissionsResponse": { - "type": "object", - "properties": { - "success": { - "type": "boolean", - "description": "Whether the permissions were revoked successfully" + "description": "Current status of the job", + "example": "COMPLETED" } }, "required": [ - "success" + "job_id", + "job_type", + "status" ] }, - "FoldersRevokePermissionsBody": { + "ModelsGetSchemasResponse": { "type": "object", "properties": { - "userGroupIds": { + "schemas": { "type": "array", "items": { "type": "string" }, - "default": [], - "description": "User group IDs to revoke permissions from" - }, - "userIds": { - "type": "array", - "items": { - "type": "string", - "format": "uuid" - }, - "default": [], - "description": "User IDs to revoke permissions from" + "description": "Sorted list of all available schema names (catalog-scoped if applicable, e.g. warehouse.reporting)" } }, - "additionalProperties": false + "required": [ + "schemas" + ] }, - "LabelsListResponse": { + "ModelsGetViewResponse": { "type": "object", "properties": { - "labels": { + "success": { + "type": "boolean", + "description": "Whether the operation succeeded" + }, + "views": { "type": "array", "items": { "type": "object", "properties": { - "color": { - "type": [ - "string", - "null" - ], - "maxLength": 9, - "description": "Hex color for the label (e.g. #0366d6)", - "example": "#0366d6" - }, "description": { - "type": [ - "string", - "null" - ], - "maxLength": 500, - "description": "Label description", - "example": "Important items that need attention" + "type": "string", + "description": "View description" }, - "homepage": { + "fields": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Field name" + }, + "type": { + "type": "string", + "enum": [ + "dimension", + "measure", + "filter" + ], + "description": "Field type" + } + }, + "required": [ + "name", + "type" + ] + }, + "description": "Fields in the view" + }, + "hidden": { "type": "boolean", - "description": "Whether label is shown on homepage" + "description": "Whether the view is hidden" }, - "name": { + "label": { "type": "string", - "description": "Label name", - "example": "verified" - }, - "usage_count": { - "type": "number", - "description": "Number of documents with this label" + "description": "View label" }, - "verified": { - "type": "boolean", - "description": "Whether label is verified" + "name": { + "type": "string", + "description": "View name" } }, - "required": [ - "color", - "description", - "homepage", - "name", - "usage_count", - "verified" + "required": [ + "fields", + "name" ] }, - "description": "List of labels" + "description": "List of views" } }, "required": [ - "labels" + "success", + "views" ] }, - "LabelsCreateResponse": { + "ModelsUpdateViewBody": { "type": "object", "properties": { - "color": { - "type": [ - "string", - "null" - ], - "maxLength": 9, - "description": "Hex color for the label (e.g. #0366d6)", - "example": "#0366d6" + "aiContext": { + "type": "string", + "description": "AI context for the view" }, "description": { - "type": [ - "string", - "null" - ], - "maxLength": 500, - "description": "Label description", - "example": "Important items that need attention" + "type": "string", + "description": "View description" }, - "homepage": { + "format": { + "type": "string", + "description": "View format" + }, + "hidden": { "type": "boolean", - "description": "Whether label is shown on homepage" + "description": "Whether the view is hidden" }, - "name": { + "label": { "type": "string", - "description": "Label name", - "example": "verified" - }, - "usage_count": { - "type": "number", - "description": "Number of documents with this label" + "description": "View label" }, - "verified": { - "type": "boolean", - "description": "Whether label is verified" + "tags": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Tags for the view" } - }, - "required": [ - "color", - "description", - "homepage", - "name", - "usage_count", - "verified" - ] + } }, - "LabelsCreateBody": { + "ModelsUpdateFieldBody": { "type": "object", "properties": { - "color": { - "type": [ - "string", - "null" - ], - "maxLength": 9, - "default": null, - "description": "Hex color for the label (e.g. #0366d6)", - "example": "#0366d6" - }, - "description": { - "type": [ - "string", - "null" - ], - "maxLength": 500, - "default": null, - "description": "Label description", - "example": "Important items that need attention" + "aiContext": { + "type": "string", + "description": "AI context for the field" }, - "homepage": { - "type": "boolean", - "default": false, - "description": "Show label on homepage. Requires admin permissions." + "allValues": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Deprecated: use sampleValues instead" }, - "name": { - "type": "string", - "minLength": 2, - "maxLength": 25, - "description": "Label name", - "example": "important" + "binBoundaries": { + "type": "array", + "items": { + "type": "number" + }, + "description": "Bin boundaries for binned fields" }, - "verified": { - "type": "boolean", - "default": false, - "description": "Mark as verified label. Requires admin permissions." - } - }, - "required": [ - "name" - ] - }, - "LabelsGetResponse": { - "type": "object", - "properties": { - "color": { - "type": [ - "string", - "null" - ], - "maxLength": 9, - "description": "Hex color for the label (e.g. #0366d6)", - "example": "#0366d6" + "binLabels": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Labels for bins" }, "description": { - "type": [ - "string", - "null" - ], - "maxLength": 500, - "description": "Label description", - "example": "Important items that need attention" + "type": "string", + "description": "Field description" }, - "homepage": { - "type": "boolean", - "description": "Whether label is shown on homepage" + "drillFields": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Drill-down fields" }, - "name": { + "elseValue": { "type": "string", - "description": "Label name", - "example": "verified" - }, - "usage_count": { - "type": "number", - "description": "Number of documents with this label" + "description": "Else value for grouped fields" }, - "verified": { - "type": "boolean", - "description": "Whether label is verified" - } - }, - "required": [ - "color", - "description", - "homepage", - "name", - "usage_count", - "verified" - ] - }, - "LabelsUpdateResponse": { - "type": "object", - "properties": { - "color": { - "type": [ - "string", - "null" - ], - "maxLength": 9, - "description": "Hex color for the label (e.g. #0366d6)", - "example": "#0366d6" + "filters": { + "type": "object", + "additionalProperties": {}, + "description": "Filters for the field" }, - "description": { - "type": [ - "string", - "null" - ], - "maxLength": 500, - "description": "Label description", - "example": "Important items that need attention" + "format": { + "type": "string", + "description": "Field format" }, - "homepage": { - "type": "boolean", - "description": "Whether label is shown on homepage" + "groupFilters": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": {} + }, + "description": "Group filters" }, - "name": { + "groupLabel": { "type": "string", - "description": "Label name", - "example": "verified" + "description": "Group label" }, - "usage_count": { - "type": "number", - "description": "Number of documents with this label" + "groupNames": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Group names" }, - "verified": { - "type": "boolean", - "description": "Whether label is verified" - } - }, - "required": [ - "color", - "description", - "homepage", - "name", - "usage_count", - "verified" - ] - }, - "LabelsUpdateBody": { - "type": "object", - "properties": { - "color": { - "type": [ - "string", - "null" - ], - "maxLength": 9, - "description": "Hex color for the label (e.g. #0366d6)", - "example": "#0366d6" + "hidden": { + "type": "boolean", + "description": "Whether the field is hidden" }, - "description": { - "type": [ - "string", - "null" - ], - "maxLength": 500, - "description": "Label description", - "example": "Important items that need attention" + "ignored": { + "type": "boolean", + "description": "Whether the field is ignored" }, - "homepage": { + "isCalc": { "type": "boolean", - "description": "Show label on homepage. Requires admin permissions to modify." + "description": "Whether this is a calculation field" }, - "name": { + "label": { "type": "string", - "minLength": 2, - "maxLength": 25, - "description": "Label name", - "example": "important" + "description": "Field label" }, - "verified": { - "type": "boolean", - "description": "Mark as verified label. Requires admin permissions to modify." + "newFieldName": { + "type": "string", + "description": "New field name (for rename)" + }, + "newViewName": { + "type": "string", + "description": "New view name (for move)" + }, + "sampleValues": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Sample values for the field" + }, + "sql": { + "type": "string", + "description": "SQL expression for the field" + }, + "synonyms": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Synonyms for the field" + }, + "tags": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Tags for the field" + }, + "topicContext": { + "type": "string", + "description": "Topic context for the field" } } }, - "ModelsListResponse": { + "ModelsListTopicsResponse": { "type": "object", "properties": { - "pageInfo": { - "allOf": [ - { - "$ref": "#/components/schemas/PageInfo" - }, - { - "description": "Pagination information" - } - ] + "success": { + "type": "boolean", + "description": "Whether the operation succeeded" }, - "records": { + "topics": { "type": "array", "items": { "type": "object", "properties": { - "baseModelId": { - "type": [ - "string", - "null" - ], - "description": "Base model ID for branch/extension models" - }, - "branches": { - "type": "array", - "items": { - "type": "object", - "properties": { - "id": { - "type": "string", - "description": "Branch ID" - }, - "name": { - "type": "string", - "description": "Branch name" - } - }, - "required": [ - "id", - "name" - ] - }, - "description": "Active branches (if include=activeBranches)" - }, - "connectionId": { - "type": [ - "string", - "null" - ], - "description": "Connection ID" - }, - "createdAt": { + "base_view_name": { "type": "string", - "description": "Creation timestamp" - }, - "deletedAt": { - "type": [ - "string", - "null" - ], - "description": "Deletion timestamp" + "description": "Base view name for the topic" }, - "id": { + "description": { "type": "string", - "description": "Model ID" - }, - "modelKind": { - "type": [ - "string", - "null" - ], - "description": "Model kind" - }, - "name": { - "type": [ - "string", - "null" - ], - "description": "Model name" + "description": "Topic description" }, - "updatedAt": { + "group_label": { "type": "string", - "description": "Last update timestamp" - } - }, - "required": [ - "baseModelId", - "connectionId", - "createdAt", - "deletedAt", - "id", - "modelKind", - "name", - "updatedAt" - ] - }, - "description": "List of model records" - } - }, - "required": [ - "pageInfo", - "records" - ] - }, - "CreateModelSchemaBase": { - "type": "object", - "properties": { - "accessGrants": { - "type": "array", - "items": { - "type": "object", - "properties": { - "accessBoostable": { - "type": "boolean" - }, - "allowedValues": { - "type": "array", - "items": { - "type": "string" - } + "description": "Group label" }, - "codeComments": { - "type": "object", - "additionalProperties": { - "type": "string" - } + "hidden": { + "type": "boolean", + "description": "Whether the topic is hidden" }, - "ignored": { - "type": "boolean" + "label": { + "type": "string", + "description": "Topic label" }, "name": { - "type": "string" - }, - "userAttribute": { - "type": "string" + "type": "string", + "description": "Topic name" } }, "required": [ - "accessBoostable", + "base_view_name", "name" ] }, - "description": "Access grants for the model" - }, - "allowAsWorkbookBase": { - "type": "boolean", - "description": "Allow this model as a workbook base" - }, - "baseModelId": { - "type": "string", - "description": "Base model ID for extension or branch models" - }, - "connectionId": { - "type": "string", - "description": "Connection ID for the model" - }, - "modelKind": { - "anyOf": [ - { - "type": "string", - "enum": [ - "SCHEMA" - ] - }, - { - "type": "string", - "enum": [ - "SHARED" - ] - }, - { - "type": "string", - "enum": [ - "SHARED_EXTENSION" - ] - }, - { - "type": "string", - "enum": [ - "BRANCH" - ] - } - ], - "default": "SCHEMA", - "description": "Kind of model to create" - }, - "modelName": { - "type": "string", - "description": "Name for the model" - }, - "usesIsolatedBranches": { - "type": "boolean", - "description": "For SHARED_EXTENSION models, controls if branches are shown on extension model page instead of parent shared model" + "description": "List of topics" } }, "required": [ - "connectionId" + "success", + "topics" ] }, - "ModelsUpdateResponse": { + "ModelsGetTopicResponse": { "type": "object", "properties": { - "model": { + "success": { + "type": "boolean", + "description": "Whether the operation succeeded" + }, + "topic": { "type": "object", "properties": { - "id": { + "base_view_name": { "type": "string", - "format": "uuid", - "description": "Model ID" + "description": "Base view name for the topic" + }, + "description": { + "type": "string", + "description": "Topic description" + }, + "group_label": { + "type": "string", + "description": "Group label" + }, + "hidden": { + "type": "boolean", + "description": "Whether the topic is hidden" + }, + "label": { + "type": "string", + "description": "Topic label" }, "name": { "type": "string", - "description": "Updated model name" + "description": "Topic name" + }, + "relationships": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": {} + }, + "description": "Relationships for the topic" + }, + "views": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": {} + }, + "description": "Views available in the topic" } }, "required": [ - "id", - "name" + "base_view_name", + "name", + "relationships", + "views" ], - "description": "Updated model details" - }, - "success": { - "type": "boolean", - "description": "Whether the operation succeeded" + "description": "Topic details with relationships and views" } }, "required": [ - "model", - "success" + "success", + "topic" ] }, - "ModelsUpdateBody": { + "ModelsUpdateTopicBody": { "type": "object", "properties": { - "name": { + "description": { "type": "string", - "minLength": 1, - "description": "New name for the model", - "example": "My Renamed Model" + "description": "Topic description" + }, + "groupLabel": { + "type": "string", + "description": "Group label for the topic" + }, + "hidden": { + "type": "boolean", + "description": "Whether the topic is hidden" + }, + "label": { + "type": "string", + "description": "Topic label" + }, + "newTopicName": { + "type": "string", + "description": "New topic name (for rename)" } - }, - "required": [ - "name" - ] + } }, - "JobsGetStatusResponse": { + "ModelsCreateFieldBody": { "type": "object", "properties": { - "job_id": { + "aggregateType": { "type": "string", - "description": "The job ID", - "example": "550e8400-e29b-41d4-a716-446655440000" + "enum": [ + "AVERAGE", + "COUNT", + "COUNT_DISTINCT", + "LIST", + "MAX", + "MIN", + "SUM", + "MEDIAN", + "PERCENTILE", + "AVERAGE_DISTINCT_ON", + "SUM_DISTINCT_ON", + "MEDIAN_DISTINCT_ON", + "PERCENTILE_DISTINCT_ON", + "SEMANTIC_VIEW_AGG" + ], + "description": "Aggregate type for measures. Setting this property promotes the field to a measure (written under `measures:`); omit it to create a dimension (written under `dimensions:`). Values must be uppercase canonical names.", + "example": "SUM" }, - "job_type": { + "aiContext": { "type": "string", - "description": "The type of job (e.g., REFRESH_SCHEMA)", - "example": "REFRESH_SCHEMA" + "description": "AI context for the field" }, - "status": { + "description": { "type": "string", - "enum": [ - "IN_PROGRESS", - "COMPLETED", - "FAILED" - ], - "description": "Current status of the job", - "example": "COMPLETED" + "description": "Field description" + }, + "fieldName": { + "type": "string", + "description": "Field name", + "example": "total_revenue" + }, + "format": { + "type": "string", + "description": "Field format" + }, + "hidden": { + "type": "boolean", + "description": "Whether the field is hidden" + }, + "label": { + "type": "string", + "description": "Field label" + }, + "sql": { + "type": "string", + "description": "SQL expression for the field" + }, + "tags": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Tags for the field" + }, + "topicContext": { + "type": "string", + "description": "Topic context for topic-scoped fields" + }, + "viewName": { + "type": "string", + "description": "View to add the field to", + "example": "orders" } }, "required": [ - "job_id", - "job_type", - "status" - ] + "fieldName", + "viewName" + ], + "additionalProperties": false }, - "ModelsGetSchemasResponse": { + "ModelsRefreshResponse": { "type": "object", "properties": { - "schemas": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Sorted list of all available schema names (catalog-scoped if applicable, e.g. warehouse.reporting)" + "jobId": { + "type": "string", + "description": "Job ID for the refresh operation" + }, + "modelId": { + "type": "string", + "description": "Model ID being refreshed" + }, + "status": { + "type": "string", + "enum": [ + "running", + "completed", + "failed" + ], + "description": "Current status of the refresh" } }, "required": [ - "schemas" + "jobId", + "modelId", + "status" ] }, - "ModelsGetViewResponse": { + "ModelsValidateResponse": { "type": "object", "properties": { - "success": { - "type": "boolean", - "description": "Whether the operation succeeded" - }, - "views": { + "issues": { "type": "array", "items": { "type": "object", "properties": { - "description": { + "field": { "type": "string", - "description": "View description" - }, - "fields": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "description": "Field name" - }, - "type": { - "type": "string", - "enum": [ - "dimension", - "measure", - "filter" - ], - "description": "Field type" - } - }, - "required": [ - "name", - "type" - ] - }, - "description": "Fields in the view" + "description": "Field name with the issue" }, - "hidden": { - "type": "boolean", - "description": "Whether the view is hidden" + "message": { + "type": "string", + "description": "Validation issue message" }, - "label": { + "severity": { "type": "string", - "description": "View label" + "enum": [ + "error", + "warning" + ], + "description": "Issue severity" }, - "name": { + "view": { "type": "string", - "description": "View name" + "description": "View name with the issue" } }, "required": [ - "fields", - "name" + "message", + "severity" ] }, - "description": "List of views" + "description": "List of validation issues" + }, + "valid": { + "type": "boolean", + "description": "Whether the model is valid" } }, "required": [ - "success", - "views" + "issues", + "valid" ] }, - "ModelsUpdateViewBody": { + "ModelsMigrateBody": { "type": "object", "properties": { - "aiContext": { - "type": "string", - "description": "AI context for the view" - }, - "description": { + "branchName": { "type": "string", - "description": "View description" + "description": "Branch name for the target model" }, - "format": { + "commitMessage": { "type": "string", - "description": "View format" + "description": "Commit message for git sync" }, - "hidden": { + "deleteViewsAndTopicsMissingFromSource": { "type": "boolean", - "description": "Whether the view is hidden" + "default": true, + "description": "When true (default), views and topics in the target model that are missing from the migrated source are deleted (the source is treated as the complete model). When false, they are kept (inherited) instead — useful when the source git ref may be missing objects that exist in omni but not in git, e.g. a newly synced schema." }, - "label": { + "gitRef": { "type": "string", - "description": "View label" + "description": "Git reference" }, - "tags": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Tags for the view" + "targetModelId": { + "type": "string", + "format": "uuid", + "description": "Target model ID to migrate to" } - } + }, + "required": [ + "targetModelId" + ] }, - "ModelsUpdateFieldBody": { + "ModelsDbtExposuresResponse": { "type": "object", "properties": { - "aiContext": { - "type": "string", - "description": "AI context for the field" - }, - "allValues": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Deprecated: use sampleValues instead" - }, - "binBoundaries": { - "type": "array", - "items": { - "type": "number" - }, - "description": "Bin boundaries for binned fields" + "pageInfo": { + "$ref": "#/components/schemas/PageInfo" }, - "binLabels": { + "records": { "type": "array", "items": { - "type": "string" - }, - "description": "Labels for bins" + "$ref": "#/components/schemas/DbtExposureWithMeta" + } + } + }, + "required": [ + "pageInfo", + "records" + ] + }, + "DbtExposureWithMeta": { + "type": "object", + "properties": { + "dashboard_identifier": { + "type": "string", + "description": "Identifier of the dashboard that generated this exposure" }, - "description": { + "deduplication_name": { "type": "string", - "description": "Field description" + "description": "A unique name for this exposure. Use this instead of exposure.name to avoid duplicate names, or use it as a fallback when exposure.name collides with another exposure." }, - "drillFields": { + "exposure": { + "$ref": "#/components/schemas/DbtExposure" + } + }, + "required": [ + "dashboard_identifier", + "deduplication_name", + "exposure" + ] + }, + "DbtExposure": { + "type": "object", + "properties": { + "depends_on": { "type": "array", "items": { "type": "string" }, - "description": "Drill-down fields" + "description": "List of dbt model references (e.g. ref('model_name'))", + "example": [ + "ref('orders')", + "ref('customers')" + ] }, - "elseValue": { + "label": { "type": "string", - "description": "Else value for grouped fields" - }, - "filters": { - "type": "object", - "additionalProperties": {}, - "description": "Filters for the field" + "description": "Original dashboard name" }, - "format": { + "name": { "type": "string", - "description": "Field format" + "description": "Sanitized exposure name. May contain duplicates across exposures; use deduplication_name for a guaranteed-unique alternative.", + "example": "my_dashboard" }, - "groupFilters": { - "type": "array", - "items": { - "type": "object", - "additionalProperties": {} - }, - "description": "Group filters" + "owner": { + "$ref": "#/components/schemas/DbtExposureOwner" }, - "groupLabel": { + "type": { "type": "string", - "description": "Group label" - }, - "groupNames": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Group names" - }, - "hidden": { - "type": "boolean", - "description": "Whether the field is hidden" - }, - "ignored": { - "type": "boolean", - "description": "Whether the field is ignored" - }, - "isCalc": { - "type": "boolean", - "description": "Whether this is a calculation field" + "enum": [ + "dashboard", + "notebook", + "analysis", + "ml", + "application" + ], + "description": "Type of the exposure", + "example": "dashboard" }, - "label": { + "url": { "type": "string", - "description": "Field label" + "description": "URL of the dashboard" + } + }, + "required": [ + "depends_on", + "name", + "owner", + "type" + ], + "description": "The dbt exposure for this dashboard." + }, + "DbtExposureOwner": { + "type": "object", + "properties": { + "email": { + "type": "string", + "description": "Email of the dashboard owner" }, - "newFieldName": { + "name": { "type": "string", - "description": "New field name (for rename)" + "description": "Name of the dashboard owner" + } + }, + "required": [ + "email", + "name" + ] + }, + "ModelsBranchDbtBody": { + "type": "object", + "properties": { + "dbt_environment_id": { + "type": "string", + "format": "uuid", + "description": "ID of the dbt environment to activate on this branch", + "example": "123e4567-e89b-12d3-a456-426614174000" }, - "newViewName": { + "dbt_git_branch": { "type": "string", - "description": "New view name (for move)" + "description": "Git branch to associate with the dbt environment", + "example": "feature/new-metrics" + } + }, + "required": [ + "dbt_environment_id" + ] + }, + "ModelsMergeBranchResponse": { + "type": "object", + "properties": { + "failed_drafts_count": { + "type": "number", + "description": "Number of drafts that failed to publish" }, - "sampleValues": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Sample values for the field" + "git_synced": { + "type": "boolean", + "description": "Whether git was synced" }, - "sql": { - "type": "string", - "description": "SQL expression for the field" + "published_drafts_count": { + "type": "number", + "description": "Number of drafts published" }, - "synonyms": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Synonyms for the field" + "success": { + "type": "boolean", + "description": "Whether the merge succeeded" + } + }, + "required": [ + "failed_drafts_count", + "git_synced", + "published_drafts_count", + "success" + ] + }, + "ModelsMergeBranchBody": { + "type": "object", + "properties": { + "commit_message": { + "type": "string", + "description": "Custom commit message for git sync" }, - "tags": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Tags for the field" + "delete_branch": { + "type": "boolean", + "default": false, + "description": "Delete the branch after merging" }, - "topicContext": { - "type": "string", - "description": "Topic context for the field" + "force_override_git_settings": { + "type": "boolean", + "default": false, + "description": "Override PR-required or git-follower settings" + }, + "publish_drafts": { + "type": "boolean", + "default": true, + "description": "Publish branch-attached drafts" } } }, - "ModelsListTopicsResponse": { + "ModelsCommitResponse": { "type": "object", "properties": { - "success": { + "did_sync": { "type": "boolean", - "description": "Whether the operation succeeded" + "description": "Whether a sync operation was performed against git" }, - "topics": { - "type": "array", - "items": { - "type": "object", - "properties": { - "base_view_name": { - "type": "string", - "description": "Base view name for the topic" - }, - "description": { - "type": "string", - "description": "Topic description" - }, - "group_label": { - "type": "string", - "description": "Group label" - }, - "hidden": { - "type": "boolean", - "description": "Whether the topic is hidden" - }, - "label": { - "type": "string", - "description": "Topic label" - }, - "name": { - "type": "string", - "description": "Topic name" - } - }, - "required": [ - "base_view_name", - "name" - ] - }, - "description": "List of topics" + "git_sha": { + "type": [ + "string", + "null" + ], + "description": "The git SHA of the commit that was pushed (null if no commit was needed)" + }, + "in_sync": { + "type": "boolean", + "description": "Whether the branch is in sync with git after the operation" + }, + "pr_url": { + "type": [ + "string", + "null" + ], + "description": "The URL of the pull request (or PR creation page for newly-created PRs). May be null when the underlying git provider is not recognized." } }, "required": [ - "success", - "topics" + "did_sync", + "git_sha", + "in_sync", + "pr_url" ] }, - "ModelsGetTopicResponse": { + "ModelsCommitBody": { "type": "object", "properties": { - "success": { + "allow_branch_exists": { "type": "boolean", - "description": "Whether the operation succeeded" + "default": true, + "description": "If true (default), the commit succeeds whether the git branch already exists or not. If false, the request fails when the git branch already exists — use this to ensure only new pull requests are created. Cannot be false when require_branch_exists is true.", + "example": true }, - "topic": { + "branch_id": { + "type": "string", + "format": "uuid", + "description": "UUID of the branch to commit.", + "example": "123e4567-e89b-12d3-a456-426614174001" + }, + "commit_message": { + "type": "string", + "minLength": 1, + "description": "Commit message for the git commit.", + "example": "Add new orders view" + }, + "require_branch_exists": { + "type": "boolean", + "default": false, + "description": "If true, the request fails when the git branch does not already exist — use this to ensure only existing pull requests are updated. Defaults to false. Cannot be true when allow_branch_exists is false.", + "example": false + } + }, + "required": [ + "branch_id", + "commit_message" + ] + }, + "ModelsCacheResetResponse": { + "type": "object", + "properties": { + "cache_reset": { "type": "object", "properties": { - "base_view_name": { - "type": "string", - "description": "Base view name for the topic" - }, - "description": { - "type": "string", - "description": "Topic description" - }, - "group_label": { - "type": "string", - "description": "Group label" - }, - "hidden": { - "type": "boolean", - "description": "Whether the topic is hidden" + "created_at": { + "type": [ + "string", + "null" + ], + "description": "Creation timestamp" }, - "label": { + "model_id": { "type": "string", - "description": "Topic label" + "description": "Model ID" }, - "name": { + "policy_name": { "type": "string", - "description": "Topic name" + "description": "Cache policy name" }, - "relationships": { - "type": "array", - "items": { - "type": "object", - "additionalProperties": {} - }, - "description": "Relationships for the topic" + "reset_at": { + "type": [ + "string", + "null" + ], + "description": "Reset timestamp" }, - "views": { - "type": "array", - "items": { - "type": "object", - "additionalProperties": {} - }, - "description": "Views available in the topic" + "updated_at": { + "type": [ + "string", + "null" + ], + "description": "Last update timestamp" } }, "required": [ - "base_view_name", - "name", - "relationships", - "views" + "created_at", + "model_id", + "policy_name", + "reset_at", + "updated_at" + ], + "description": "Cache reset details" + }, + "success": { + "type": "boolean", + "description": "Whether the operation succeeded" + } + }, + "required": [ + "cache_reset", + "success" + ] + }, + "ModelsCacheResetBody": { + "type": "object", + "properties": { + "resetAt": { + "type": "string", + "description": "ISO-8601 timestamp for when to reset the cache", + "example": "2024-01-15T12:00:00Z" + } + } + }, + "ModelsGitGetResponse": { + "type": "object", + "properties": { + "authMethod": { + "type": "string", + "enum": [ + "ssh", + "https_token" + ], + "description": "Authentication method. \"ssh\" for deploy key, \"https_token\" for deploy token/PAT.", + "example": "ssh" + }, + "baseBranch": { + "type": "string", + "description": "The target branch for Omni pull requests", + "example": "main" + }, + "branchPerPullRequest": { + "type": "boolean", + "description": "If true, all pull requests will create a branch in Omni, even those created outside of the tool", + "example": false + }, + "cloneUrl": { + "type": "string", + "description": "Clone URL of the git repository (SSH or HTTPS)", + "example": "git@github.com:org/repo.git" + }, + "gitFollower": { + "type": "boolean", + "description": "If true, the shared model is read-only and can only be updated by merging pull requests to the base branch", + "example": false + }, + "gitServiceProvider": { + "type": "string", + "description": "The git provider type", + "example": "github" + }, + "modelPath": { + "type": [ + "string", + "null" + ], + "description": "Path to model files in the repository", + "example": "omni/my_model" + }, + "publicKey": { + "type": [ + "string", + "null" ], - "description": "Topic details with relationships and views" + "description": "SSH public key for repository access (deploy key). Null for HTTPS token auth.", + "example": "ssh-ed25519 AAAA..." + }, + "requirePullRequest": { + "type": "string", + "enum": [ + "always", + "users-only", + "never" + ], + "description": "When pull requests are required: \"always\" for all changes, \"users-only\" for user-initiated changes only, \"never\" for direct commits.", + "example": "users-only" + }, + "sshUrl": { + "type": "string", + "deprecated": true, + "description": "Deprecated — use cloneUrl. Clone URL of the git repository." + }, + "webUrl": { + "type": [ + "string", + "null" + ], + "description": "Custom web URL for the git repository, or null if not set", + "example": "https://github.com/org/repo" + }, + "webhookSecret": { + "type": "string", + "description": "Webhook secret for signature verification. Only included if requested via ?include=webhookSecret" + }, + "webhookUrl": { + "type": "string", + "description": "Webhook URL to configure in your git provider", + "example": "https://app.omni.co/api/webhooks/model/..." } }, "required": [ - "success", - "topic" + "authMethod", + "baseBranch", + "branchPerPullRequest", + "cloneUrl", + "gitFollower", + "gitServiceProvider", + "modelPath", + "publicKey", + "requirePullRequest", + "sshUrl", + "webUrl", + "webhookUrl" ] }, - "ModelsUpdateTopicBody": { + "ModelsGitCreateResponse": { "type": "object", "properties": { - "description": { + "authMethod": { "type": "string", - "description": "Topic description" + "enum": [ + "ssh", + "https_token" + ], + "description": "Authentication method. \"ssh\" for deploy key, \"https_token\" for deploy token/PAT.", + "example": "ssh" }, - "groupLabel": { + "baseBranch": { "type": "string", - "description": "Group label for the topic" + "description": "The target branch for Omni pull requests", + "example": "main" }, - "hidden": { + "branchPerPullRequest": { "type": "boolean", - "description": "Whether the topic is hidden" + "description": "If true, all pull requests will create a branch in Omni, even those created outside of the tool", + "example": false }, - "label": { + "cloneUrl": { "type": "string", - "description": "Topic label" + "description": "Clone URL of the git repository (SSH or HTTPS)", + "example": "git@github.com:org/repo.git" }, - "newTopicName": { + "gitFollower": { + "type": "boolean", + "description": "If true, the shared model is read-only and can only be updated by merging pull requests to the base branch", + "example": false + }, + "gitServiceProvider": { "type": "string", - "description": "New topic name (for rename)" + "description": "The git provider type", + "example": "github" + }, + "modelPath": { + "type": [ + "string", + "null" + ], + "description": "Path to model files in the repository", + "example": "omni/my_model" + }, + "publicKey": { + "type": [ + "string", + "null" + ], + "description": "SSH public key for repository access (deploy key). Null for HTTPS token auth.", + "example": "ssh-ed25519 AAAA..." + }, + "requirePullRequest": { + "type": "string", + "enum": [ + "always", + "users-only", + "never" + ], + "description": "When pull requests are required: \"always\" for all changes, \"users-only\" for user-initiated changes only, \"never\" for direct commits.", + "example": "users-only" + }, + "sshUrl": { + "type": "string", + "deprecated": true, + "description": "Deprecated — use cloneUrl. Clone URL of the git repository." + }, + "webUrl": { + "type": [ + "string", + "null" + ], + "description": "Custom web URL for the git repository, or null if not set", + "example": "https://github.com/org/repo" + }, + "webhookSecret": { + "type": "string", + "description": "Webhook secret for signature verification. Only included if requested via ?include=webhookSecret" + }, + "webhookUrl": { + "type": "string", + "description": "Webhook URL to configure in your git provider", + "example": "https://app.omni.co/api/webhooks/model/..." } - } + }, + "required": [ + "authMethod", + "baseBranch", + "branchPerPullRequest", + "cloneUrl", + "gitFollower", + "gitServiceProvider", + "modelPath", + "publicKey", + "requirePullRequest", + "sshUrl", + "webUrl", + "webhookUrl" + ] }, - "ModelsCreateFieldBody": { + "ModelsGitCreateBody": { "type": "object", "properties": { - "aggregateType": { - "type": "string", - "description": "Aggregate type for measures" - }, - "aiContext": { + "authMethod": { "type": "string", - "description": "AI context for the field" + "enum": [ + "ssh", + "https_token" + ], + "default": "ssh", + "description": "Authentication method. \"ssh\" for deploy key (default), \"https_token\" for deploy token/PAT.", + "example": "ssh" }, - "description": { + "baseBranch": { "type": "string", - "description": "Field description" + "default": "main", + "description": "The target branch for Omni pull requests. Defaults to \"main\"", + "example": "main" }, - "fieldName": { - "type": "string", - "description": "Field name", - "example": "total_revenue" + "branchPerPullRequest": { + "type": "boolean", + "default": false, + "description": "If true, all pull requests will create a branch in Omni. Defaults to false", + "example": false }, - "format": { + "cloneUrl": { "type": "string", - "description": "Field format" + "minLength": 1, + "description": "Clone URL of the git repository. SSH (git@...) for deploy key auth, HTTPS (https://...) for token auth.", + "example": "git@github.com:org/repo.git" }, - "hidden": { + "gitFollower": { "type": "boolean", - "description": "Whether the field is hidden" + "default": false, + "description": "If true, the shared model will be read-only. Defaults to false", + "example": false }, - "label": { + "gitServiceProvider": { "type": "string", - "description": "Field label" + "enum": [ + "github", + "gitlab", + "azure_devops", + "bitbucket", + "bitbucket_datacenter", + "auto" + ], + "default": "auto", + "description": "The git provider type. Use \"auto\" for automatic detection. Defaults to \"auto\"", + "example": "auto" }, - "sql": { + "modelPath": { "type": "string", - "description": "SQL expression for the field" + "description": "Path to model files in the repository. Defaults to omni/. Use a plain name (e.g., \"my_model\") for omni/my_model, or a leading slash for a custom path (e.g., \"/bi/models/sales\")", + "example": "my_model" }, - "tags": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Tags for the field" + "requirePullRequest": { + "type": "string", + "enum": [ + "always", + "users-only", + "never" + ], + "default": "never", + "description": "Controls when pull requests are required. Defaults to \"never\"", + "example": "never" }, - "topicContext": { + "sshUrl": { "type": "string", - "description": "Topic context for topic-scoped fields" + "minLength": 1, + "description": "Deprecated — use cloneUrl. Clone URL of the git repository.", + "example": "git@github.com:org/repo.git", + "deprecated": true }, - "viewName": { + "token": { "type": "string", - "description": "View to add the field to", - "example": "orders" - } - }, - "required": [ - "fieldName", - "viewName" - ] + "maxLength": 1000, + "pattern": "^[a-zA-Z0-9_\\-.]+$", + "description": "HTTPS token for authentication (deploy token value, PAT, etc.). Required when authMethod is \"https_token\"." + }, + "webUrl": { + "type": "string", + "description": "Custom web URL for the git repository. Use when the clone URL goes through a tunnel/VPC and differs from the inferred HTTPS address", + "example": "https://github.com/org/repo" + } + } }, - "ModelsRefreshResponse": { + "ModelsGitUpdateResponse": { "type": "object", "properties": { - "jobId": { + "authMethod": { "type": "string", - "description": "Job ID for the refresh operation" + "enum": [ + "ssh", + "https_token" + ], + "description": "Authentication method. \"ssh\" for deploy key, \"https_token\" for deploy token/PAT.", + "example": "ssh" }, - "modelId": { + "baseBranch": { "type": "string", - "description": "Model ID being refreshed" + "description": "The target branch for Omni pull requests", + "example": "main" }, - "status": { + "branchPerPullRequest": { + "type": "boolean", + "description": "If true, all pull requests will create a branch in Omni, even those created outside of the tool", + "example": false + }, + "cloneUrl": { "type": "string", - "enum": [ - "running", - "completed", - "failed" - ], - "description": "Current status of the refresh" - } - }, - "required": [ - "jobId", - "modelId", - "status" - ] - }, - "ModelsValidateResponse": { - "type": "object", - "properties": { - "issues": { - "type": "array", - "items": { - "type": "object", - "properties": { - "field": { - "type": "string", - "description": "Field name with the issue" - }, - "message": { - "type": "string", - "description": "Validation issue message" - }, - "severity": { - "type": "string", - "enum": [ - "error", - "warning" - ], - "description": "Issue severity" - }, - "view": { - "type": "string", - "description": "View name with the issue" - } - }, - "required": [ - "message", - "severity" - ] - }, - "description": "List of validation issues" + "description": "Clone URL of the git repository (SSH or HTTPS)", + "example": "git@github.com:org/repo.git" }, - "valid": { + "gitFollower": { "type": "boolean", - "description": "Whether the model is valid" - } - }, - "required": [ - "issues", - "valid" - ] - }, - "ModelsMigrateBody": { - "type": "object", - "properties": { - "branchName": { + "description": "If true, the shared model is read-only and can only be updated by merging pull requests to the base branch", + "example": false + }, + "gitServiceProvider": { "type": "string", - "description": "Branch name for the target model" + "description": "The git provider type", + "example": "github" }, - "commitMessage": { + "modelPath": { + "type": [ + "string", + "null" + ], + "description": "Path to model files in the repository", + "example": "omni/my_model" + }, + "publicKey": { + "type": [ + "string", + "null" + ], + "description": "SSH public key for repository access (deploy key). Null for HTTPS token auth.", + "example": "ssh-ed25519 AAAA..." + }, + "requirePullRequest": { "type": "string", - "description": "Commit message for git sync" + "enum": [ + "always", + "users-only", + "never" + ], + "description": "When pull requests are required: \"always\" for all changes, \"users-only\" for user-initiated changes only, \"never\" for direct commits.", + "example": "users-only" }, - "gitRef": { + "sshUrl": { "type": "string", - "description": "Git reference" + "deprecated": true, + "description": "Deprecated — use cloneUrl. Clone URL of the git repository." }, - "targetModelId": { + "webUrl": { + "type": [ + "string", + "null" + ], + "description": "Custom web URL for the git repository, or null if not set", + "example": "https://github.com/org/repo" + }, + "webhookSecret": { "type": "string", - "format": "uuid", - "description": "Target model ID to migrate to" - } - }, - "required": [ - "targetModelId" - ] - }, - "ModelsDbtExposuresResponse": { - "type": "object", - "properties": { - "pageInfo": { - "$ref": "#/components/schemas/PageInfo" + "description": "Webhook secret for signature verification. Only included if requested via ?include=webhookSecret" }, - "records": { - "type": "array", - "items": { - "$ref": "#/components/schemas/DbtExposureWithMeta" - } + "webhookUrl": { + "type": "string", + "description": "Webhook URL to configure in your git provider", + "example": "https://app.omni.co/api/webhooks/model/..." } }, "required": [ - "pageInfo", - "records" + "authMethod", + "baseBranch", + "branchPerPullRequest", + "cloneUrl", + "gitFollower", + "gitServiceProvider", + "modelPath", + "publicKey", + "requirePullRequest", + "sshUrl", + "webUrl", + "webhookUrl" ] }, - "DbtExposureWithMeta": { + "ModelsGitUpdateBody": { "type": "object", "properties": { - "dashboard_identifier": { + "authMethod": { "type": "string", - "description": "Identifier of the dashboard that generated this exposure" + "enum": [ + "ssh", + "https_token" + ], + "description": "Authentication method to change to.", + "example": "ssh" }, - "deduplication_name": { + "baseBranch": { "type": "string", - "description": "A unique name for this exposure. Use this instead of exposure.name to avoid duplicate names, or use it as a fallback when exposure.name collides with another exposure." + "description": "The target branch for Omni pull requests", + "example": "main" }, - "exposure": { - "$ref": "#/components/schemas/DbtExposure" - } - }, - "required": [ - "dashboard_identifier", - "deduplication_name", - "exposure" - ] - }, - "DbtExposure": { - "type": "object", - "properties": { - "depends_on": { - "type": "array", - "items": { - "type": "string" - }, - "description": "List of dbt model references (e.g. ref('model_name'))", - "example": [ - "ref('orders')", - "ref('customers')" - ] + "branchPerPullRequest": { + "type": "boolean", + "description": "If true, all pull requests will create a branch in Omni", + "example": false }, - "label": { + "cloneUrl": { "type": "string", - "description": "Original dashboard name" + "minLength": 1, + "description": "Clone URL of the git repository (SSH or HTTPS).", + "example": "git@github.com:org/repo.git" }, - "name": { + "gitFollower": { + "type": "boolean", + "description": "If true, the shared model will be read-only", + "example": false + }, + "gitServiceProvider": { "type": "string", - "description": "Sanitized exposure name. May contain duplicates across exposures; use deduplication_name for a guaranteed-unique alternative.", - "example": "my_dashboard" + "enum": [ + "github", + "gitlab", + "azure_devops", + "bitbucket", + "bitbucket_datacenter", + "auto" + ], + "description": "The git provider type", + "example": "github" }, - "owner": { - "$ref": "#/components/schemas/DbtExposureOwner" + "modelPath": { + "type": "string", + "description": "Path to model files in the repository", + "example": "my_model" }, - "type": { + "requirePullRequest": { "type": "string", "enum": [ - "dashboard", - "notebook", - "analysis", - "ml", - "application" + "always", + "users-only", + "never" ], - "description": "Type of the exposure", - "example": "dashboard" + "description": "Controls when pull requests are required", + "example": "users-only" }, - "url": { - "type": "string", - "description": "URL of the dashboard" - } - }, - "required": [ - "depends_on", - "name", - "owner", - "type" - ], - "description": "The dbt exposure for this dashboard." - }, - "DbtExposureOwner": { - "type": "object", - "properties": { - "email": { + "sshUrl": { "type": "string", - "description": "Email of the dashboard owner" + "minLength": 1, + "description": "Deprecated — use cloneUrl. Clone URL of the git repository.", + "example": "git@github.com:org/repo.git", + "deprecated": true }, - "name": { - "type": "string", - "description": "Name of the dashboard owner" - } - }, - "required": [ - "email", - "name" - ] - }, - "ModelsBranchDbtBody": { - "type": "object", - "properties": { - "dbt_environment_id": { + "token": { "type": "string", - "format": "uuid", - "description": "ID of the dbt environment to activate on this branch", - "example": "123e4567-e89b-12d3-a456-426614174000" + "maxLength": 1000, + "pattern": "^[a-zA-Z0-9_\\-.]+$", + "description": "HTTPS token for authentication (deploy token value, PAT, etc.)." }, - "dbt_git_branch": { + "webUrl": { "type": "string", - "description": "Git branch to associate with the dbt environment", - "example": "feature/new-metrics" + "description": "Custom web URL for the git repository. Use when the clone URL goes through a tunnel/VPC and differs from the inferred HTTPS address", + "example": "https://github.com/org/repo" } - }, - "required": [ - "dbt_environment_id" - ] + } }, - "ModelsMergeBranchResponse": { + "ModelsGitDeleteResponse": { "type": "object", "properties": { - "failed_drafts_count": { - "type": "number", - "description": "Number of drafts that failed to publish" - }, - "git_synced": { - "type": "boolean", - "description": "Whether git was synced" - }, - "published_drafts_count": { - "type": "number", - "description": "Number of drafts published" + "message": { + "type": "string", + "description": "Success message", + "example": "Git repository unlinked successfully" }, "success": { "type": "boolean", - "description": "Whether the merge succeeded" + "description": "Whether the operation succeeded", + "example": true } }, "required": [ - "failed_drafts_count", - "git_synced", - "published_drafts_count", + "message", "success" ] }, - "ModelsMergeBranchBody": { - "type": "object", - "properties": { - "commit_message": { - "type": "string", - "description": "Custom commit message for git sync" - }, - "delete_branch": { - "type": "boolean", - "default": false, - "description": "Delete the branch after merging" - }, - "force_override_git_settings": { - "type": "boolean", - "default": false, - "description": "Override PR-required or git-follower settings" - }, - "publish_drafts": { - "type": "boolean", - "default": true, - "description": "Publish branch-attached drafts" - } - } - }, - "ModelsCommitResponse": { + "ModelsGitSyncResponse": { "type": "object", "properties": { - "did_sync": { + "didSync": { "type": "boolean", - "description": "Whether a sync operation was performed against git" + "description": "Whether a sync operation was performed" }, - "git_sha": { + "gitSha": { "type": [ "string", "null" ], - "description": "The git SHA of the commit that was pushed (null if no commit was needed)" + "description": "The git SHA after the sync operation" }, - "in_sync": { + "inSync": { "type": "boolean", - "description": "Whether the branch is in sync with git after the operation" + "description": "Whether the model is currently in sync with git" }, - "pr_url": { - "type": [ - "string", - "null" - ], - "description": "The URL of the pull request (or PR creation page for newly-created PRs). May be null when the underlying git provider is not recognized." + "message": { + "type": "string", + "description": "Human-readable message about the sync status" } }, "required": [ - "did_sync", - "git_sha", - "in_sync", - "pr_url" + "didSync", + "gitSha", + "inSync", + "message" ] }, - "ModelsCommitBody": { + "ModelsGitSyncBody": { "type": "object", "properties": { - "allow_branch_exists": { - "type": "boolean", - "default": true, - "description": "If true (default), the commit succeeds whether the git branch already exists or not. If false, the request fails when the git branch already exists — use this to ensure only new pull requests are created. Cannot be false when require_branch_exists is true.", - "example": true - }, - "branch_id": { - "type": "string", - "format": "uuid", - "description": "UUID of the branch to commit.", - "example": "123e4567-e89b-12d3-a456-426614174001" - }, - "commit_message": { + "commitMessage": { "type": "string", - "minLength": 1, - "description": "Commit message for the git commit.", - "example": "Add new orders view" - }, - "require_branch_exists": { - "type": "boolean", - "default": false, - "description": "If true, the request fails when the git branch does not already exist — use this to ensure only existing pull requests are updated. Defaults to false. Cannot be true when allow_branch_exists is false.", - "example": false + "description": "Optional commit message for the git sync operation", + "example": "Update model schema" } - }, - "required": [ - "branch_id", - "commit_message" - ] + } }, - "ModelsCacheResetResponse": { + "ModelsContentValidatorGetResponse": { "type": "object", "properties": { - "cache_reset": { - "type": "object", + "branch": { + "type": [ + "object", + "null" + ], "properties": { - "created_at": { - "type": [ - "string", - "null" - ], - "description": "Creation timestamp" - }, - "model_id": { + "id": { "type": "string", - "description": "Model ID" + "description": "Branch UUID" }, - "policy_name": { + "name": { "type": "string", - "description": "Cache policy name" - }, - "reset_at": { - "type": [ - "string", - "null" - ], - "description": "Reset timestamp" - }, - "updated_at": { - "type": [ - "string", - "null" - ], - "description": "Last update timestamp" + "description": "Branch name" } }, "required": [ - "created_at", - "model_id", - "policy_name", - "reset_at", - "updated_at" + "id", + "name" ], - "description": "Cache reset details" + "description": "Branch info (present if branch_id was specified)" + }, + "content": { + "type": "array", + "items": {}, + "description": "Documents with their validation results" + }, + "model_id": { + "type": "string", + "description": "Model UUID" + } + }, + "required": [ + "branch", + "content", + "model_id" + ] + }, + "ContentFilterMode": { + "type": "string", + "enum": [ + "ALL", + "WITH_ISSUES", + "NO_ISSUES" + ], + "description": "Filter documents by issue status. ALL (default) returns all documents with at least one query. WITH_ISSUES returns only documents with at least one query issue, dashboard filter issue, or document error. NO_ISSUES returns only documents with zero issues and no document errors." + }, + "ModelsContentValidatorReplaceResponse": { + "type": "object", + "properties": { + "replaced_dashboard_filters_count": { + "type": "integer", + "description": "Number of dashboard filters replaced" + }, + "replaced_documents_count": { + "type": "integer", + "description": "Number of documents modified" }, - "success": { - "type": "boolean", - "description": "Whether the operation succeeded" + "replaced_queries_count": { + "type": "integer", + "description": "Number of queries replaced" + }, + "replaced_workbook_models_count": { + "type": "integer", + "description": "Number of workbook models replaced" + }, + "skipped_pr_required_count": { + "type": "integer", + "description": "Number of documents skipped due to pull request requirements" } }, "required": [ - "cache_reset", - "success" + "replaced_dashboard_filters_count", + "replaced_documents_count", + "replaced_queries_count", + "replaced_workbook_models_count", + "skipped_pr_required_count" ] }, - "ModelsCacheResetBody": { - "type": "object", - "properties": { - "resetAt": { - "type": "string", - "description": "ISO-8601 timestamp for when to reset the cache", - "example": "2024-01-15T12:00:00Z" - } - } - }, - "ModelsGitGetResponse": { + "ModelsContentValidatorReplaceBody": { "type": "object", "properties": { - "authMethod": { + "branch_id": { "type": "string", - "enum": [ - "ssh", - "https_token" - ], - "description": "Authentication method. \"ssh\" for deploy key, \"https_token\" for deploy token/PAT.", - "example": "ssh" + "description": "Optional branch ID" }, - "baseBranch": { + "creator_id": { "type": "string", - "description": "The target branch for Omni pull requests", - "example": "main" - }, - "branchPerPullRequest": { - "type": "boolean", - "description": "If true, all pull requests will create a branch in Omni, even those created outside of the tool", - "example": false + "format": "uuid", + "description": "Restrict replacement to documents created by this user (user ID). Unknown IDs return 400." }, - "cloneUrl": { + "find": { "type": "string", - "description": "Clone URL of the git repository (SSH or HTTPS)", - "example": "git@github.com:org/repo.git" - }, - "gitFollower": { - "type": "boolean", - "description": "If true, the shared model is read-only and can only be updated by merging pull requests to the base branch", - "example": false + "minLength": 1, + "description": "The string to find" }, - "gitServiceProvider": { + "find_or_replace_type": { "type": "string", - "description": "The git provider type", - "example": "github" - }, - "modelPath": { - "type": [ - "string", - "null" + "enum": [ + "FIELD", + "TOPIC", + "VIEW" ], - "description": "Path to model files in the repository", - "example": "omni/my_model" + "description": "Type of find/replace operation." }, - "publicKey": { - "type": [ - "string", - "null" - ], - "description": "SSH public key for repository access (deploy key). Null for HTTPS token auth.", - "example": "ssh-ed25519 AAAA..." + "folder_paths": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Restrict replacement to documents in matching folder paths (prefix match). Documents with no folder are excluded unless \"\" is specified." }, - "requirePullRequest": { - "type": "string", - "enum": [ - "always", - "users-only", - "never" - ], - "description": "When pull requests are required: \"always\" for all changes, \"users-only\" for user-initiated changes only, \"never\" for direct commits.", - "example": "users-only" + "include_personal_folders": { + "type": "boolean", + "default": false, + "description": "Whether to include personal folders" }, - "sshUrl": { + "labels": { "type": "string", - "deprecated": true, - "description": "Deprecated — use cloneUrl. Clone URL of the git repository." - }, - "webUrl": { - "type": [ - "string", - "null" - ], - "description": "Custom web URL for the git repository, or null if not set", - "example": "https://github.com/org/repo" + "description": "Comma-separated label names to scope replacement. Unknown labels return 400." }, - "webhookSecret": { + "only_in_workbook_id": { "type": "string", - "description": "Webhook secret for signature verification. Only included if requested via ?include=webhookSecret" + "description": "Optional workbook ID to limit the replace scope" }, - "webhookUrl": { + "replacement": { "type": "string", - "description": "Webhook URL to configure in your git provider", - "example": "https://app.omni.co/api/webhooks/model/..." + "minLength": 1, + "description": "The replacement string" } }, "required": [ - "authMethod", - "baseBranch", - "branchPerPullRequest", - "cloneUrl", - "gitFollower", - "gitServiceProvider", - "modelPath", - "publicKey", - "requirePullRequest", - "sshUrl", - "webUrl", - "webhookUrl" + "find", + "find_or_replace_type", + "replacement" ] }, - "ModelsGitCreateResponse": { + "ModelYamlResponse": { "type": "object", "properties": { - "authMethod": { - "type": "string", - "enum": [ - "ssh", - "https_token" - ], - "description": "Authentication method. \"ssh\" for deploy key, \"https_token\" for deploy token/PAT.", - "example": "ssh" + "checksums": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Checksums for each file" }, - "baseBranch": { - "type": "string", - "description": "The target branch for Omni pull requests", - "example": "main" + "files": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "YAML content for each file" }, - "branchPerPullRequest": { - "type": "boolean", - "description": "If true, all pull requests will create a branch in Omni, even those created outside of the tool", - "example": false + "version": { + "type": "number", + "description": "Model version number" }, - "cloneUrl": { + "viewNames": { + "type": "object", + "additionalProperties": {}, + "description": "View name mappings" + } + }, + "required": [ + "files", + "version" + ] + }, + "ModelYamlCreateRequestBody": { + "type": "object", + "properties": { + "branchId": { "type": "string", - "description": "Clone URL of the git repository (SSH or HTTPS)", - "example": "git@github.com:org/repo.git" - }, - "gitFollower": { - "type": "boolean", - "description": "If true, the shared model is read-only and can only be updated by merging pull requests to the base branch", - "example": false + "format": "uuid", + "description": "Branch ID for branch-aware operations" }, - "gitServiceProvider": { + "fileName": { "type": "string", - "description": "The git provider type", - "example": "github" - }, - "modelPath": { - "type": [ - "string", - "null" - ], - "description": "Path to model files in the repository", - "example": "omni/my_model" - }, - "publicKey": { - "type": [ - "string", - "null" - ], - "description": "SSH public key for repository access (deploy key). Null for HTTPS token auth.", - "example": "ssh-ed25519 AAAA..." + "minLength": 1, + "description": "File name to create or update" }, - "requirePullRequest": { + "mode": { "type": "string", "enum": [ - "always", - "users-only", - "never" + "combined", + "extension", + "staged", + "merged", + "fully-resolved" ], - "description": "When pull requests are required: \"always\" for all changes, \"users-only\" for user-initiated changes only, \"never\" for direct commits.", - "example": "users-only" + "default": "combined", + "description": "IDE mode for YAML operations" }, - "sshUrl": { + "commitMessage": { "type": "string", - "deprecated": true, - "description": "Deprecated — use cloneUrl. Clone URL of the git repository." + "description": "Commit message for git sync" }, - "webUrl": { - "type": [ - "string", - "null" - ], - "description": "Custom web URL for the git repository, or null if not set", - "example": "https://github.com/org/repo" + "fetchedAtMillis": { + "type": "number", + "description": "Timestamp when the file was fetched" + }, + "fullyResolved": { + "type": "boolean", + "default": false, + "description": "Treat the posted YAML as fully resolved (with the extends chain expanded). Only valid with mode=combined." }, - "webhookSecret": { + "previousChecksum": { "type": "string", - "description": "Webhook secret for signature verification. Only included if requested via ?include=webhookSecret" + "description": "Previous checksum for conflict detection" }, - "webhookUrl": { + "yaml": { "type": "string", - "description": "Webhook URL to configure in your git provider", - "example": "https://app.omni.co/api/webhooks/model/..." + "description": "YAML content for the file" } }, "required": [ - "authMethod", - "baseBranch", - "branchPerPullRequest", - "cloneUrl", - "gitFollower", - "gitServiceProvider", - "modelPath", - "publicKey", - "requirePullRequest", - "sshUrl", - "webUrl", - "webhookUrl" + "fileName", + "yaml" + ], + "additionalProperties": false + }, + "AiAgentActionsResponse": { + "type": "object", + "properties": { + "records": { + "type": "array", + "items": { + "$ref": "#/components/schemas/AiAgentAction" + }, + "description": "AI agent actions in display order: sample queries first, then skills. Topic-level entries follow model-level ones, and skills are deduped by id with topic skills winning over model skills." + } + }, + "required": [ + "records" ] }, - "ModelsGitCreateBody": { + "AiAgentAction": { "type": "object", "properties": { - "authMethod": { + "kind": { "type": "string", "enum": [ - "ssh", - "https_token" + "sample", + "skill" ], - "default": "ssh", - "description": "Authentication method. \"ssh\" for deploy key (default), \"https_token\" for deploy token/PAT.", - "example": "ssh" + "description": "Source of the entry: `sample` for `sample_queries` (model- or topic-level) and `skill` for `skills` (model- or topic-level).", + "example": "skill" }, - "baseBranch": { + "label": { "type": "string", - "default": "main", - "description": "The target branch for Omni pull requests. Defaults to \"main\"", - "example": "main" + "description": "Short, human-readable name for the action — chip text in client UIs and the visible \"prompt\" on the answer card.", + "example": "Revenue trends" }, - "branchPerPullRequest": { - "type": "boolean", - "default": false, - "description": "If true, all pull requests will create a branch in Omni. Defaults to false", - "example": false - }, - "cloneUrl": { + "prompt": { "type": "string", - "minLength": 1, - "description": "Clone URL of the git repository. SSH (git@...) for deploy key auth, HTTPS (https://...) for token auth.", - "example": "git@github.com:org/repo.git" + "description": "Submit this string verbatim as the `prompt` on `POST /api/v1/ai/jobs`. For sample queries this is the raw prompt; for skills it is a pre-formatted wrapper around the skill's input.", + "example": "Skill:\nShow me the recent revenue trends grouped by month…" + } + }, + "required": [ + "kind", + "label", + "prompt" + ] + }, + "QueryRunResponse": { + "type": "object", + "properties": { + "completedQueries": { + "type": "array", + "items": {}, + "description": "Queries that completed synchronously with their results." }, - "gitFollower": { - "type": "boolean", - "default": false, - "description": "If true, the shared model will be read-only. Defaults to false", - "example": false + "jobIds": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Job IDs for queries running asynchronously. Use /api/v1/query/wait to poll for results.", + "example": [ + "job_abc123", + "job_def456" + ] }, - "gitServiceProvider": { + "plan": { + "description": "Query execution plan (only present if planOnly is true)." + } + } + }, + "QueryTimeoutResponse": { + "type": "object", + "properties": { + "detail": { "type": "string", + "description": "Error message indicating the query timed out.", + "example": "Query timed out" + }, + "remaining_job_ids": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Job IDs for queries that have not yet completed. Use /api/v1/query/wait to poll for results." + }, + "timed_out": { + "type": "boolean", "enum": [ - "github", - "gitlab", - "azure_devops", - "bitbucket", - "bitbucket_datacenter", - "auto" + true ], - "default": "auto", - "description": "The git provider type. Use \"auto\" for automatic detection. Defaults to \"auto\"", - "example": "auto" - }, - "modelPath": { + "description": "Always true for timeout responses.", + "example": true + } + }, + "required": [ + "detail", + "timed_out" + ] + }, + "QueryRunBody": { + "type": "object", + "properties": { + "branchId": { "type": "string", - "description": "Path to model files in the repository. Defaults to omni/. Use a plain name (e.g., \"my_model\") for omni/my_model, or a leading slash for a custom path (e.g., \"/bi/models/sales\")", - "example": "my_model" + "format": "uuid", + "description": "Optional model branch to run the query against. Must belong to the same shared model as the query. When omitted, the query runs against the shared model. Takes precedence over the legacy `?branch_id=` URL query parameter.", + "example": "550e8400-e29b-41d4-a716-446655440000" }, - "requirePullRequest": { + "cache": { "type": "string", "enum": [ - "always", - "users-only", - "never" + "disabled", + "normal", + "refresh", + "refresh_all" ], - "default": "never", - "description": "Controls when pull requests are required. Defaults to \"never\"", - "example": "never" + "description": "Cache policy for query execution. Controls whether to use cached results.", + "example": "normal" }, - "sshUrl": { - "type": "string", - "minLength": 1, - "description": "Deprecated — use cloneUrl. Clone URL of the git repository.", - "example": "git@github.com:org/repo.git", - "deprecated": true + "formatResults": { + "type": "boolean", + "description": "Whether to format result values (e.g., apply number formatting). Only valid when resultType is specified." }, - "token": { + "planOnly": { + "type": "boolean", + "default": false, + "description": "If true, returns only the query execution plan without running the query." + }, + "query": { + "description": "The semantic query definition including fields, filters, sorts, and other query parameters." + }, + "resultType": { "type": "string", - "maxLength": 1000, - "pattern": "^[a-zA-Z0-9_\\-.]+$", - "description": "HTTPS token for authentication (deploy token value, PAT, etc.). Required when authMethod is \"https_token\"." + "enum": [ + "csv", + "json", + "xlsx" + ], + "description": "Output format for the results. If not specified, returns base64-encoded Arrow format." }, - "webUrl": { + "userId": { "type": "string", - "description": "Custom web URL for the git repository. Use when the clone URL goes through a tunnel/VPC and differs from the inferred HTTPS address", - "example": "https://github.com/org/repo" + "format": "uuid", + "description": "Alternate location for the `?userId=` query parameter. Prefer the query parameter — this body field exists for backwards compatibility. Supplying both forms results in a 400. Only valid for org-scoped API keys; when set, the user's attributes are applied for row-level security and connection-environment switching.", + "example": "550e8400-e29b-41d4-a716-446655440000" } } }, - "ModelsGitUpdateResponse": { + "QueryWaitResponse": { "type": "object", "properties": { - "authMethod": { - "type": "string", - "enum": [ - "ssh", - "https_token" + "results": { + "type": "array", + "items": {}, + "description": "Array of completed query results. Each result contains the query data or an error." + } + }, + "required": [ + "results" + ] + }, + "SchedulesListItem": { + "type": "object", + "properties": { + "alert": { + "type": "object", + "properties": { + "conditionQueryName": { + "type": [ + "string", + "null" + ], + "description": "Name of the query used for alert condition" + }, + "conditionType": { + "type": "string", + "description": "Type of alert condition: RESULTS_CHANGED, RESULTS_PRESENT, RESULTS_MISSING" + } + }, + "required": [ + "conditionQueryName", + "conditionType" ], - "description": "Authentication method. \"ssh\" for deploy key, \"https_token\" for deploy token/PAT.", - "example": "ssh" + "description": "Alert configuration (only present for alert-type schedules)" }, - "baseBranch": { + "content": { "type": "string", - "description": "The target branch for Omni pull requests", - "example": "main" + "description": "Content type: dashboard or tile", + "example": "dashboard" }, - "branchPerPullRequest": { - "type": "boolean", - "description": "If true, all pull requests will create a branch in Omni, even those created outside of the tool", - "example": false + "dashboardName": { + "type": "string", + "description": "Name of the dashboard", + "example": "Weekly Sales Report" }, - "cloneUrl": { + "destinationType": { + "type": "string", + "description": "Delivery destination type: email, slack, webhook, sftp, s3, google_sheets", + "example": "email" + }, + "disabledAt": { + "type": [ + "string", + "null" + ], + "format": "date-time", + "description": "Timestamp when the schedule was paused (null if active)" + }, + "format": { "type": "string", - "description": "Clone URL of the git repository (SSH or HTTPS)", - "example": "git@github.com:org/repo.git" + "description": "Output format: pdf, png, csv, xlsx, json, link_only", + "example": "pdf" }, - "gitFollower": { - "type": "boolean", - "description": "If true, the shared model is read-only and can only be updated by merging pull requests to the base branch", - "example": false + "id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the schedule" }, - "gitServiceProvider": { + "identifier": { "type": "string", - "description": "The git provider type", - "example": "github" + "description": "Dashboard identifier", + "example": "12db1a0a" }, - "modelPath": { + "lastCompletedAt": { "type": [ "string", "null" ], - "description": "Path to model files in the repository", - "example": "omni/my_model" + "format": "date-time", + "description": "Timestamp of last completed delivery" }, - "publicKey": { + "lastStatus": { "type": [ "string", "null" ], - "description": "SSH public key for repository access (deploy key). Null for HTTPS token auth.", - "example": "ssh-ed25519 AAAA..." + "description": "Status of last delivery: COMPLETE, ERROR, ERROR_DELIVERED, KILLED, CONDITION_UNMET" }, - "requirePullRequest": { + "name": { "type": "string", - "enum": [ - "always", - "users-only", - "never" - ], - "description": "When pull requests are required: \"always\" for all changes, \"users-only\" for user-initiated changes only, \"never\" for direct commits.", - "example": "users-only" + "description": "Name of the schedule", + "example": "Weekly Sales Report" }, - "sshUrl": { + "ownerId": { "type": "string", - "deprecated": true, - "description": "Deprecated — use cloneUrl. Clone URL of the git repository." + "format": "uuid", + "description": "User ID of the schedule owner" }, - "webUrl": { + "ownerName": { + "type": "string", + "description": "Display name of the schedule owner", + "example": "John Doe" + }, + "recipientCount": { + "type": "number", + "description": "Number of recipients (-1 for non-email destinations)", + "example": 5 + }, + "schedule": { + "type": "string", + "description": "AWS EventBridge cron expression (minute hour day-of-month month day-of-week year)", + "example": "0 9 ? * MON *" + }, + "slackRecipientType": { "type": [ "string", "null" ], - "description": "Custom web URL for the git repository, or null if not set", - "example": "https://github.com/org/repo" + "description": "Slack recipient type: Channel or Users (null for non-Slack)" }, - "webhookSecret": { - "type": "string", - "description": "Webhook secret for signature verification. Only included if requested via ?include=webhookSecret" + "systemDisabledAt": { + "type": [ + "string", + "null" + ], + "format": "date-time", + "description": "Timestamp when system disabled the schedule (null if not system-disabled)" }, - "webhookUrl": { + "systemDisabledReason": { + "type": [ + "string", + "null" + ], + "description": "Reason for system disabling: missingQuery, noAccess, orphanedFilterConfigKeys" + }, + "timezone": { "type": "string", - "description": "Webhook URL to configure in your git provider", - "example": "https://app.omni.co/api/webhooks/model/..." + "description": "IANA timezone for the schedule", + "example": "America/New_York" } }, "required": [ - "authMethod", - "baseBranch", - "branchPerPullRequest", - "cloneUrl", - "gitFollower", - "gitServiceProvider", - "modelPath", - "publicKey", - "requirePullRequest", - "sshUrl", - "webUrl", - "webhookUrl" + "content", + "dashboardName", + "destinationType", + "disabledAt", + "format", + "id", + "identifier", + "lastCompletedAt", + "lastStatus", + "name", + "ownerId", + "ownerName", + "recipientCount", + "schedule", + "slackRecipientType", + "systemDisabledAt", + "systemDisabledReason", + "timezone" ] }, - "ModelsGitUpdateBody": { + "SchedulesGetResponse": { "type": "object", "properties": { - "authMethod": { - "type": "string", - "enum": [ - "ssh", - "https_token" + "conditionQueryMapKey": { + "type": [ + "string", + "null" ], - "description": "Authentication method to change to.", - "example": "ssh" - }, - "baseBranch": { - "type": "string", - "description": "The target branch for Omni pull requests", - "example": "main" + "description": "Query key used for alert condition (null for standard schedules)" }, - "branchPerPullRequest": { - "type": "boolean", - "description": "If true, all pull requests will create a branch in Omni", - "example": false + "conditionType": { + "type": [ + "string", + "null" + ], + "description": "Alert condition type: RESULTS_CHANGED, RESULTS_PRESENT, RESULTS_MISSING" }, - "cloneUrl": { + "createdAt": { "type": "string", - "minLength": 1, - "description": "Clone URL of the git repository (SSH or HTTPS).", - "example": "git@github.com:org/repo.git" + "format": "date-time", + "description": "Creation timestamp" }, - "gitFollower": { - "type": "boolean", - "description": "If true, the shared model will be read-only", - "example": false + "destinations": { + "type": "array", + "items": { + "$ref": "#/components/schemas/SchedulesGetDestination" + }, + "description": "Delivery destination configurations" }, - "gitServiceProvider": { - "type": "string", - "enum": [ - "github", - "gitlab", - "azure_devops", - "bitbucket", - "bitbucket_datacenter", - "auto" + "disabledAt": { + "type": [ + "string", + "null" ], - "description": "The git provider type", - "example": "github" - }, - "modelPath": { - "type": "string", - "description": "Path to model files in the repository", - "example": "my_model" + "format": "date-time", + "description": "Timestamp when the schedule was paused (null if active)" }, - "requirePullRequest": { + "entityId": { "type": "string", - "enum": [ - "always", - "users-only", - "never" - ], - "description": "Controls when pull requests are required", - "example": "users-only" + "description": "ID of the associated dashboard" }, - "sshUrl": { - "type": "string", - "minLength": 1, - "description": "Deprecated — use cloneUrl. Clone URL of the git repository.", - "example": "git@github.com:org/repo.git", - "deprecated": true + "fanOut": { + "type": "boolean", + "description": "Whether personalized fan-out delivery is enabled", + "example": false }, - "token": { - "type": "string", - "maxLength": 1000, - "pattern": "^[a-zA-Z0-9_\\-.]+$", - "description": "HTTPS token for authentication (deploy token value, PAT, etc.)." + "filterConfig": { + "description": "The effective dashboard filter configuration that the schedule will run with: the dashboard's current default filters merged under the schedule's persisted overrides, with any keys no longer present on the dashboard dropped. This matches what is shown when the schedule is opened in the Edit Delivery panel, and may differ from the schedule's persisted filter configuration." }, - "webUrl": { - "type": "string", - "description": "Custom web URL for the git repository. Use when the clone URL goes through a tunnel/VPC and differs from the inferred HTTPS address", - "example": "https://github.com/org/repo" - } - } - }, - "ModelsGitDeleteResponse": { - "type": "object", - "properties": { - "message": { + "id": { "type": "string", - "description": "Success message", - "example": "Git repository unlinked successfully" - }, - "success": { - "type": "boolean", - "description": "Whether the operation succeeded", - "example": true - } - }, - "required": [ - "message", - "success" - ] - }, - "ModelsGitSyncResponse": { - "type": "object", - "properties": { - "didSync": { - "type": "boolean", - "description": "Whether a sync operation was performed" - }, - "gitSha": { - "type": [ - "string", - "null" - ], - "description": "The git SHA after the sync operation" + "format": "uuid", + "description": "Schedule UUID", + "example": "123e4567-e89b-12d3-a456-426614174000" }, - "inSync": { + "killJobsOnFailure": { "type": "boolean", - "description": "Whether the model is currently in sync with git" + "description": "Whether to stop the job if any queries fail", + "example": false }, - "message": { + "metadata": { + "description": "Schedule metadata including format options and delivery settings" + }, + "name": { "type": "string", - "description": "Human-readable message about the sync status" - } - }, - "required": [ - "didSync", - "gitSha", - "inSync", - "message" - ] - }, - "ModelsGitSyncBody": { - "type": "object", - "properties": { - "commitMessage": { + "description": "Schedule name", + "example": "Weekly Sales Report" + }, + "organizationId": { "type": "string", - "description": "Optional commit message for the git sync operation", - "example": "Update model schema" - } - } - }, - "ModelsContentValidatorGetResponse": { - "type": "object", - "properties": { - "branch": { - "type": [ - "object", - "null" - ], + "format": "uuid", + "description": "Organization UUID" + }, + "owner": { + "type": "object", "properties": { - "id": { - "type": "string", - "description": "Branch UUID" - }, "name": { "type": "string", - "description": "Branch name" + "description": "Schedule owner name" } }, "required": [ - "id", "name" - ], - "description": "Branch info (present if branch_id was specified)" + ] }, - "content": { - "type": "array", - "items": {}, - "description": "Documents with their validation results" + "ownerId": { + "type": "string", + "format": "uuid", + "description": "User ID of the schedule owner" }, - "model_id": { + "schedule": { "type": "string", - "description": "Model UUID" - } - }, - "required": [ - "branch", - "content", - "model_id" - ] - }, - "ContentFilterMode": { - "type": "string", - "enum": [ - "ALL", - "WITH_ISSUES", - "NO_ISSUES" - ], - "description": "Filter documents by issue status. ALL (default) returns all documents with at least one query. WITH_ISSUES returns only documents with at least one query issue, dashboard filter issue, or document error. NO_ISSUES returns only documents with zero issues and no document errors." - }, - "ModelsContentValidatorReplaceResponse": { - "type": "object", - "properties": { - "replaced_dashboard_filters_count": { - "type": "integer", - "description": "Number of dashboard filters replaced" + "description": "AWS EventBridge cron expression (minute hour day-of-month month day-of-week year)", + "example": "0 9 ? * MON *" }, - "replaced_documents_count": { - "type": "integer", - "description": "Number of documents modified" + "systemDisabledAt": { + "type": [ + "string", + "null" + ], + "format": "date-time", + "description": "Timestamp when the system disabled the schedule" }, - "replaced_queries_count": { - "type": "integer", - "description": "Number of queries replaced" + "systemDisabledReason": { + "type": [ + "string", + "null" + ], + "description": "Reason for system disabling: missingQuery, noAccess, orphanedFilterConfigKeys" }, - "replaced_workbook_models_count": { - "type": "integer", - "description": "Number of workbook models replaced" + "timezone": { + "type": "string", + "description": "IANA timezone for the schedule", + "example": "America/New_York" }, - "skipped_pr_required_count": { - "type": "integer", - "description": "Number of documents skipped due to pull request requirements" + "updatedAt": { + "type": "string", + "format": "date-time", + "description": "Last update timestamp" } }, "required": [ - "replaced_dashboard_filters_count", - "replaced_documents_count", - "replaced_queries_count", - "replaced_workbook_models_count", - "skipped_pr_required_count" + "conditionQueryMapKey", + "conditionType", + "createdAt", + "destinations", + "disabledAt", + "entityId", + "fanOut", + "id", + "killJobsOnFailure", + "name", + "organizationId", + "owner", + "ownerId", + "schedule", + "systemDisabledAt", + "systemDisabledReason", + "timezone", + "updatedAt" ] }, - "ModelsContentValidatorReplaceBody": { + "SchedulesGetDestination": { "type": "object", "properties": { - "branch_id": { + "format": { "type": "string", - "description": "Optional branch ID" + "description": "Output format: pdf, png, csv, xlsx, json, link_only", + "example": "pdf" }, - "find": { + "id": { "type": "string", - "minLength": 1, - "description": "The string to find" + "format": "uuid", + "description": "Destination UUID" }, - "find_or_replace_type": { - "type": "string", - "enum": [ - "FIELD", - "TOPIC", - "VIEW" + "lastCompletedAt": { + "type": [ + "string", + "null" ], - "description": "Type of find/replace operation." + "format": "date-time", + "description": "Timestamp of last completed delivery" }, - "folder_paths": { + "lastStatus": { + "type": [ + "string", + "null" + ], + "description": "Status of last delivery: COMPLETE, ERROR, ERROR_DELIVERED, KILLED, CONDITION_UNMET" + }, + "metadata": { + "description": "Destination-specific configuration (type, recipients, credentials, etc.)" + }, + "recipients": { "type": "array", "items": { - "type": "string" + "$ref": "#/components/schemas/SchedulesGetRecipient" }, - "description": "Restrict replacement to documents in matching folder paths (prefix match). Documents with no folder are excluded unless \"\" is specified." - }, - "include_personal_folders": { - "type": "boolean", - "default": false, - "description": "Whether to include personal folders" - }, - "labels": { - "type": "string", - "description": "Comma-separated label names to scope replacement. Unknown labels return 400." - }, - "only_in_workbook_id": { - "type": "string", - "description": "Optional workbook ID to limit the replace scope" + "description": "Individual email recipients" }, - "replacement": { - "type": "string", - "minLength": 1, - "description": "The replacement string" + "userGroupRecipients": { + "type": "array", + "items": {}, + "description": "User group recipients" } }, "required": [ - "find", - "find_or_replace_type", - "replacement" + "format", + "id", + "lastCompletedAt", + "lastStatus", + "recipients", + "userGroupRecipients" ] }, - "ModelYamlResponse": { + "SchedulesGetRecipient": { "type": "object", "properties": { - "checksums": { - "type": "object", - "additionalProperties": { - "type": "string" - }, - "description": "Checksums for each file" + "id": { + "type": "string", + "format": "uuid", + "description": "Recipient ID" }, - "files": { + "membership": { "type": "object", - "additionalProperties": { - "type": "string" + "properties": { + "user": { + "type": "object", + "properties": { + "email": { + "type": "string", + "format": "email", + "description": "Recipient email" + }, + "name": { + "type": [ + "string", + "null" + ], + "description": "Recipient name" + } + }, + "required": [ + "email", + "name" + ] + } }, - "description": "YAML content for each file" - }, - "version": { - "type": "number", - "description": "Model version number" + "required": [ + "user" + ] }, - "viewNames": { - "type": "object", - "additionalProperties": {}, - "description": "View name mappings" + "membershipId": { + "type": "string", + "format": "uuid", + "description": "Membership ID" } }, "required": [ - "files", - "version" + "id", + "membership", + "membershipId" ] }, - "ModelYamlCreateRequestBody": { + "SchedulesRecipientsGetResponse": { "type": "object", "properties": { - "branchId": { - "type": "string", - "format": "uuid", - "description": "Branch ID for branch-aware operations" - }, - "fileName": { - "type": "string", - "minLength": 1, - "description": "File name to create or update" + "recipients": { + "type": "array", + "items": { + "$ref": "#/components/schemas/EmailRecipient" + }, + "description": "List of individual recipients (for email destinations)." }, - "mode": { + "type": { "type": "string", "enum": [ - "combined", - "extension", - "staged", - "merged", - "history" + "email", + "google_sheets", + "s3", + "sftp", + "slack", + "webhook" ], - "default": "combined", - "description": "IDE mode for YAML operations" + "description": "The schedule's destination type.", + "example": "email" }, - "commitMessage": { + "userGroupRecipients": { + "type": "array", + "items": { + "$ref": "#/components/schemas/UserGroupRecipient" + }, + "description": "List of user group recipients (for email destinations)." + } + }, + "required": [ + "type" + ] + }, + "EmailRecipient": { + "type": "object", + "properties": { + "email": { "type": "string", - "description": "Commit message for git sync" - }, - "fetchedAtMillis": { - "type": "number", - "description": "Timestamp when the file was fetched" - }, - "fullyResolved": { - "type": "boolean", - "default": false, - "description": "Treat the posted YAML as fully resolved (with the extends chain expanded). Only valid with mode=combined." + "format": "email", + "description": "Recipient's email address.", + "example": "user@example.com" }, - "previousChecksum": { + "id": { "type": "string", - "description": "Previous checksum for conflict detection" + "description": "Unique identifier for the recipient." }, - "yaml": { + "name": { "type": "string", - "description": "YAML content for the file" + "description": "Recipient's display name.", + "example": "John Doe" } }, "required": [ - "fileName", - "yaml" - ], - "additionalProperties": false + "email", + "id", + "name" + ] }, - "QueryRunResponse": { + "UserGroupRecipient": { "type": "object", "properties": { - "completedQueries": { - "type": "array", - "items": {}, - "description": "Queries that completed synchronously with their results." + "id": { + "type": "string", + "description": "User group ID." }, - "jobIds": { + "name": { + "type": "string", + "description": "User group name.", + "example": "Sales Team" + }, + "recipients": { "type": "array", "items": { - "type": "string" + "$ref": "#/components/schemas/EmailRecipient" }, - "description": "Job IDs for queries running asynchronously. Use /api/v1/query/wait to poll for results.", - "example": [ - "job_abc123", - "job_def456" - ] - }, - "plan": { - "description": "Query execution plan (only present if planOnly is true)." + "description": "List of recipients in the user group." } - } + }, + "required": [ + "id", + "name", + "recipients" + ] }, - "QueryTimeoutResponse": { + "SchedulesAddRecipientsResponse": { "type": "object", "properties": { - "detail": { - "type": "string", - "description": "Error message indicating the query timed out.", - "example": "Query timed out" + "addedGroupRecipientsCount": { + "type": "number", + "description": "Number of user group recipients added.", + "example": 1 }, - "remaining_job_ids": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Job IDs for queries that have not yet completed. Use /api/v1/query/wait to poll for results." + "addedRecipientsCount": { + "type": "number", + "description": "Number of individual recipients added.", + "example": 2 }, - "timed_out": { + "success": { "type": "boolean", - "enum": [ - true - ], - "description": "Always true for timeout responses.", + "description": "Whether the operation was successful.", "example": true } }, "required": [ - "detail", - "timed_out" + "addedGroupRecipientsCount", + "addedRecipientsCount", + "success" ] }, - "QueryRunBody": { + "SchedulesAddRecipientsBody": { "type": "object", "properties": { - "branchId": { - "type": "string", - "format": "uuid", - "description": "Optional model branch to run the query against. Must belong to the same shared model as the query. When omitted, the query runs against the shared model. Takes precedence over the legacy `?branch_id=` URL query parameter.", - "example": "550e8400-e29b-41d4-a716-446655440000" - }, - "cache": { - "type": "string", - "enum": [ - "disabled", - "normal", - "refresh", - "refresh_all" - ], - "description": "Cache policy for query execution. Controls whether to use cached results.", - "example": "normal" - }, - "formatResults": { - "type": "boolean", - "description": "Whether to format result values (e.g., apply number formatting). Only valid when resultType is specified." - }, - "planOnly": { - "type": "boolean", - "default": false, - "description": "If true, returns only the query execution plan without running the query." - }, - "query": { - "description": "The semantic query definition including fields, filters, sorts, and other query parameters." + "emails": { + "type": "array", + "items": { + "type": "string", + "format": "email" + }, + "default": [], + "description": "At least one email, userId, or userGroupId must be provided. Array of email addresses to add as recipients.", + "example": [ + "user@example.com" + ] }, - "resultType": { - "type": "string", - "enum": [ - "csv", - "json", - "xlsx" - ], - "description": "Output format for the results. If not specified, returns base64-encoded Arrow format." + "userGroupIds": { + "type": "array", + "items": { + "type": "string", + "format": "uuid" + }, + "default": [], + "description": "At least one email, userId, or userGroupId must be provided. Array of user group UUIDs to add as recipients.", + "example": [ + "123e4567-e89b-12d3-a456-426614174000" + ] }, - "userId": { - "type": "string", - "format": "uuid", - "description": "User ID to execute the query as (for row-level security). Only valid for org-scoped API keys.", - "example": "550e8400-e29b-41d4-a716-446655440000" + "userIds": { + "type": "array", + "items": { + "type": "string", + "format": "uuid" + }, + "default": [], + "description": "At least one email, userId, or userGroupId must be provided. Array of user UUIDs to add as recipients. Use the List users and List embed users endpoints to retrieve user IDs.", + "example": [ + "987fcdeb-51a2-43d7-9b56-254415f67890" + ] } } }, - "QueryWaitResponse": { + "SchedulesRemoveRecipientsResponse": { "type": "object", "properties": { - "results": { - "type": "array", - "items": {}, - "description": "Array of completed query results. Each result contains the query data or an error." + "removedGroupRecipientsCount": { + "type": "number", + "description": "Number of user group recipients removed.", + "example": 1 + }, + "removedRecipientsCount": { + "type": "number", + "description": "Number of individual recipients removed.", + "example": 2 + }, + "success": { + "type": "boolean", + "description": "Whether the operation was successful.", + "example": true } }, "required": [ - "results" + "removedGroupRecipientsCount", + "removedRecipientsCount", + "success" ] }, - "SchedulesListItem": { + "SchedulesRemoveRecipientsBody": { "type": "object", "properties": { - "alert": { - "type": "object", - "properties": { - "conditionQueryName": { - "type": [ - "string", - "null" - ], - "description": "Name of the query used for alert condition" - }, - "conditionType": { - "type": "string", - "description": "Type of alert condition: RESULTS_CHANGED, RESULTS_PRESENT, RESULTS_MISSING" - } + "emails": { + "type": "array", + "items": { + "type": "string", + "format": "email" }, - "required": [ - "conditionQueryName", - "conditionType" - ], - "description": "Alert configuration (only present for alert-type schedules)" - }, - "content": { - "type": "string", - "description": "Content type: dashboard or tile", - "example": "dashboard" - }, - "dashboardName": { - "type": "string", - "description": "Name of the dashboard", - "example": "Weekly Sales Report" - }, - "destinationType": { - "type": "string", - "description": "Delivery destination type: email, slack, webhook, sftp, s3, google_sheets", - "example": "email" - }, - "disabledAt": { - "type": [ - "string", - "null" - ], - "format": "date-time", - "description": "Timestamp when the schedule was paused (null if active)" - }, - "format": { - "type": "string", - "description": "Output format: pdf, png, csv, xlsx, json, link_only", - "example": "pdf" - }, - "id": { - "type": "string", - "format": "uuid", - "description": "Unique identifier for the schedule" - }, - "identifier": { - "type": "string", - "description": "Dashboard identifier", - "example": "12db1a0a" - }, - "lastCompletedAt": { - "type": [ - "string", - "null" - ], - "format": "date-time", - "description": "Timestamp of last completed delivery" - }, - "lastStatus": { - "type": [ - "string", - "null" - ], - "description": "Status of last delivery: COMPLETE, ERROR, ERROR_DELIVERED, KILLED, CONDITION_UNMET" + "default": [], + "description": "At least one email, userId, or userGroupId must be provided. Array of recipient email addresses to remove from the scheduled task.", + "example": [ + "user@example.com" + ] }, - "name": { - "type": "string", - "description": "Name of the schedule", - "example": "Weekly Sales Report" + "userGroupIds": { + "type": "array", + "items": { + "type": "string", + "format": "uuid" + }, + "default": [], + "description": "At least one email, userId, or userGroupId must be provided. Array of user group UUIDs to remove as recipients.", + "example": [ + "123e4567-e89b-12d3-a456-426614174000" + ] }, - "ownerId": { + "userIds": { + "type": "array", + "items": { + "type": "string", + "format": "uuid" + }, + "default": [], + "description": "At least one email, userId, or userGroupId must be provided. Array of recipient user UUIDs to remove from the scheduled task. Use the List users and List embed users endpoints to retrieve user IDs.", + "example": [ + "987fcdeb-51a2-43d7-9b56-254415f67890" + ] + } + } + }, + "SchedulesTransferOwnershipBody": { + "type": "object", + "properties": { + "userId": { "type": "string", "format": "uuid", - "description": "User ID of the schedule owner" - }, - "ownerName": { - "type": "string", - "description": "Display name of the schedule owner", - "example": "John Doe" - }, - "recipientCount": { - "type": "number", - "description": "Number of recipients (-1 for non-email destinations)", - "example": 5 - }, - "schedule": { - "type": "string", - "description": "AWS EventBridge cron expression (minute hour day-of-month month day-of-week year)", - "example": "0 9 ? * MON *" - }, - "slackRecipientType": { - "type": [ - "string", - "null" - ], - "description": "Slack recipient type: Channel or Users (null for non-Slack)" - }, - "systemDisabledAt": { - "type": [ - "string", - "null" - ], - "format": "date-time", - "description": "Timestamp when system disabled the schedule (null if not system-disabled)" - }, - "systemDisabledReason": { - "type": [ - "string", - "null" - ], - "description": "Reason for system disabling: missingQuery, noAccess, orphanedFilterConfigKeys" - }, - "timezone": { - "type": "string", - "description": "IANA timezone for the schedule", - "example": "America/New_York" + "description": "The UUID of the user to transfer schedule ownership to. Use the List users endpoint to retrieve user IDs. The new owner must be a member of the same organization, not be the current owner, and have permission to view the dashboard associated with the schedule.", + "example": "987fcdeb-51a2-43d7-9b56-254415f67890" } }, "required": [ - "content", - "dashboardName", - "destinationType", - "disabledAt", - "format", - "id", - "identifier", - "lastCompletedAt", - "lastStatus", - "name", - "ownerId", - "ownerName", - "recipientCount", - "schedule", - "slackRecipientType", - "systemDisabledAt", - "systemDisabledReason", - "timezone" + "userId" ] }, - "SchedulesGetResponse": { + "ScimUsersListResponse": { "type": "object", "properties": { - "conditionQueryMapKey": { - "type": [ - "string", - "null" - ], - "description": "Query key used for alert condition (null for standard schedules)" - }, - "conditionType": { - "type": [ - "string", - "null" - ], - "description": "Alert condition type: RESULTS_CHANGED, RESULTS_PRESENT, RESULTS_MISSING" + "Resources": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ScimUserResponse" + }, + "description": "List of SCIM users" }, - "createdAt": { - "type": "string", - "format": "date-time", - "description": "Creation timestamp" + "itemsPerPage": { + "type": "number", + "description": "Items per page" }, - "destinations": { + "schemas": { "type": "array", "items": { - "$ref": "#/components/schemas/SchedulesGetDestination" + "type": "string" }, - "description": "Delivery destination configurations" - }, - "disabledAt": { - "type": [ - "string", - "null" - ], - "format": "date-time", - "description": "Timestamp when the schedule was paused (null if active)" + "description": "SCIM schema URIs" }, - "entityId": { - "type": "string", - "description": "ID of the associated dashboard" + "startIndex": { + "type": "number", + "description": "Start index (1-based)" }, - "fanOut": { + "totalResults": { + "type": "number", + "description": "Total number of results" + } + }, + "required": [ + "Resources", + "itemsPerPage", + "schemas", + "startIndex", + "totalResults" + ] + }, + "ScimUserResponse": { + "type": "object", + "properties": { + "active": { "type": "boolean", - "description": "Whether personalized fan-out delivery is enabled", - "example": false + "description": "Whether the user is active" }, - "filterConfig": { - "description": "Applied dashboard filter configuration" + "displayName": { + "type": "string", + "description": "Display name" }, "id": { "type": "string", "format": "uuid", - "description": "Schedule UUID", - "example": "123e4567-e89b-12d3-a456-426614174000" - }, - "killJobsOnFailure": { - "type": "boolean", - "description": "Whether to stop the job if any queries fail", - "example": false + "description": "SCIM user ID" }, - "metadata": { - "description": "Schedule metadata including format options and delivery settings" + "schemas": { + "type": "array", + "items": { + "type": "string" + }, + "description": "SCIM schema URIs" }, - "name": { + "userName": { "type": "string", - "description": "Schedule name", - "example": "Weekly Sales Report" - }, - "organizationId": { + "format": "email", + "description": "Username (email)" + } + }, + "required": [ + "active", + "displayName", + "id", + "schemas", + "userName" + ] + }, + "ScimUserCreateRequest": { + "type": "object", + "properties": { + "displayName": { "type": "string", - "format": "uuid", - "description": "Organization UUID" + "description": "Display name of the user", + "example": "John Doe" }, - "owner": { + "urn:omni:params:1.0:UserAttribute": { "type": "object", - "properties": { - "name": { - "type": "string", - "description": "Schedule owner name" - } + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "array", + "items": { + "type": "number" + } + }, + { + "type": "null" + }, + { + "type": "boolean" + }, + { + "type": "object", + "properties": {} + } + ] }, - "required": [ - "name" - ] - }, - "ownerId": { - "type": "string", - "format": "uuid", - "description": "User ID of the schedule owner" - }, - "schedule": { - "type": "string", - "description": "AWS EventBridge cron expression (minute hour day-of-month month day-of-week year)", - "example": "0 9 ? * MON *" - }, - "systemDisabledAt": { - "type": [ - "string", - "null" - ], - "format": "date-time", - "description": "Timestamp when the system disabled the schedule" - }, - "systemDisabledReason": { - "type": [ - "string", - "null" - ], - "description": "Reason for system disabling: missingQuery, noAccess, orphanedFilterConfigKeys" - }, - "timezone": { - "type": "string", - "description": "IANA timezone for the schedule", - "example": "America/New_York" + "description": "Omni user attributes" }, - "updatedAt": { + "userName": { "type": "string", - "format": "date-time", - "description": "Last update timestamp" + "format": "email", + "description": "Email address (username) of the user", + "example": "user@example.com" } }, "required": [ - "conditionQueryMapKey", - "conditionType", - "createdAt", - "destinations", - "disabledAt", - "entityId", - "fanOut", - "id", - "killJobsOnFailure", - "name", - "organizationId", - "owner", - "ownerId", - "schedule", - "systemDisabledAt", - "systemDisabledReason", - "timezone", - "updatedAt" + "displayName", + "userName" ] }, - "SchedulesGetDestination": { + "ScimUserPutRequest": { "type": "object", "properties": { - "format": { - "type": "string", - "description": "Output format: pdf, png, csv, xlsx, json, link_only", - "example": "pdf" + "active": { + "type": "boolean", + "default": true, + "description": "Whether the user is active" }, - "id": { + "displayName": { "type": "string", - "format": "uuid", - "description": "Destination UUID" - }, - "lastCompletedAt": { - "type": [ - "string", - "null" - ], - "format": "date-time", - "description": "Timestamp of last completed delivery" - }, - "lastStatus": { - "type": [ - "string", - "null" - ], - "description": "Status of last delivery: COMPLETE, ERROR, ERROR_DELIVERED, KILLED, CONDITION_UNMET" + "description": "Display name of the user" }, - "metadata": { - "description": "Destination-specific configuration (type, recipients, credentials, etc.)" + "urn:ietf:params:scim:schemas:extension:enterprise:2.0:User": { + "type": "object", + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "array", + "items": { + "type": "number" + } + }, + { + "type": "null" + }, + { + "type": "boolean" + }, + { + "type": "object", + "properties": {} + } + ] + }, + "description": "Enterprise SCIM user attributes" }, - "recipients": { - "type": "array", - "items": { - "$ref": "#/components/schemas/SchedulesGetRecipient" + "urn:omni:params:1.0:UserAttribute": { + "type": "object", + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "array", + "items": { + "type": "number" + } + }, + { + "type": "null" + }, + { + "type": "boolean" + }, + { + "type": "object", + "properties": {} + } + ] }, - "description": "Individual email recipients" + "description": "Omni user attributes" }, - "userGroupRecipients": { - "type": "array", - "items": {}, - "description": "User group recipients" + "userName": { + "type": "string", + "format": "email", + "description": "Email address (username) of the user", + "example": "user@example.com" } }, "required": [ - "format", - "id", - "lastCompletedAt", - "lastStatus", - "recipients", - "userGroupRecipients" + "userName" ] }, - "SchedulesGetRecipient": { + "ScimUserPatchRequest": { "type": "object", "properties": { - "id": { - "type": "string", - "format": "uuid", - "description": "Recipient ID" - }, - "membership": { - "type": "object", - "properties": { - "user": { - "type": "object", - "properties": { - "email": { - "type": "string", - "format": "email", - "description": "Recipient email" - }, - "name": { - "type": [ - "string", - "null" - ], - "description": "Recipient name" - } + "Operations": { + "type": "array", + "items": { + "type": "object", + "properties": { + "op": { + "type": "string", + "enum": [ + "replace", + "Replace", + "add", + "Add", + "Remove", + "remove" + ] }, - "required": [ - "email", - "name" - ] - } + "path": { + "type": "string" + }, + "value": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "array", + "items": { + "type": "number" + } + }, + { + "type": "null" + }, + { + "type": "boolean" + }, + { + "type": "object", + "properties": { + "urn:ietf:params:scim:schemas:extension:enterprise:2.0:User": { + "type": "object", + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "array", + "items": { + "type": "number" + } + }, + { + "type": "null" + }, + { + "type": "boolean" + }, + { + "type": "object", + "properties": {} + } + ] + } + }, + "urn:omni:params:1.0:UserAttribute": { + "type": "object", + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "array", + "items": { + "type": "number" + } + }, + { + "type": "null" + }, + { + "type": "boolean" + }, + { + "type": "object", + "properties": {} + } + ] + } + }, + "active": { + "type": "boolean" + }, + "displayName": { + "type": "string" + }, + "userName": { + "type": "string", + "format": "email" + } + } + } + ] + } + }, + "required": [ + "op", + "value" + ] }, - "required": [ - "user" - ] + "minItems": 1, + "description": "List of patch operations to apply" }, - "membershipId": { - "type": "string", - "format": "uuid", - "description": "Membership ID" + "schemas": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "urn:ietf:params:scim:api:messages:2.0:PatchOp" + ] + }, + "description": "SCIM schema URIs" } }, "required": [ - "id", - "membership", - "membershipId" + "Operations", + "schemas" ] }, - "SchedulesRecipientsGetResponse": { + "ScimGroupsListResponse": { "type": "object", "properties": { - "recipients": { + "Resources": { "type": "array", "items": { - "$ref": "#/components/schemas/EmailRecipient" + "$ref": "#/components/schemas/ScimGroupResponse" }, - "description": "List of individual recipients (for email destinations)." + "description": "List of SCIM groups" }, - "type": { - "type": "string", - "enum": [ - "email", - "google_sheets", - "s3", - "sftp", - "slack", - "webhook" - ], - "description": "The schedule's destination type.", - "example": "email" + "itemsPerPage": { + "type": "number", + "description": "Items per page" }, - "userGroupRecipients": { + "schemas": { "type": "array", "items": { - "$ref": "#/components/schemas/UserGroupRecipient" + "type": "string" }, - "description": "List of user group recipients (for email destinations)." + "description": "SCIM schema URIs" + }, + "startIndex": { + "type": "number", + "description": "Start index (1-based)" + }, + "totalResults": { + "type": "number", + "description": "Total number of results" } }, "required": [ - "type" + "Resources", + "itemsPerPage", + "schemas", + "startIndex", + "totalResults" ] }, - "EmailRecipient": { + "ScimGroupResponse": { "type": "object", "properties": { - "email": { + "displayName": { "type": "string", - "format": "email", - "description": "Recipient's email address.", - "example": "user@example.com" + "description": "Group display name" }, "id": { "type": "string", - "description": "Unique identifier for the recipient." + "description": "SCIM group ID (miniUuid)" }, - "name": { - "type": "string", - "description": "Recipient's display name.", - "example": "John Doe" + "members": { + "type": "array", + "items": { + "type": "object", + "properties": { + "display": { + "type": "string", + "description": "Member display name" + }, + "value": { + "type": "string", + "format": "uuid", + "description": "Member user ID" + } + }, + "required": [ + "display", + "value" + ] + }, + "description": "Group members" + }, + "schemas": { + "type": "array", + "items": { + "type": "string" + }, + "description": "SCIM schema URIs" } }, "required": [ - "email", + "displayName", "id", - "name" + "schemas" ] }, - "UserGroupRecipient": { + "ScimGroupsCreateBody": { "type": "object", "properties": { - "id": { - "type": "string", - "description": "User group ID." - }, - "name": { + "displayName": { "type": "string", - "description": "User group name.", - "example": "Sales Team" + "description": "Display name of the group", + "example": "Engineering Team" }, - "recipients": { + "members": { "type": "array", "items": { - "$ref": "#/components/schemas/EmailRecipient" + "type": "object", + "properties": { + "value": { + "type": "string", + "format": "uuid", + "description": "User membership ID", + "example": "550e8400-e29b-41d4-a716-446655440000" + } + }, + "required": [ + "value" + ] }, - "description": "List of recipients in the user group." + "default": [], + "description": "List of group members" } }, "required": [ - "id", - "name", - "recipients" + "displayName" ] }, - "SchedulesAddRecipientsResponse": { + "ScimGroupsReplaceBody": { "type": "object", "properties": { - "addedGroupRecipientsCount": { - "type": "number", - "description": "Number of user group recipients added.", - "example": 1 - }, - "addedRecipientsCount": { - "type": "number", - "description": "Number of individual recipients added.", - "example": 2 + "displayName": { + "type": "string", + "description": "Display name of the group", + "example": "Engineering Team" }, - "success": { - "type": "boolean", - "description": "Whether the operation was successful.", - "example": true + "members": { + "type": "array", + "items": { + "type": "object", + "properties": { + "display": { + "type": "string", + "description": "Display name of the member", + "example": "john.doe@example.com" + }, + "value": { + "type": "string", + "format": "uuid", + "description": "User membership ID", + "example": "550e8400-e29b-41d4-a716-446655440000" + } + }, + "required": [ + "display", + "value" + ] + }, + "description": "List of group members" } }, "required": [ - "addedGroupRecipientsCount", - "addedRecipientsCount", - "success" + "displayName", + "members" ] }, - "SchedulesAddRecipientsBody": { + "ScimGroupsPatchBody": { "type": "object", "properties": { - "emails": { - "type": "array", - "items": { - "type": "string", - "format": "email" - }, - "default": [], - "description": "At least one email, userId, or userGroupId must be provided. Array of email addresses to add as recipients.", - "example": [ - "user@example.com" - ] - }, - "userGroupIds": { + "Operations": { "type": "array", "items": { - "type": "string", - "format": "uuid" + "anyOf": [ + { + "type": "object", + "properties": { + "op": { + "type": "string", + "enum": [ + "replace", + "Replace" + ], + "description": "Operation type", + "example": "replace" + }, + "value": { + "type": "object", + "properties": { + "displayName": { + "type": "string", + "description": "New display name", + "example": "Engineering Team" + }, + "id": { + "type": "string", + "description": "Group ID" + } + }, + "required": [ + "displayName" + ] + } + }, + "required": [ + "op", + "value" + ] + }, + { + "type": "object", + "properties": { + "op": { + "type": "string", + "enum": [ + "remove", + "Remove" + ], + "description": "Operation type", + "example": "remove" + }, + "path": { + "type": "string", + "pattern": "members\\[value eq \"(.{36})\"\\]", + "description": "SCIM path for member to remove", + "example": "members[value eq \"550e8400-e29b-41d4-a716-446655440000\"]" + } + }, + "required": [ + "op", + "path" + ] + }, + { + "type": "object", + "properties": { + "op": { + "type": "string", + "enum": [ + "add", + "Add" + ], + "description": "Operation type", + "example": "add" + }, + "path": { + "type": "string", + "enum": [ + "members" + ], + "description": "Path for members", + "example": "members" + }, + "value": { + "type": "array", + "items": { + "type": "object", + "properties": { + "display": { + "type": "string", + "description": "Display name of the member", + "example": "john.doe@example.com" + }, + "value": { + "type": "string", + "format": "uuid", + "description": "User membership ID", + "example": "550e8400-e29b-41d4-a716-446655440000" + } + }, + "required": [ + "value" + ] + } + } + }, + "required": [ + "op", + "path", + "value" + ] + }, + { + "type": "object", + "properties": { + "op": { + "type": "string", + "enum": [ + "replace", + "Replace" + ], + "description": "Operation type", + "example": "replace" + }, + "path": { + "type": "string", + "enum": [ + "members", + "displayName" + ], + "description": "Path for attribute to replace", + "example": "members" + }, + "value": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "object", + "properties": { + "display": { + "type": "string", + "description": "Display name of the member", + "example": "john.doe@example.com" + }, + "value": { + "type": "string", + "format": "uuid", + "description": "User membership ID", + "example": "550e8400-e29b-41d4-a716-446655440000" + } + }, + "required": [ + "value" + ] + } + }, + { + "type": "string" + } + ] + } + }, + "required": [ + "op", + "path", + "value" + ] + } + ] }, - "default": [], - "description": "At least one email, userId, or userGroupId must be provided. Array of user group UUIDs to add as recipients.", - "example": [ - "123e4567-e89b-12d3-a456-426614174000" - ] + "description": "List of SCIM patch operations" }, - "userIds": { + "schemas": { "type": "array", "items": { "type": "string", - "format": "uuid" + "enum": [ + "urn:ietf:params:scim:api:messages:2.0:PatchOp" + ] }, - "default": [], - "description": "At least one email, userId, or userGroupId must be provided. Array of user UUIDs to add as recipients. Use the List users and List embed users endpoints to retrieve user IDs.", - "example": [ - "987fcdeb-51a2-43d7-9b56-254415f67890" - ] - } - } - }, - "SchedulesRemoveRecipientsResponse": { - "type": "object", - "properties": { - "removedGroupRecipientsCount": { - "type": "number", - "description": "Number of user group recipients removed.", - "example": 1 - }, - "removedRecipientsCount": { - "type": "number", - "description": "Number of individual recipients removed.", - "example": 2 - }, - "success": { - "type": "boolean", - "description": "Whether the operation was successful.", - "example": true + "description": "SCIM schema URIs" } }, "required": [ - "removedGroupRecipientsCount", - "removedRecipientsCount", - "success" + "Operations", + "schemas" ] }, - "SchedulesRemoveRecipientsBody": { + "DocumentExportResponse": { "type": "object", "properties": { - "emails": { - "type": "array", - "items": { - "type": "string", - "format": "email" - }, - "default": [], - "description": "At least one email, userId, or userGroupId must be provided. Array of recipient email addresses to remove from the scheduled task.", - "example": [ - "user@example.com" - ] - }, - "userGroupIds": { - "type": "array", - "items": { - "type": "string", - "format": "uuid" - }, - "default": [], - "description": "At least one email, userId, or userGroupId must be provided. Array of user group UUIDs to remove as recipients.", - "example": [ - "123e4567-e89b-12d3-a456-426614174000" - ] + "dashboard": { + "description": "Dashboard configuration and layout" }, - "userIds": { - "type": "array", - "items": { - "type": "string", - "format": "uuid" + "document": { + "type": "object", + "properties": { + "ephemeral": { + "type": "string" + }, + "name": { + "type": "string" + } }, - "default": [], - "description": "At least one email, userId, or userGroupId must be provided. Array of recipient user UUIDs to remove from the scheduled task. Use the List users and List embed users endpoints to retrieve user IDs.", - "example": [ - "987fcdeb-51a2-43d7-9b56-254415f67890" + "required": [ + "name" ] - } - } - }, - "SchedulesTransferOwnershipBody": { - "type": "object", - "properties": { - "userId": { - "type": "string", - "format": "uuid", - "description": "The UUID of the user to transfer schedule ownership to. Use the List users endpoint to retrieve user IDs. The new owner must be a member of the same organization, not be the current owner, and have permission to view the dashboard associated with the schedule.", - "example": "987fcdeb-51a2-43d7-9b56-254415f67890" - } - }, - "required": [ - "userId" - ] - }, - "ScimUsersListResponse": { - "type": "object", - "properties": { - "Resources": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ScimUserResponse" - }, - "description": "List of SCIM users" }, - "itemsPerPage": { - "type": "number", - "description": "Items per page" + "exportVersion": { + "type": "string" }, - "schemas": { - "type": "array", - "items": { - "type": "string" - }, - "description": "SCIM schema URIs" + "fileUploads": { + "type": "object", + "additionalProperties": {} }, - "startIndex": { - "type": "number", - "description": "Start index (1-based)" + "queryModels": { + "type": "object", + "additionalProperties": {} }, - "totalResults": { - "type": "number", - "description": "Total number of results" - } + "workbookModel": {} }, "required": [ - "Resources", - "itemsPerPage", - "schemas", - "startIndex", - "totalResults" + "document", + "exportVersion", + "queryModels" ] }, - "ScimUserResponse": { + "DocumentImportResponse": { "type": "object", "properties": { - "active": { - "type": "boolean", - "description": "Whether the user is active" - }, - "displayName": { - "type": "string", - "description": "Display name" - }, - "id": { + "documentId": { "type": "string", "format": "uuid", - "description": "SCIM user ID" - }, - "schemas": { - "type": "array", - "items": { - "type": "string" - }, - "description": "SCIM schema URIs" + "description": "ID of the imported document" }, - "userName": { + "identifier": { "type": "string", - "format": "email", - "description": "Username (email)" + "description": "Document identifier (miniUuid)" } }, "required": [ - "active", - "displayName", - "id", - "schemas", - "userName" + "documentId", + "identifier" ] }, - "ScimUserCreateRequest": { + "DocumentImportBody": { "type": "object", "properties": { - "displayName": { + "baseModelId": { "type": "string", - "description": "Display name of the user", - "example": "John Doe" + "format": "uuid", + "description": "Base model ID for the imported document" }, - "urn:omni:params:1.0:UserAttribute": { + "dashboard": { + "description": "Dashboard export data" + }, + "document": { "type": "object", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "array", - "items": { - "type": "string" - } - }, - { - "type": "array", - "items": { - "type": "number" - } - }, - { - "type": "null" - }, - { - "type": "boolean" - }, - { - "type": "object", - "properties": {} - } - ] + "properties": { + "ephemeral": { + "type": "string" + }, + "name": { + "type": "string" + } }, - "description": "Omni user attributes" - }, - "userName": { - "type": "string", - "format": "email", - "description": "Email address (username) of the user", - "example": "user@example.com" - } - }, - "required": [ - "displayName", - "userName" - ] - }, - "ScimUserPutRequest": { - "type": "object", - "properties": { - "active": { - "type": "boolean", - "default": true, - "description": "Whether the user is active" + "required": [ + "name" + ] }, - "displayName": { + "exportVersion": { "type": "string", - "description": "Display name of the user" + "enum": [ + "0.1" + ] }, - "urn:ietf:params:scim:schemas:extension:enterprise:2.0:User": { + "fileUploads": { "type": "object", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "array", - "items": { - "type": "string" - } - }, - { - "type": "array", - "items": { - "type": "number" - } - }, - { - "type": "null" - }, - { - "type": "boolean" - }, - { - "type": "object", - "properties": {} - } - ] - }, - "description": "Enterprise SCIM user attributes" + "additionalProperties": {} }, - "urn:omni:params:1.0:UserAttribute": { + "folderPath": { + "type": "string" + }, + "identifier": { + "type": "string" + }, + "queryModels": { "type": "object", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "array", - "items": { - "type": "string" - } - }, - { - "type": "array", - "items": { - "type": "number" - } - }, - { - "type": "null" - }, - { - "type": "boolean" - }, - { - "type": "object", - "properties": {} - } - ] - }, - "description": "Omni user attributes" + "additionalProperties": {} }, - "userName": { - "type": "string", - "format": "email", - "description": "Email address (username) of the user", - "example": "user@example.com" - } + "workbookModel": {} }, "required": [ - "userName" + "baseModelId", + "document", + "exportVersion", + "queryModels" ] }, - "ScimUserPatchRequest": { + "UserAttributesListResponse": { "type": "object", "properties": { - "Operations": { + "records": { "type": "array", "items": { "type": "object", "properties": { - "op": { - "type": "string", - "enum": [ - "replace", - "Replace", - "add", - "Add", - "Remove", - "remove" - ] - }, - "path": { - "type": "string" - }, - "value": { + "default_value": { "anyOf": [ { "type": "string" @@ -6614,1988 +29478,3177 @@ { "type": "array", "items": { - "type": "string" - } - }, - { - "type": "array", - "items": { - "type": "number" + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + } + ] } }, { "type": "null" - }, - { - "type": "boolean" - }, - { - "type": "object", - "properties": { - "active": { - "type": "boolean" - }, - "displayName": { - "type": "string" - }, - "userName": { - "type": "string", - "format": "email" - } - } } - ] + ], + "description": "Default value applied when no user-specific value is set. When multiple_values is true, this is an array. Null if no default is configured.", + "example": "us-east" + }, + "description": { + "type": [ + "string", + "null" + ], + "description": "Human-readable description of the attribute and its purpose", + "example": "User region for row-level security filtering" + }, + "id": { + "type": "string", + "description": "Unique identifier for custom attributes. Empty string for system-defined attributes.", + "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" + }, + "label": { + "type": "string", + "description": "Display name shown in the Omni UI", + "example": "Region" + }, + "multiple_values": { + "type": "boolean", + "description": "Whether the attribute accepts an array of values. When true, default_value and user-specific values are arrays.", + "example": false + }, + "name": { + "type": "string", + "description": "Reference name used in model SQL and in embed SSO URL parameters", + "example": "region" + }, + "system": { + "type": "boolean", + "description": "System-defined attributes (e.g. omni_user_id, omni_user_email) are built-in and read-only. Custom attributes have system=false.", + "example": false + }, + "type": { + "type": "string", + "enum": [ + "String", + "Number" + ], + "description": "Data type that determines valid values. String attributes accept text, Number attributes accept numeric values stored as strings for precision.", + "example": "String" } }, - "required": [ - "op", - "value" - ] + "required": [ + "default_value", + "description", + "id", + "label", + "multiple_values", + "name", + "system", + "type" + ] + }, + "description": "All user attribute definitions in the organization, including both system-defined and custom attributes" + } + }, + "required": [ + "records" + ] + }, + "UploadsListResponse": { + "type": "object", + "properties": { + "pageInfo": { + "$ref": "#/components/schemas/PageInfo" + }, + "records": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Upload" + } + } + }, + "required": [ + "pageInfo", + "records" + ] + }, + "Upload": { + "type": "object", + "properties": { + "connection_id": { + "type": "string", + "format": "uuid", + "description": "Connection ID the upload is associated with" + }, + "created_at": { + "type": "string", + "format": "date-time", + "description": "When the file was uploaded" + }, + "file_name": { + "type": "string", + "description": "Original file name", + "example": "users.csv" + }, + "id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the upload" + }, + "in_db_as_table_name": { + "type": [ + "string", + "null" + ], + "description": "Database table name if uploaded to database scratch schema" + }, + "model_id": { + "type": [ + "string", + "null" + ], + "format": "uuid", + "description": "Model ID the upload is associated with (inferred from connection's shared model if not explicitly set)" + }, + "size_bytes": { + "type": [ + "number", + "null" + ], + "description": "File size in bytes" + }, + "updated_at": { + "type": "string", + "format": "date-time", + "description": "Last update timestamp" + }, + "uploaded_by_user": { + "type": [ + "object", + "null" + ], + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "User ID of the uploader" + }, + "name": { + "type": "string", + "description": "Name of the user who uploaded the file" + } }, - "minItems": 1, - "description": "List of patch operations to apply" + "required": [ + "id", + "name" + ], + "description": "User who uploaded the file" }, - "schemas": { - "type": "array", - "items": { - "type": "string", - "enum": [ - "urn:ietf:params:scim:api:messages:2.0:PatchOp" - ] - }, - "description": "SCIM schema URIs" + "view_name": { + "type": "string", + "description": "View name associated with the upload" } }, "required": [ - "Operations", - "schemas" + "connection_id", + "created_at", + "file_name", + "id", + "in_db_as_table_name", + "model_id", + "size_bytes", + "updated_at", + "uploaded_by_user", + "view_name" ] }, - "ScimGroupsListResponse": { + "UploadCreateResponse": { "type": "object", "properties": { - "Resources": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ScimGroupResponse" - }, - "description": "List of SCIM groups" + "fileName": { + "type": "string", + "description": "Original file name", + "example": "users.csv" }, - "itemsPerPage": { - "type": "number", - "description": "Items per page" + "id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the upload" }, - "schemas": { - "type": "array", - "items": { - "type": "string" - }, - "description": "SCIM schema URIs" + "inDbAsTableName": { + "type": "string", + "description": "Database table name in the scratch schema" }, - "startIndex": { - "type": "number", - "description": "Start index (1-based)" + "modelId": { + "type": "string", + "format": "uuid", + "description": "Model ID the view was created in" }, - "totalResults": { - "type": "number", - "description": "Total number of results" + "rowCount": { + "type": "integer", + "description": "Number of rows in the uploaded file" + }, + "truncated": { + "type": "boolean", + "description": "Whether the file was truncated due to row limit" + }, + "viewCreated": { + "type": "boolean", + "description": "Whether a view was created in the model" + }, + "viewName": { + "type": "string", + "description": "Name of the view created" } }, "required": [ - "Resources", - "itemsPerPage", - "schemas", - "startIndex", - "totalResults" + "fileName", + "id", + "inDbAsTableName", + "modelId", + "rowCount", + "truncated", + "viewCreated", + "viewName" ] }, - "ScimGroupResponse": { + "UploadCreateBody": { "type": "object", "properties": { - "displayName": { + "branchId": { "type": "string", - "description": "Group display name" + "format": "uuid", + "description": "UUID of the branch to create the view in (mutually exclusive with branchName)" }, - "id": { + "branchName": { "type": "string", - "description": "SCIM group ID (miniUuid)" + "description": "Name of the branch to create the view in (mutually exclusive with branchId)" }, - "members": { - "type": "array", - "items": { - "type": "object", - "properties": { - "display": { - "type": "string", - "description": "Member display name" - }, - "value": { - "type": "string", - "format": "uuid", - "description": "Member user ID" - } - }, - "required": [ - "display", - "value" - ] - }, - "description": "Group members" + "file": { + "type": "string", + "description": "The CSV file to upload", + "format": "binary" }, - "schemas": { - "type": "array", - "items": { - "type": "string" - }, - "description": "SCIM schema URIs" + "modelId": { + "type": "string", + "format": "uuid", + "description": "UUID of the model to create the view in" + }, + "viewName": { + "type": "string", + "description": "Override the view name (defaults to sanitized file name)" } }, "required": [ - "displayName", - "id", - "schemas" + "file", + "modelId" ] }, - "ScimGroupsCreateBody": { + "UploadDeleteResponse": { "type": "object", "properties": { - "displayName": { - "type": "string", - "description": "Display name of the group", - "example": "Engineering Team" - }, - "members": { - "type": "array", - "items": { - "type": "object", - "properties": { - "value": { - "type": "string", - "format": "uuid", - "description": "User membership ID", - "example": "550e8400-e29b-41d4-a716-446655440000" - } - }, - "required": [ - "value" - ] - }, - "default": [], - "description": "List of group members" + "success": { + "type": "boolean", + "description": "Whether the deletion was successful" } }, "required": [ - "displayName" + "success" ] }, - "ScimGroupsReplaceBody": { + "UsersGetModelRolesResponse": { "type": "object", "properties": { - "displayName": { + "membershipId": { "type": "string", - "description": "Display name of the group", - "example": "Engineering Team" - }, - "members": { - "type": "array", - "items": { - "type": "object", - "properties": { - "display": { - "type": "string", - "description": "Display name of the member", - "example": "john.doe@example.com" - }, - "value": { - "type": "string", - "format": "uuid", - "description": "User membership ID", - "example": "550e8400-e29b-41d4-a716-446655440000" - } - }, - "required": [ - "display", - "value" - ] + "format": "uuid", + "description": "The user membership ID" + }, + "results": { + "type": "array", + "items": { + "$ref": "#/components/schemas/RoleAssignmentResult" }, - "description": "List of group members" + "description": "List of role assignments" } }, "required": [ - "displayName", - "members" + "membershipId", + "results" ] }, - "ScimGroupsPatchBody": { + "RoleAssignmentResult": { "type": "object", "properties": { - "Operations": { - "type": "array", - "items": { - "anyOf": [ - { - "type": "object", - "properties": { - "op": { - "type": "string", - "enum": [ - "replace", - "Replace" - ], - "description": "Operation type", - "example": "replace" - }, - "value": { - "type": "object", - "properties": { - "displayName": { - "type": "string", - "description": "New display name", - "example": "Engineering Team" - }, - "id": { - "type": "string", - "description": "Group ID" - } - }, - "required": [ - "displayName" - ] - } - }, - "required": [ - "op", - "value" - ] - }, - { - "type": "object", - "properties": { - "op": { - "type": "string", - "enum": [ - "remove", - "Remove" - ], - "description": "Operation type", - "example": "remove" - }, - "path": { - "type": "string", - "pattern": "members\\[value eq \"(.{36})\"\\]", - "description": "SCIM path for member to remove", - "example": "members[value eq \"550e8400-e29b-41d4-a716-446655440000\"]" - } - }, - "required": [ - "op", - "path" - ] - }, - { - "type": "object", - "properties": { - "op": { - "type": "string", - "enum": [ - "add", - "Add" - ], - "description": "Operation type", - "example": "add" - }, - "path": { - "type": "string", - "enum": [ - "members" - ], - "description": "Path for members", - "example": "members" - }, - "value": { - "type": "array", - "items": { - "type": "object", - "properties": { - "display": { - "type": "string", - "description": "Display name of the member", - "example": "john.doe@example.com" - }, - "value": { - "type": "string", - "format": "uuid", - "description": "User membership ID", - "example": "550e8400-e29b-41d4-a716-446655440000" - } - }, - "required": [ - "value" - ] - } - } - }, - "required": [ - "op", - "path", - "value" - ] - }, - { - "type": "object", - "properties": { - "op": { - "type": "string", - "enum": [ - "replace", - "Replace" - ], - "description": "Operation type", - "example": "replace" - }, - "path": { - "type": "string", - "enum": [ - "members", - "displayName" - ], - "description": "Path for attribute to replace", - "example": "members" - }, - "value": { - "anyOf": [ - { - "type": "array", - "items": { - "type": "object", - "properties": { - "display": { - "type": "string", - "description": "Display name of the member", - "example": "john.doe@example.com" - }, - "value": { - "type": "string", - "format": "uuid", - "description": "User membership ID", - "example": "550e8400-e29b-41d4-a716-446655440000" - } - }, - "required": [ - "value" - ] - } - }, - { - "type": "string" - } - ] - } - }, - "required": [ - "op", - "path", - "value" - ] - } - ] + "baseRole": { + "type": "string", + "description": "The base role definition name", + "example": "VIEWER" + }, + "connectionId": { + "type": "string", + "format": "uuid", + "description": "Connection this role applies to" + }, + "from": { + "$ref": "#/components/schemas/RoleOrigin" + }, + "modelId": { + "type": "string", + "format": "uuid", + "description": "Model this role applies to" + }, + "priority": { + "type": "number", + "description": "Priority for role resolution (higher = more permissive)" + }, + "resolved": { + "type": "boolean", + "description": "Whether this is the resolved (effective) role" + }, + "roleName": { + "type": "string", + "description": "The role name (base or custom)", + "example": "VIEWER" + } + }, + "required": [ + "baseRole", + "connectionId", + "from", + "modelId", + "priority", + "resolved", + "roleName" + ] + }, + "RoleOrigin": { + "oneOf": [ + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "USER" + ], + "description": "Role assigned directly to user" + } }, - "description": "List of SCIM patch operations" + "required": [ + "type" + ] + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "ORG" + ], + "description": "Role inherited from organization" + } + }, + "required": [ + "type" + ] }, - "schemas": { - "type": "array", - "items": { - "type": "string", - "enum": [ - "urn:ietf:params:scim:api:messages:2.0:PatchOp" - ] + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "BASE" + ], + "description": "Connection base role" + } }, - "description": "SCIM schema URIs" - } - }, - "required": [ - "Operations", - "schemas" - ] - }, - "DocumentExportResponse": { - "type": "object", - "properties": { - "dashboard": { - "description": "Dashboard configuration and layout" + "required": [ + "type" + ] }, - "document": { + { "type": "object", "properties": { - "ephemeral": { - "type": "string" + "depth": { + "type": "number", + "description": "Nesting depth of the group" + }, + "miniUuid": { + "type": "string", + "description": "Short identifier of the group", + "example": "abc123" }, "name": { - "type": "string" + "type": "string", + "description": "Name of the group", + "example": "Engineering Team" + }, + "type": { + "type": "string", + "enum": [ + "GROUP" + ], + "description": "Role inherited from group membership" } }, "required": [ - "name" + "depth", + "miniUuid", + "name", + "type" ] + } + ], + "description": "Origin of this role assignment" + }, + "UsersAssignModelRoleResponse": { + "type": "object", + "properties": { + "connectionId": { + "type": "string", + "format": "uuid", + "description": "The connection ID for this role assignment" }, - "exportVersion": { - "type": "string" - }, - "fileUploads": { - "type": "object", - "additionalProperties": {} + "membershipId": { + "type": "string", + "format": "uuid", + "description": "The user membership ID" }, - "queryModels": { - "type": "object", - "additionalProperties": {} + "modelId": { + "type": "string", + "format": "uuid", + "description": "The model ID for this role assignment" }, - "workbookModel": {} + "roleName": { + "type": "string", + "description": "The assigned role name", + "example": "VIEWER" + } }, "required": [ - "document", - "exportVersion", - "queryModels" + "connectionId", + "membershipId", + "modelId", + "roleName" ] }, - "DocumentImportResponse": { + "UsersAssignModelRoleBody": { "type": "object", "properties": { - "documentId": { + "connectionId": { "type": "string", "format": "uuid", - "description": "ID of the imported document" + "description": "Connection ID for connection-level role assignment. Required if modelId not provided.", + "example": "550e8400-e29b-41d4-a716-446655440000" }, - "identifier": { + "modelId": { "type": "string", - "description": "Document identifier (miniUuid)" + "format": "uuid", + "description": "Model ID for model-level role assignment. Required if connectionId not provided.", + "example": "550e8400-e29b-41d4-a716-446655440000" + }, + "roleName": { + "type": "string", + "minLength": 1, + "description": "Name of the role to assign (base or custom role)", + "example": "VIEWER" } }, "required": [ - "documentId", - "identifier" + "roleName" ] }, - "DocumentImportBody": { + "UsersListEmailOnlyResponse": { "type": "object", "properties": { - "baseModelId": { - "type": "string", - "format": "uuid", - "description": "Base model ID for the imported document" - }, - "dashboard": { - "description": "Dashboard export data" + "pageInfo": { + "$ref": "#/components/schemas/PageInfo" }, - "document": { - "type": "object", - "properties": { - "ephemeral": { - "type": "string" + "records": { + "type": "array", + "items": { + "type": "object", + "properties": { + "email": { + "type": "string", + "description": "User email address", + "example": "user@example.com" + }, + "user_attributes": { + "type": "object", + "additionalProperties": {}, + "description": "User attributes as key-value pairs" + }, + "user_id": { + "type": "string", + "format": "uuid", + "description": "User ID" + } }, - "name": { - "type": "string" - } - }, - "required": [ - "name" - ] - }, - "exportVersion": { + "required": [ + "email", + "user_attributes", + "user_id" + ] + } + } + }, + "required": [ + "pageInfo", + "records" + ] + }, + "UsersCreateEmailOnlyResponse": { + "type": "object", + "properties": { + "email": { "type": "string", - "enum": [ - "0.1" - ] - }, - "fileUploads": { - "type": "object", - "additionalProperties": {} - }, - "folderPath": { - "type": "string" + "format": "email", + "description": "Email address of the created user", + "example": "user@example.com" }, - "identifier": { - "type": "string" + "userId": { + "type": "string", + "format": "uuid", + "description": "ID of the created user" + } + }, + "required": [ + "email", + "userId" + ] + }, + "UsersCreateEmailOnlyBody": { + "type": "object", + "properties": { + "email": { + "type": "string", + "format": "email", + "description": "Email address for the user", + "example": "user@example.com" }, - "queryModels": { + "userAttributes": { "type": "object", - "additionalProperties": {} - }, - "workbookModel": {} + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "type": "null" + } + ] + }, + "description": "Optional user attributes as key-value pairs" + } + }, + "required": [ + "email" + ] + }, + "UsersCreateEmailOnlyBulkResponse": { + "type": "object", + "properties": { + "results": { + "type": "array", + "items": { + "type": "object", + "properties": { + "email": { + "type": "string", + "format": "email", + "description": "Email address of the created user", + "example": "user@example.com" + }, + "userId": { + "type": "string", + "format": "uuid", + "description": "ID of the created user" + } + }, + "required": [ + "email", + "userId" + ] + }, + "description": "Results for each created user" + } }, "required": [ - "baseModelId", - "document", - "exportVersion", - "queryModels" + "results" ] }, - "UserAttributesListResponse": { + "UsersCreateEmailOnlyBulkBody": { "type": "object", "properties": { - "records": { + "users": { "type": "array", "items": { "type": "object", "properties": { - "default_value": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "array", - "items": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - } - ] - } - }, - { - "type": "null" - } - ], - "description": "Default value applied when no user-specific value is set. When multiple_values is true, this is an array. Null if no default is configured.", - "example": "us-east" - }, - "description": { - "type": [ - "string", - "null" - ], - "description": "Human-readable description of the attribute and its purpose", - "example": "User region for row-level security filtering" - }, - "id": { - "type": "string", - "description": "Unique identifier for custom attributes. Empty string for system-defined attributes.", - "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" - }, - "label": { - "type": "string", - "description": "Display name shown in the Omni UI", - "example": "Region" - }, - "multiple_values": { - "type": "boolean", - "description": "Whether the attribute accepts an array of values. When true, default_value and user-specific values are arrays.", - "example": false - }, - "name": { + "email": { "type": "string", - "description": "Reference name used in model SQL and in embed SSO URL parameters", - "example": "region" - }, - "system": { - "type": "boolean", - "description": "System-defined attributes (e.g. omni_user_id, omni_user_email) are built-in and read-only. Custom attributes have system=false.", - "example": false + "format": "email", + "description": "Email address for the user", + "example": "user@example.com" }, - "type": { - "type": "string", - "enum": [ - "String", - "Number" - ], - "description": "Data type that determines valid values. String attributes accept text, Number attributes accept numeric values stored as strings for precision.", - "example": "String" + "userAttributes": { + "type": "object", + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "type": "null" + } + ] + }, + "description": "Optional user attributes as key-value pairs" } }, "required": [ - "default_value", - "description", - "id", - "label", - "multiple_values", - "name", - "system", - "type" + "email" ] }, - "description": "All user attribute definitions in the organization, including both system-defined and custom attributes" + "minItems": 1, + "maxItems": 20, + "description": "Array of users to create (1-20 users)" } }, "required": [ - "records" + "users" ] }, - "UploadsListResponse": { + "UserGroupsGetModelRolesResponse": { "type": "object", "properties": { - "pageInfo": { - "$ref": "#/components/schemas/PageInfo" - }, - "records": { + "results": { "type": "array", "items": { - "$ref": "#/components/schemas/Upload" - } + "$ref": "#/components/schemas/UserGroupRoleAssignmentResult" + }, + "description": "List of role assignments" + }, + "userGroupId": { + "type": "string", + "description": "The user group short identifier", + "example": "abc123" } }, "required": [ - "pageInfo", - "records" + "results", + "userGroupId" ] }, - "Upload": { + "UserGroupRoleAssignmentResult": { "type": "object", "properties": { - "connection_id": { + "baseRole": { + "type": "string", + "description": "The base role definition name", + "example": "VIEWER" + }, + "connectionId": { "type": "string", "format": "uuid", - "description": "Connection ID the upload is associated with" + "description": "Connection this role applies to" }, - "created_at": { + "from": { + "$ref": "#/components/schemas/UserGroupRoleOrigin" + }, + "modelId": { "type": "string", - "format": "date-time", - "description": "When the file was uploaded" + "format": "uuid", + "description": "Model this role applies to" }, - "file_name": { + "priority": { + "type": "number", + "description": "Priority for role resolution (higher = more permissive)" + }, + "roleName": { "type": "string", - "description": "Original file name", - "example": "users.csv" + "description": "The role name (base or custom)", + "example": "VIEWER" + } + }, + "required": [ + "baseRole", + "connectionId", + "from", + "modelId", + "priority", + "roleName" + ] + }, + "UserGroupRoleOrigin": { + "type": "object", + "properties": { + "depth": { + "type": "number", + "description": "Nesting depth of the group (0 for direct assignment)" }, - "id": { + "miniUuid": { "type": "string", - "format": "uuid", - "description": "Unique identifier for the upload" + "description": "Short identifier of the group", + "example": "abc123" }, - "in_db_as_table_name": { - "type": [ - "string", - "null" - ], - "description": "Database table name if uploaded to database scratch schema" + "name": { + "type": "string", + "description": "Name of the group", + "example": "Engineering Team" }, - "model_id": { - "type": [ - "string", - "null" + "type": { + "type": "string", + "enum": [ + "GROUP" ], + "description": "Role assigned to group" + } + }, + "required": [ + "depth", + "miniUuid", + "name", + "type" + ], + "description": "Origin of this role assignment" + }, + "UserGroupsAssignModelRoleResponse": { + "type": "object", + "properties": { + "connectionId": { + "type": "string", "format": "uuid", - "description": "Model ID the upload is associated with (inferred from connection's shared model if not explicitly set)" - }, - "size_bytes": { - "type": [ - "number", - "null" - ], - "description": "File size in bytes" + "description": "The connection ID for this role assignment" }, - "updated_at": { + "modelId": { "type": "string", - "format": "date-time", - "description": "Last update timestamp" + "format": "uuid", + "description": "The model ID for this role assignment" }, - "uploaded_by_user": { - "type": [ - "object", - "null" - ], - "properties": { - "id": { - "type": "string", - "format": "uuid", - "description": "User ID of the uploader" - }, - "name": { - "type": "string", - "description": "Name of the user who uploaded the file" - } - }, - "required": [ - "id", - "name" - ], - "description": "User who uploaded the file" + "roleName": { + "type": "string", + "description": "The assigned role name", + "example": "VIEWER" }, - "view_name": { + "userGroupId": { "type": "string", - "description": "View name associated with the upload" + "description": "The user group short identifier", + "example": "abc123" } }, "required": [ - "connection_id", - "created_at", - "file_name", - "id", - "in_db_as_table_name", - "model_id", - "size_bytes", - "updated_at", - "uploaded_by_user", - "view_name" + "connectionId", + "modelId", + "roleName", + "userGroupId" ] }, - "UploadCreateResponse": { + "UserGroupsAssignModelRoleBody": { "type": "object", "properties": { - "fileName": { + "connectionId": { "type": "string", - "description": "Original file name", - "example": "users.csv" + "format": "uuid", + "description": "Connection ID for connection-level role assignment. Required if modelId not provided.", + "example": "550e8400-e29b-41d4-a716-446655440000" }, - "id": { + "modelId": { "type": "string", "format": "uuid", - "description": "Unique identifier for the upload" + "description": "Model ID for model-level role assignment. Required if connectionId not provided.", + "example": "550e8400-e29b-41d4-a716-446655440000" }, - "inDbAsTableName": { + "roleName": { "type": "string", - "description": "Database table name in the scratch schema" + "minLength": 1, + "description": "Name of the role to assign (base or custom role)", + "example": "VIEWER" + } + }, + "required": [ + "roleName" + ] + } + }, + "parameters": {} + }, + "paths": { + "/api/v1/ai/generate-query": { + "post": { + "description": "Generate an Omni semantic query from a natural language prompt. Optionally executes the generated query and returns results. The AI analyzes the prompt, selects appropriate fields and filters from the model, and constructs a query. Requires the querier role on the target model.", + "operationId": "aiGenerateQuery", + "summary": "Generate query from natural language", + "tags": [ + "AI" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AiGenerateQueryBody" + } + } + } + }, + "responses": { + "200": { + "description": "Query generated successfully. If runQuery is true (default), includes execution results. Check the error field — a 200 response may still contain a partial error if the query was generated but execution failed. When the organization is over its AI downgrade threshold the response also carries `downgradedModelTier` naming the cheaper tier the query was generated with.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AiGenerateQueryResponse" + } + } + } }, - "modelId": { - "type": "string", - "format": "uuid", - "description": "Model ID the view was created in" + "400": { + "description": "Invalid request. The prompt may be missing, the modelId may be invalid, or the AI was unable to generate a query for the given prompt.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError400" + } + } + } + }, + "401": { + "description": "Missing or invalid API key.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError401" + } + } + } + }, + "402": { + "description": "AI is unavailable because the organization is over its AI credit limit. The body carries the stable reason code `shutoff`.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AiCreditShutoffError" + } + } + } + }, + "403": { + "description": "Insufficient permissions. Requires the querier role on the target model and AI query generation must be enabled for the organization.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError403" + } + } + } + }, + "404": { + "description": "The specified model or topic was not found in the organization.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError404" + } + } + } + }, + "500": { + "description": "AI service error." + } + } + } + }, + "/api/v1/ai/pick-topic": { + "post": { + "description": "Analyze a natural language prompt and determine which topic in the model is the best fit for answering the question. Useful as a preprocessing step before calling generate-query or submitting an AI job, especially when the user's question could relate to multiple topics.", + "operationId": "aiPickTopic", + "summary": "Pick the best topic for a prompt", + "tags": [ + "AI" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AiPickTopicBody" + } + } + } + }, + "responses": { + "200": { + "description": "Topic selected successfully. The returned topicId can be used as the topicName parameter in other AI endpoints.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AiPickTopicResponse" + } + } + } + }, + "400": { + "description": "Invalid request body. The prompt or modelId may be missing or malformed.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError400" + } + } + } + }, + "401": { + "description": "Missing or invalid API key.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError401" + } + } + } + }, + "403": { + "description": "Insufficient permissions. Requires the querier role on the target model and AI must be enabled for the organization.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError403" + } + } + } + }, + "404": { + "description": "The specified model was not found, or no accessible topics exist in the model.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError404" + } + } + } + }, + "500": { + "description": "AI service error." + } + } + } + }, + "/api/v1/ai/search-omni-docs": { + "post": { + "description": "Search the Omni documentation using AI to answer questions about Omni features, configuration, modeling, dashboards, and more. Sends a natural language question and returns a synthesized answer with source links to the relevant documentation pages.", + "operationId": "aiSearchOmniDocs", + "summary": "Search Omni documentation", + "tags": [ + "AI" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AiSearchOmniDocsBody" + } + } + } + }, + "responses": { + "200": { + "description": "Documentation search completed successfully. Returns a synthesized answer with source links.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AiSearchOmniDocsResponse" + } + } + } }, - "rowCount": { - "type": "integer", - "description": "Number of rows in the uploaded file" + "400": { + "description": "Invalid request. The question may be missing or exceed the 2000 character limit.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError400" + } + } + } }, - "truncated": { - "type": "boolean", - "description": "Whether the file was truncated due to row limit" + "401": { + "description": "Missing or invalid API key.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError401" + } + } + } }, - "viewCreated": { - "type": "boolean", - "description": "Whether a view was created in the model" + "403": { + "description": "Omni Agent is not enabled for this organization.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError403" + } + } + } }, - "viewName": { - "type": "string", - "description": "Name of the view created" + "500": { + "description": "AI service error." + } + } + } + }, + "/api/v1/ai/jobs": { + "post": { + "description": "Submit a new AI job for asynchronous execution. The AI will analyze the prompt, generate and execute queries against the specified model, and produce a summarized answer. Jobs are processed by a background worker and typically complete within 15–60 seconds. Use GET /api/v1/ai/jobs/{jobId} to poll for status, or configure a webhookUrl to receive a notification when the job completes. Optionally continue an existing conversation by providing a conversationId.", + "operationId": "aiJobSubmit", + "summary": "Submit an AI job", + "tags": [ + "AI" + ], + "parameters": [ + { + "schema": { + "type": "string", + "format": "uuid", + "description": "Target user membership ID (for org-scoped API keys)" + }, + "required": false, + "description": "Target user membership ID (for org-scoped API keys)", + "name": "userId", + "in": "query" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AiJobSubmitBody" + } + } } }, - "required": [ - "fileName", - "id", - "inDbAsTableName", - "modelId", - "rowCount", - "truncated", - "viewCreated", - "viewName" - ] - }, - "UploadCreateBody": { - "type": "object", - "properties": { - "branchId": { - "type": "string", - "format": "uuid", - "description": "UUID of the branch to create the view in (mutually exclusive with branchName)" + "responses": { + "201": { + "description": "Job created and queued for execution. Use the returned jobId to poll for status or retrieve results.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AiJobSubmitResponse" + } + } + } }, - "branchName": { - "type": "string", - "description": "Name of the branch to create the view in (mutually exclusive with branchId)" + "400": { + "description": "Invalid request body. Common causes: missing or empty prompt, invalid UUID for modelId/branchId/conversationId, invalid webhook URL format.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError400" + } + } + } }, - "file": { - "type": "string", - "description": "The CSV file to upload", - "format": "binary" + "401": { + "description": "Missing or invalid API key.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError401" + } + } + } }, - "modelId": { - "type": "string", - "format": "uuid", - "description": "UUID of the model to create the view in" + "403": { + "description": "Insufficient permissions. The AI jobs API must be enabled for the organization, AI query generation must be enabled, and the user must have appropriate model access. User-scoped API keys cannot act on behalf of other users.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError403" + } + } + } }, - "viewName": { - "type": "string", - "description": "Override the view name (defaults to sanitized file name)" + "404": { + "description": "The specified model was not found in the organization, the branchId does not belong to the specified model, or the topicName does not exist in the model (or is excluded by ai_chat_topics restrictions).", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError404" + } + } + } + }, + "409": { + "description": "An active job already exists for the specified conversationId. Wait for the current job to complete before submitting another job to the same conversation.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError409" + } + } + } } - }, - "required": [ - "modelId" - ] - }, - "UploadDeleteResponse": { - "type": "object", - "properties": { - "success": { - "type": "boolean", - "description": "Whether the deletion was successful" + } + } + }, + "/api/v1/ai/jobs/{jobId}": { + "get": { + "description": "Get the current status of an AI job, including its state, progress information, and result summary. The response fields vary by state — for example, progress is only present during EXECUTING, and resultSummary is only present when COMPLETE. Poll this endpoint every 2–5 seconds until the job reaches a terminal state (COMPLETE, FAILED, or CANCELLED).", + "operationId": "aiJobStatus", + "summary": "Get AI job status", + "tags": [ + "AI" + ], + "parameters": [ + { + "schema": { + "type": "string", + "format": "uuid", + "description": "The unique identifier of the AI job", + "example": "123e4567-e89b-12d3-a456-426614174000" + }, + "required": true, + "description": "The unique identifier of the AI job", + "name": "jobId", + "in": "path" } - }, - "required": [ - "success" - ] - }, - "UsersGetModelRolesResponse": { - "type": "object", - "properties": { - "membershipId": { - "type": "string", - "format": "uuid", - "description": "The user membership ID" + ], + "responses": { + "200": { + "description": "Job status retrieved successfully. Check the state field to determine if the job is still running or has reached a terminal state.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AiJobStatusResponse" + } + } + } }, - "results": { - "type": "array", - "items": { - "$ref": "#/components/schemas/RoleAssignmentResult" + "400": { + "description": "Invalid job ID format. Must be a valid UUID.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError400" + } + } + } + }, + "401": { + "description": "Missing or invalid API key.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError401" + } + } + } + }, + "404": { + "description": "Job not found. The job may not exist or may belong to a different organization.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError404" + } + } + } + } + } + } + }, + "/api/v1/ai/jobs/{jobId}/cancel": { + "post": { + "description": "Request cancellation of an AI job. This endpoint is idempotent — calling it on an already-cancelled or completed job returns success with the current state. For QUEUED jobs, cancellation is immediate. For EXECUTING jobs, the worker will stop after completing its current iteration. Jobs in DELIVERING state cannot be cancelled as they are already finalizing results. Only the job owner or organization admins can cancel jobs.", + "operationId": "aiJobCancel", + "summary": "Cancel an AI job", + "tags": [ + "AI" + ], + "parameters": [ + { + "schema": { + "type": "string", + "format": "uuid", + "description": "The unique identifier of the AI job", + "example": "123e4567-e89b-12d3-a456-426614174000" }, - "description": "List of role assignments" + "required": true, + "description": "The unique identifier of the AI job", + "name": "jobId", + "in": "path" } - }, - "required": [ - "membershipId", - "results" - ] - }, - "RoleAssignmentResult": { - "type": "object", - "properties": { - "baseRole": { - "type": "string", - "description": "The base role definition name", - "example": "VIEWER" - }, - "connectionId": { - "type": "string", - "format": "uuid", - "description": "Connection this role applies to" + ], + "responses": { + "200": { + "description": "Cancellation request processed. The state field indicates the job's state after the attempt — CANCELLED if successful, or the current terminal state if the job had already completed.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AiJobCancelResponse" + } + } + } }, - "from": { - "$ref": "#/components/schemas/RoleOrigin" + "400": { + "description": "Invalid job ID format. Must be a valid UUID.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError400" + } + } + } }, - "modelId": { - "type": "string", - "format": "uuid", - "description": "Model this role applies to" + "401": { + "description": "Missing or invalid API key.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError401" + } + } + } }, - "priority": { - "type": "number", - "description": "Priority for role resolution (higher = more permissive)" + "403": { + "description": "Permission denied. Only the job owner or organization admins can cancel jobs.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError403" + } + } + } }, - "resolved": { - "type": "boolean", - "description": "Whether this is the resolved (effective) role" + "404": { + "description": "Job not found. The job may not exist or may belong to a different organization.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError404" + } + } + } }, - "roleName": { - "type": "string", - "description": "The role name (base or custom)", - "example": "VIEWER" + "409": { + "description": "Concurrent modification conflict. The job state was changed by another request. Retry the cancellation.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError409" + } + } + } } - }, - "required": [ - "baseRole", - "connectionId", - "from", - "modelId", - "priority", - "resolved", - "roleName" - ] - }, - "RoleOrigin": { - "oneOf": [ + } + } + }, + "/api/v1/ai/jobs/{jobId}/result": { + "get": { + "description": "Retrieve the full result of a completed AI job, including all actions taken by the AI (queries generated, data retrieved) and the final summarized answer. Results are only available for jobs in COMPLETE state and are retained for 14 days after completion. The response is streamed directly from storage.", + "operationId": "aiJobResult", + "summary": "Get AI job result", + "tags": [ + "AI" + ], + "parameters": [ { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "USER" - ], - "description": "Role assigned directly to user" - } + "schema": { + "type": "string", + "format": "uuid", + "description": "The unique identifier of the AI job", + "example": "123e4567-e89b-12d3-a456-426614174000" }, - "required": [ - "type" - ] + "required": true, + "description": "The unique identifier of the AI job", + "name": "jobId", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Full job result including the AI's actions, query results (with CSV data), and the final Markdown-formatted answer.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AiJobResultResponse" + } + } + } }, - { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "ORG" - ], - "description": "Role inherited from organization" + "400": { + "description": "Invalid job ID format. Must be a valid UUID.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError400" + } } - }, - "required": [ - "type" - ] + } }, - { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "BASE" - ], - "description": "Connection base role" + "401": { + "description": "Missing or invalid API key.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError401" + } } - }, - "required": [ - "type" - ] + } }, - { - "type": "object", - "properties": { - "depth": { - "type": "number", - "description": "Nesting depth of the group" - }, - "miniUuid": { - "type": "string", - "description": "Short identifier of the group", - "example": "abc123" - }, - "name": { - "type": "string", - "description": "Name of the group", - "example": "Engineering Team" - }, - "type": { - "type": "string", - "enum": [ - "GROUP" - ], - "description": "Role inherited from group membership" + "404": { + "description": "Job not found, not in COMPLETE state, or result is no longer available (results are retained for 14 days).", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError404" + } } + } + } + } + } + }, + "/api/v1/ai/jobs/{jobId}/vis": { + "get": { + "description": "Render the visualization from a completed AI job as a PNG image. The endpoint extracts the visualization configuration from the job result, loads Arrow IPC data, and renders it server-side using Vega. For style-only follow-ups (e.g., \"make it a bar chart\"), the endpoint walks back through previous jobs in the conversation to find the original query data.", + "operationId": "aiJobVisualization", + "summary": "Render AI job visualization", + "tags": [ + "AI" + ], + "parameters": [ + { + "schema": { + "type": "string", + "format": "uuid", + "description": "The unique identifier of the AI job", + "example": "123e4567-e89b-12d3-a456-426614174000" }, - "required": [ - "depth", - "miniUuid", - "name", - "type" - ] + "required": true, + "description": "The unique identifier of the AI job", + "name": "jobId", + "in": "path" } ], - "description": "Origin of this role assignment" - }, - "UsersAssignModelRoleResponse": { - "type": "object", - "properties": { - "connectionId": { - "type": "string", - "format": "uuid", - "description": "The connection ID for this role assignment" - }, - "membershipId": { - "type": "string", - "format": "uuid", - "description": "The user membership ID" + "responses": { + "200": { + "description": "Visualization rendered as a PNG image. The Content-Type header is image/png.", + "content": { + "image/png": { + "schema": { + "format": "binary", + "type": "string" + } + } + } }, - "modelId": { - "type": "string", - "format": "uuid", - "description": "The model ID for this role assignment" + "400": { + "description": "Invalid job ID format. Must be a valid UUID.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError400" + } + } + } }, - "roleName": { - "type": "string", - "description": "The assigned role name", - "example": "VIEWER" - } - }, - "required": [ - "connectionId", - "membershipId", - "modelId", - "roleName" - ] - }, - "UsersAssignModelRoleBody": { - "type": "object", - "properties": { - "connectionId": { - "type": "string", - "format": "uuid", - "description": "Connection ID for connection-level role assignment. Required if modelId not provided.", - "example": "550e8400-e29b-41d4-a716-446655440000" + "401": { + "description": "Missing or invalid API key.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError401" + } + } + } }, - "modelId": { - "type": "string", - "format": "uuid", - "description": "Model ID for model-level role assignment. Required if connectionId not provided.", - "example": "550e8400-e29b-41d4-a716-446655440000" + "404": { + "description": "Job not found, not in COMPLETE state, or the apiAiVis feature flag is not enabled.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError404" + } + } + } }, - "roleName": { - "type": "string", - "minLength": 1, - "description": "Name of the role to assign (base or custom role)", - "example": "VIEWER" + "422": { + "description": "The job completed but cannot be rendered as a visualization. Common causes: no visualization action in the job result, no Arrow IPC data available, missing summary fields, or the chart type is not renderable as an image (e.g., tables, KPIs).", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError422" + } + } + } } - }, - "required": [ - "roleName" - ] - }, - "UsersListEmailOnlyResponse": { - "type": "object", - "properties": { - "pageInfo": { - "$ref": "#/components/schemas/PageInfo" + } + } + }, + "/api/v1/ai/branding": { + "get": { + "description": "Returns the organization's AI helper branding — display name, optional custom logo URL, and copy used on AI helper landing surfaces (headline, body, prompt placeholder). Falls back to Omni's defaults when the organization hasn't configured custom branding, so the response is always populated. Used by client apps (iOS, embeds) to render the AI helper with the org's chosen identity.", + "operationId": "aiBranding", + "summary": "Get AI helper branding", + "tags": [ + "AI" + ], + "responses": { + "200": { + "description": "AI branding retrieved successfully.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AiBrandingResponse" + } + } + } }, - "records": { - "type": "array", - "items": { - "type": "object", - "properties": { - "email": { - "type": "string", - "description": "User email address", - "example": "user@example.com" - }, - "user_attributes": { - "type": "object", - "additionalProperties": {}, - "description": "User attributes as key-value pairs" - }, - "user_id": { - "type": "string", - "format": "uuid", - "description": "User ID" + "401": { + "description": "Missing or invalid API key.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError401" } - }, - "required": [ - "email", - "user_attributes", - "user_id" - ] + } } - } - }, - "required": [ - "pageInfo", - "records" - ] - }, - "UsersCreateEmailOnlyResponse": { - "type": "object", - "properties": { - "email": { - "type": "string", - "format": "email", - "description": "Email address of the created user", - "example": "user@example.com" }, - "userId": { - "type": "string", - "format": "uuid", - "description": "ID of the created user" + "403": { + "description": "AI access is required to view AI helper branding (no model in the org grants USE_AI to the caller).", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError403" + } + } + } } - }, - "required": [ - "email", - "userId" - ] - }, - "UsersCreateEmailOnlyBody": { - "type": "object", - "properties": { - "email": { - "type": "string", - "format": "email", - "description": "Email address for the user", - "example": "user@example.com" + } + } + }, + "/api/v1/ai/conversations": { + "get": { + "description": "List the user's recent AI conversations, ordered by most-recent activity. Each record includes the conversation id (pass it back as `conversationId` on subsequent /api/v1/ai/jobs submissions to continue the thread), an optional name, and a one-line summary of the most recent prompt for display. Paginated via opaque `pageInfo.nextCursor` — pass it back as `cursor` to fetch the next page.", + "operationId": "aiConversationsList", + "summary": "List AI conversations", + "tags": [ + "AI" + ], + "parameters": [ + { + "schema": { + "type": "string", + "description": "Cursor for pagination (from previous response nextCursor)", + "example": "eyJpZCI6IjEyMzQ1In0" + }, + "required": false, + "description": "Cursor for pagination (from previous response nextCursor)", + "name": "cursor", + "in": "query" }, - "userAttributes": { - "type": "object", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - }, - { - "type": "null" - } - ] + { + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 100, + "default": 20, + "description": "Number of results per page (1-100, integer)", + "example": 20 + }, + "required": false, + "description": "Number of results per page (1-100, integer)", + "name": "pageSize", + "in": "query" + }, + { + "schema": { + "type": "string", + "format": "uuid", + "description": "Target user membership ID (for org-scoped API keys)" }, - "description": "Optional user attributes as key-value pairs" + "required": false, + "description": "Target user membership ID (for org-scoped API keys)", + "name": "userId", + "in": "query" } - }, - "required": [ - "email" - ] - }, - "UsersCreateEmailOnlyBulkResponse": { - "type": "object", - "properties": { - "results": { - "type": "array", - "items": { - "type": "object", - "properties": { - "email": { - "type": "string", - "format": "email", - "description": "Email address of the created user", - "example": "user@example.com" - }, - "userId": { - "type": "string", - "format": "uuid", - "description": "ID of the created user" + ], + "responses": { + "200": { + "description": "Paginated list of conversations.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AiConversationsListResponse" } - }, - "required": [ - "email", - "userId" - ] - }, - "description": "Results for each created user" - } - }, - "required": [ - "results" - ] - }, - "UsersCreateEmailOnlyBulkBody": { - "type": "object", - "properties": { - "users": { - "type": "array", - "items": { - "type": "object", - "properties": { - "email": { - "type": "string", - "format": "email", - "description": "Email address for the user", - "example": "user@example.com" - }, - "userAttributes": { - "type": "object", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - }, - { - "type": "null" - } - ] - }, - "description": "Optional user attributes as key-value pairs" + } + } + }, + "401": { + "description": "Missing or invalid API key.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError401" } - }, - "required": [ - "email" - ] - }, - "minItems": 1, - "maxItems": 20, - "description": "Array of users to create (1-20 users)" + } + } + }, + "403": { + "description": "Insufficient permissions.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError403" + } + } + } } - }, - "required": [ - "users" - ] - }, - "UserGroupsGetModelRolesResponse": { - "type": "object", - "properties": { - "results": { - "type": "array", - "items": { - "$ref": "#/components/schemas/UserGroupRoleAssignmentResult" + } + } + }, + "/api/v1/ai/conversations/{conversationId}": { + "get": { + "description": "Return a conversation with its full message history (alternating user / assistant turns). Used by clients (iOS app, embed widgets) to restore a prior conversation in their UI.", + "operationId": "aiConversationDetail", + "summary": "Get AI conversation with messages", + "tags": [ + "AI" + ], + "parameters": [ + { + "schema": { + "type": "string", + "format": "uuid" }, - "description": "List of role assignments" - }, - "userGroupId": { - "type": "string", - "description": "The user group short identifier", - "example": "abc123" + "required": true, + "name": "conversationId", + "in": "path" } - }, - "required": [ - "results", - "userGroupId" - ] - }, - "UserGroupRoleAssignmentResult": { - "type": "object", - "properties": { - "baseRole": { - "type": "string", - "description": "The base role definition name", - "example": "VIEWER" + ], + "responses": { + "200": { + "description": "Conversation with messages in chronological order.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AiConversationDetailResponse" + } + } + } }, - "connectionId": { - "type": "string", - "format": "uuid", - "description": "Connection this role applies to" + "401": { + "description": "Missing or invalid API key.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError401" + } + } + } }, - "from": { - "$ref": "#/components/schemas/UserGroupRoleOrigin" + "403": { + "description": "AI access is required to view chat conversations (no model in the org grants USE_AI to the caller).", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError403" + } + } + } }, - "modelId": { - "type": "string", - "format": "uuid", - "description": "Model this role applies to" + "404": { + "description": "Conversation not found. User-scoped keys also get 404 (not 403) when the conversation exists but belongs to a different user — existence of another user's conversations is not disclosed.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError404" + } + } + } + } + } + } + }, + "/api/v1/api-keys": { + "get": { + "description": "Returns all API tokens in the organization, including organization-level keys, personal access tokens, and MCP OAuth grants. Secrets are never returned. Requires organization admin permissions.", + "operationId": "apiKeysList", + "summary": "List API tokens", + "tags": [ + "API Tokens" + ], + "parameters": [ + { + "schema": { + "type": "string", + "format": "uuid", + "description": "Cursor from the previous response (token UUID)" + }, + "required": false, + "description": "Cursor from the previous response (token UUID)", + "name": "cursor", + "in": "query" + }, + { + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 100, + "default": 20, + "description": "Number of results per page (1-100, integer)", + "example": 20 + }, + "required": false, + "description": "Number of results per page (1-100, integer)", + "name": "pageSize", + "in": "query" + }, + { + "schema": { + "type": "string", + "enum": [ + "asc", + "desc" + ], + "default": "desc", + "description": "Sort direction for results", + "example": "desc" + }, + "required": false, + "description": "Sort direction for results", + "name": "sortDirection", + "in": "query" }, - "priority": { - "type": "number", - "description": "Priority for role resolution (higher = more permissive)" + { + "schema": { + "type": "string", + "enum": [ + "createdAt", + "name" + ], + "default": "createdAt" + }, + "required": false, + "name": "sortField", + "in": "query" }, - "roleName": { - "type": "string", - "description": "The role name (base or custom)", - "example": "VIEWER" + { + "schema": { + "type": "string", + "enum": [ + "organization", + "personal", + "mcp" + ], + "description": "Filter by API token type. When omitted, all types are returned.", + "example": "personal" + }, + "required": false, + "description": "Filter by API token type. When omitted, all types are returned.", + "name": "type", + "in": "query" } - }, - "required": [ - "baseRole", - "connectionId", - "from", - "modelId", - "priority", - "roleName" - ] - }, - "UserGroupRoleOrigin": { - "type": "object", - "properties": { - "depth": { - "type": "number", - "description": "Nesting depth of the group (0 for direct assignment)" + ], + "responses": { + "200": { + "description": "Paginated list of API tokens", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiKeyListResponse" + } + } + } }, - "miniUuid": { - "type": "string", - "description": "Short identifier of the group", - "example": "abc123" + "400": { + "description": "Invalid query parameters" }, - "name": { - "type": "string", - "description": "Name of the group", - "example": "Engineering Team" + "401": { + "description": "Authentication required" }, - "type": { - "type": "string", - "enum": [ - "GROUP" - ], - "description": "Role assigned to group" + "403": { + "description": "Insufficient permissions" } - }, - "required": [ - "depth", - "miniUuid", - "name", - "type" + } + } + }, + "/api/v1/api-keys/{id}": { + "get": { + "description": "Returns a single API token by id. Requires organization admin permissions.", + "operationId": "apiKeysGet", + "summary": "Get API token", + "tags": [ + "API Tokens" ], - "description": "Origin of this role assignment" - }, - "UserGroupsAssignModelRoleResponse": { - "type": "object", - "properties": { - "connectionId": { - "type": "string", - "format": "uuid", - "description": "The connection ID for this role assignment" - }, - "modelId": { - "type": "string", - "format": "uuid", - "description": "The model ID for this role assignment" + "parameters": [ + { + "schema": { + "type": "string", + "format": "uuid", + "description": "Token UUID", + "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" + }, + "required": true, + "description": "Token UUID", + "name": "id", + "in": "path" + } + ], + "responses": { + "200": { + "description": "The requested API token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiKey" + } + } + } }, - "roleName": { - "type": "string", - "description": "The assigned role name", - "example": "VIEWER" + "400": { + "description": "Malformed `id` (must be a UUID)" }, - "userGroupId": { - "type": "string", - "description": "The user group short identifier", - "example": "abc123" - } - }, - "required": [ - "connectionId", - "modelId", - "roleName", - "userGroupId" - ] - }, - "UserGroupsAssignModelRoleBody": { - "type": "object", - "properties": { - "connectionId": { - "type": "string", - "format": "uuid", - "description": "Connection ID for connection-level role assignment. Required if modelId not provided.", - "example": "550e8400-e29b-41d4-a716-446655440000" + "401": { + "description": "Authentication required" }, - "modelId": { - "type": "string", - "format": "uuid", - "description": "Model ID for model-level role assignment. Required if connectionId not provided.", - "example": "550e8400-e29b-41d4-a716-446655440000" + "403": { + "description": "Insufficient permissions" }, - "roleName": { - "type": "string", - "minLength": 1, - "description": "Name of the role to assign (base or custom role)", - "example": "VIEWER" + "404": { + "description": "Token not found in this organization" } - }, - "required": [ - "roleName" - ] - } - }, - "parameters": {} - }, - "paths": { - "/api/v1/ai/generate-query": { - "post": { - "description": "Generate an Omni semantic query from a natural language prompt. Optionally executes the generated query and returns results. The AI analyzes the prompt, selects appropriate fields and filters from the model, and constructs a query. Requires the querier role on the target model.", - "operationId": "aiGenerateQuery", - "summary": "Generate query from natural language", + } + }, + "put": { + "description": "Enables or disables an API token. Requires organization admin permissions.", + "operationId": "apiKeysUpdate", + "summary": "Enable or disable an API token", "tags": [ - "AI" + "API Tokens" + ], + "parameters": [ + { + "schema": { + "type": "string", + "format": "uuid", + "description": "Token UUID", + "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" + }, + "required": true, + "description": "Token UUID", + "name": "id", + "in": "path" + } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/AiGenerateQueryBody" + "$ref": "#/components/schemas/ApiKeyUpdateBody" + } + } + } + }, + "responses": { + "200": { + "description": "The updated API token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiKey" + } } } + }, + "400": { + "description": "Invalid body, malformed `id`, or missing/malformed `Authorization` header" + }, + "403": { + "description": "Invalid bearer token, or caller lacks organization admin permissions" + }, + "404": { + "description": "Token not found in this organization" + }, + "405": { + "description": "Method not allowed" + } + } + }, + "delete": { + "description": "Revokes an API token by permanently deleting it. Works for all token types. Requires organization admin permissions.", + "operationId": "apiKeysDelete", + "summary": "Revoke an API token", + "tags": [ + "API Tokens" + ], + "parameters": [ + { + "schema": { + "type": "string", + "format": "uuid", + "description": "Token UUID", + "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" + }, + "required": true, + "description": "Token UUID", + "name": "id", + "in": "path" } - }, + ], "responses": { "200": { - "description": "Query generated successfully. If runQuery is true (default), includes execution results. Check the error field — a 200 response may still contain a partial error if the query was generated but execution failed.", + "description": "The token was revoked", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/AiGenerateQueryResponse" + "$ref": "#/components/schemas/ApiKeyDeleteResponse" } } } }, "400": { - "description": "Invalid request. The prompt may be missing, the modelId may be invalid, or the AI was unable to generate a query for the given prompt.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiError400" - } - } - } - }, - "401": { - "description": "Missing or invalid API key.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiError401" - } - } - } + "description": "Malformed `id`, or missing/malformed `Authorization` header" }, "403": { - "description": "Insufficient permissions. Requires the querier role on the target model and AI query generation must be enabled for the organization.", + "description": "Invalid bearer token, or caller lacks organization admin permissions" + }, + "404": { + "description": "Token not found in this organization" + }, + "405": { + "description": "Method not allowed" + } + } + } + }, + "/api/v1/connections": { + "get": { + "operationId": "connectionsList", + "summary": "List connections", + "tags": [ + "Connections" + ], + "parameters": [ + { + "schema": { + "type": "string", + "description": "Filter by database name (case-insensitive contains)", + "example": "analytics" + }, + "required": false, + "description": "Filter by database name (case-insensitive contains)", + "name": "database", + "in": "query" + }, + { + "schema": { + "type": "string", + "description": "Filter by dialect(s). Comma-separated list for multiple values", + "example": "snowflake,bigquery" + }, + "required": false, + "description": "Filter by dialect(s). Comma-separated list for multiple values", + "name": "dialect", + "in": "query" + }, + { + "schema": { + "type": "boolean", + "description": "Include soft-deleted connections in results", + "example": false + }, + "required": false, + "description": "Include soft-deleted connections in results", + "name": "includeDeleted", + "in": "query" + }, + { + "schema": { + "type": "string", + "description": "Filter by connection name (case-insensitive contains)", + "example": "Production" + }, + "required": false, + "description": "Filter by connection name (case-insensitive contains)", + "name": "name", + "in": "query" + }, + { + "schema": { + "type": "string", + "enum": [ + "asc", + "desc" + ], + "description": "Sort direction", + "example": "desc" + }, + "required": false, + "description": "Sort direction", + "name": "sortDirection", + "in": "query" + }, + { + "schema": { + "type": "string", + "enum": [ + "database", + "dialect", + "name" + ], + "description": "Field to sort by", + "example": "name" + }, + "required": false, + "description": "Field to sort by", + "name": "sortField", + "in": "query" + } + ], + "responses": { + "200": { + "description": "List of connections", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ApiError403" + "type": "object", + "properties": { + "connections": { + "type": "array", + "items": { + "type": "object", + "properties": { + "baseRole": { + "type": [ + "string", + "null" + ], + "description": "Default role for users on this connection", + "example": "QUERIER" + }, + "branchConnectionEnvironmentOverridesUserAttr": { + "type": [ + "boolean", + "null" + ], + "description": "Whether branch environments override user attributes", + "example": false + }, + "createdAt": { + "type": "string", + "description": "Timestamp when connection was created (ISO 8601)", + "example": "2024-01-15T10:30:00Z" + }, + "database": { + "type": [ + "string", + "null" + ], + "description": "Database name", + "example": "analytics_db" + }, + "defaultSchema": { + "type": [ + "string", + "null" + ], + "description": "Default schema for the connection", + "example": "public" + }, + "deletedAt": { + "type": [ + "string", + "null" + ], + "description": "Timestamp when connection was deleted (ISO 8601)", + "example": null + }, + "dialect": { + "type": "string", + "enum": [ + "snowflake", + "bigquery", + "redshift", + "postgres", + "mysql", + "mariadb", + "databricks", + "databricks_lakebase", + "trino", + "athena", + "duckdb", + "motherduck", + "sqlserver", + "clickhouse", + "singlestore" + ], + "description": "Database dialect type", + "example": "snowflake" + }, + "environmentConnectionSwitchesSchemaModel": { + "type": [ + "boolean", + "null" + ], + "description": "Whether environment connections switch schema model", + "example": false + }, + "id": { + "type": "string", + "format": "uuid", + "description": "Unique connection identifier", + "example": "550e8400-e29b-41d4-a716-446655440000" + }, + "name": { + "type": "string", + "description": "Connection display name", + "example": "Production Snowflake" + }, + "updatedAt": { + "type": "string", + "description": "Timestamp when connection was last updated (ISO 8601)", + "example": "2024-01-15T10:30:00Z" + }, + "userAttributeNameForConnectionEnvironments": { + "type": [ + "string", + "null" + ], + "description": "User attribute name used for connection environments", + "example": "region" + }, + "userAttributeValuesForDefaultEnvironment": { + "type": [ + "array", + "null" + ], + "items": { + "type": "string" + }, + "description": "Default user attribute values for the base environment", + "example": [ + "us-east", + "us-west" + ] + } + }, + "required": [ + "baseRole", + "branchConnectionEnvironmentOverridesUserAttr", + "createdAt", + "database", + "defaultSchema", + "deletedAt", + "dialect", + "environmentConnectionSwitchesSchemaModel", + "id", + "name", + "updatedAt", + "userAttributeNameForConnectionEnvironments", + "userAttributeValuesForDefaultEnvironment" + ], + "description": "Connection object", + "title": "Connection" + }, + "description": "List of connections" + } + }, + "required": [ + "connections" + ], + "description": "List connections response", + "title": "ConnectionsListResponse" } } } }, - "404": { - "description": "The specified model or topic was not found in the organization.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiError404" - } - } - } + "401": { + "description": "Authentication required" }, - "500": { - "description": "AI service error." + "403": { + "description": "Permission denied - admin role required" } } - } - }, - "/api/v1/ai/pick-topic": { + }, "post": { - "description": "Analyze a natural language prompt and determine which topic in the model is the best fit for answering the question. Useful as a preprocessing step before calling generate-query or submitting an AI job, especially when the user's question could relate to multiple topics.", - "operationId": "aiPickTopic", - "summary": "Pick the best topic for a prompt", + "description": "Create a new database connection. The request body varies by dialect - see dialect-specific documentation for required fields.", + "operationId": "connectionsCreate", + "summary": "Create connection", "tags": [ - "AI" + "Connections" ], "requestBody": { - "required": true, "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/AiPickTopicBody" + "type": "object", + "properties": { + "acceptsLicense": { + "type": "boolean", + "description": "Acceptance of the license terms. Required for Oracle connections.", + "example": true + }, + "allowsUserSpecificTimezones": { + "type": "boolean", + "default": false, + "description": "Whether to allow users to specify their own timezones", + "example": false + }, + "alwaysScopeViewNames": { + "type": "boolean", + "description": "Whether to always include schema (and catalog) prefixes in generated view names, even for tables in the default schema. Defaults to true for dialects that support multiple catalogs, false otherwise.", + "example": true + }, + "authenticationType": { + "type": "string", + "description": "Authentication type. Applicable for BigQuery, MSSQL, Snowflake, Databricks, and Athena.", + "example": "snowflake-password" + }, + "awsRoleArn": { + "type": "string", + "description": "AWS IAM role ARN. Applicable for Athena only.", + "example": "arn:aws:iam::123456789012:role/OmniAthenaRole" + }, + "baseRole": { + "type": "string", + "enum": [ + "NO_ACCESS", + "VIEWER", + "RESTRICTED_QUERIER", + "QUERIER", + "MODELER", + "CONNECTION_ADMIN" + ], + "description": "The default role for users accessing the connection", + "example": "QUERIER" + }, + "database": { + "type": "string", + "description": "The default database/catalog to connect to. For BigQuery, this is the project ID. For Athena, this is the data catalog.", + "example": "analytics_db" + }, + "defaultSchema": { + "type": "string", + "description": "The default schema to use. Required for MSSQL.", + "example": "public" + }, + "dialect": { + "type": "string", + "enum": [ + "athena", + "bigquery", + "clickhouse", + "databricks", + "databricks_lakebase", + "exasol", + "mariadb", + "motherduck", + "mssql", + "mysql", + "oracle", + "postgres", + "redshift", + "sap_hana", + "snowflake", + "starrocks", + "trino" + ], + "description": "The database dialect", + "example": "snowflake" + }, + "enableDbSemanticLayerIntegration": { + "type": "boolean", + "default": false, + "description": "Enable the dialect-native semantic layer integration. Applicable for Snowflake and Databricks.", + "example": false + }, + "enableDbSemanticLayerTopics": { + "type": "boolean", + "default": false, + "description": "Enable the dialect-native semantic layer topics. Applicable for Snowflake and Databricks.", + "example": false + }, + "externalOauthAudience": { + "type": "string", + "description": "External OAuth audience claim. Applicable for Snowflake." + }, + "externalOauthAuthorizationUrl": { + "type": "string", + "format": "uri", + "description": "External OAuth authorization URL (must be HTTPS). Applicable for Snowflake.", + "example": "https://oauth.example.com/authorize" + }, + "externalOauthTokenUrl": { + "type": "string", + "format": "uri", + "description": "External OAuth token URL (must be HTTPS). Applicable for Snowflake.", + "example": "https://oauth.example.com/token" + }, + "host": { + "type": "string", + "description": "The hostname or IP address of the database server. For Snowflake, provide only the account identifier.", + "example": "myaccount" + }, + "hostOverride": { + "type": "string", + "description": "Custom Snowflake host (when not using the account identifier). Mutually exclusive with `host`.", + "example": "myaccount.snowflakecomputing.com" + }, + "includeOtherCatalogs": { + "type": "string", + "description": "Comma-separated list of other catalogs/databases to include. Only applicable for databases that support multi-catalog queries.", + "example": "other_project1,other_project2" + }, + "includeSchemas": { + "type": "string", + "description": "Comma-separated list of schemas to include. Leave empty to include all schemas.", + "example": "public,analytics" + }, + "inferRelationshipsFromColumnNames": { + "type": "boolean", + "default": true, + "description": "Whether to infer relationships from column-name conventions during schema refresh. Defaults to true.", + "example": true + }, + "inferRelationshipsFromForeignKeys": { + "type": "boolean", + "default": false, + "description": "Whether to infer relationships from declared foreign keys during schema refresh. Currently honored for Postgres and Snowflake.", + "example": false + }, + "maxBillingBytes": { + "type": "string", + "description": "Maximum bytes that can be billed for a BigQuery query. Applicable for BigQuery only.", + "example": "1000000000" + }, + "name": { + "type": "string", + "description": "A descriptive name for the connection", + "example": "Production Warehouse" + }, + "oauthClientId": { + "type": "string", + "description": "OAuth client ID for admin schema refresh. Applicable for Snowflake and Databricks." + }, + "oauthClientSecretUnencrypted": { + "type": "string", + "description": "OAuth client secret for admin schema refresh. Applicable for Snowflake and Databricks." + }, + "offloadedSchemas": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ], + "description": "Schemas whose tables should be queried via the offloaded engine. Accepts a comma-separated string or an array of schema names.", + "example": [ + "analytics_archive" + ] + }, + "passwordUnencrypted": { + "type": "string", + "description": "The password to authenticate with. For BigQuery, this must be the JSON service account key file content. For Snowflake with keypair authentication, this can be omitted." + }, + "port": { + "type": "integer", + "description": "The port number for the database connection. Not required for Snowflake, MotherDuck, BigQuery, Databricks, and Athena.", + "example": 5432 + }, + "privateKey": { + "type": "string", + "description": "An RSA key for keypair authentication. Omni will automatically add PEM headers if none are provided. Applicable for Snowflake only." + }, + "queryTimeoutSeconds": { + "type": "integer", + "maximum": 3600, + "description": "The timeout in seconds for queries. Maximum value is 3600 (1 hour). Only applicable for databases that support query timeouts.", + "example": 900 + }, + "queryTimezone": { + "type": "string", + "description": "The timezone to use for queries", + "example": "NONE" + }, + "region": { + "type": "string", + "description": "Required for BigQuery and Athena connections. For BigQuery, specify a region like \"us\". For Athena, specify an AWS region like \"us-east-1\".", + "example": "us-east-1" + }, + "scratchSchema": { + "type": "string", + "description": "Schema to use for data input (upload) tables. If not specified, a suitable default will be chosen.", + "example": "omni_scratch" + }, + "systemTimezone": { + "type": "string", + "description": "The timezone to use for the system", + "example": "UTC" + }, + "trustServerCertificate": { + "type": "boolean", + "default": false, + "description": "Whether to trust the server certificate. Applicable for MSSQL, Exasol, ClickHouse, Trino, and SAP HANA.", + "example": false + }, + "useMachineAuth": { + "type": "boolean", + "description": "Whether to authenticate using machine credentials (OAuth M2M). Applicable for Athena and Databricks.", + "example": false + }, + "username": { + "type": "string", + "description": "The username to authenticate with. For BigQuery, this is the client email from the service account.", + "example": "analytics_user" + }, + "warehouse": { + "type": "string", + "description": "Required for Snowflake (specify the warehouse) and Databricks (specify the HTTP path).", + "example": "COMPUTE_WH" + } + }, + "required": [ + "dialect", + "name", + "passwordUnencrypted" + ], + "description": "Request body for creating a database connection. Required fields: dialect, name, passwordUnencrypted. Additional fields may be required depending on the dialect.", + "title": "ConnectionsCreateBody" } } } }, "responses": { - "200": { - "description": "Topic selected successfully. The returned topicId can be used as the topicName parameter in other AI endpoints.", + "201": { + "description": "Connection created successfully", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/AiPickTopicResponse" + "type": "object", + "properties": { + "data": { + "type": "string", + "format": "uuid", + "description": "Created connection ID", + "example": "550e8400-e29b-41d4-a716-446655440000" + }, + "success": { + "type": "boolean", + "description": "Whether the operation succeeded", + "example": true + } + }, + "required": [ + "data", + "success" + ], + "description": "Create connection response", + "title": "ConnectionsCreateResponse" } } } }, "400": { - "description": "Invalid request body. The prompt or modelId may be missing or malformed.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiError400" - } - } - } + "description": "Invalid request body or dialect" }, "401": { - "description": "Missing or invalid API key.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiError401" - } - } - } + "description": "Authentication required" }, "403": { - "description": "Insufficient permissions. Requires the querier role on the target model and AI must be enabled for the organization.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiError403" - } - } - } - }, - "404": { - "description": "The specified model was not found, or no accessible topics exist in the model.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiError404" - } - } - } - }, - "500": { - "description": "AI service error." + "description": "Permission denied - admin role required" } } } }, - "/api/v1/ai/search-omni-docs": { - "post": { - "description": "Search the Omni documentation using AI to answer questions about Omni features, configuration, modeling, dashboards, and more. Sends a natural language question and returns a synthesized answer with source links to the relevant documentation pages.", - "operationId": "aiSearchOmniDocs", - "summary": "Search Omni documentation", + "/api/v1/connections/{id}": { + "get": { + "description": "Fetch a single connection by ID.", + "operationId": "connectionsGet", + "summary": "Get connection", "tags": [ - "AI" + "Connections" ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AiSearchOmniDocsBody" - } - } + "parameters": [ + { + "schema": { + "type": "string", + "format": "uuid", + "description": "Connection ID", + "example": "550e8400-e29b-41d4-a716-446655440000" + }, + "required": true, + "description": "Connection ID", + "name": "id", + "in": "path" } - }, + ], "responses": { "200": { - "description": "Documentation search completed successfully. Returns a synthesized answer with source links.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AiSearchOmniDocsResponse" - } - } - } - }, - "400": { - "description": "Invalid request. The question may be missing or exceed the 2000 character limit.", + "description": "Connection object", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ApiError400" + "type": "object", + "properties": { + "connection": { + "type": "object", + "properties": { + "baseRole": { + "type": [ + "string", + "null" + ], + "description": "Default role for users on this connection", + "example": "QUERIER" + }, + "branchConnectionEnvironmentOverridesUserAttr": { + "type": [ + "boolean", + "null" + ], + "description": "Whether branch environments override user attributes", + "example": false + }, + "createdAt": { + "type": "string", + "description": "Timestamp when connection was created (ISO 8601)", + "example": "2024-01-15T10:30:00Z" + }, + "database": { + "type": [ + "string", + "null" + ], + "description": "Database name", + "example": "analytics_db" + }, + "defaultSchema": { + "type": [ + "string", + "null" + ], + "description": "Default schema for the connection", + "example": "public" + }, + "deletedAt": { + "type": [ + "string", + "null" + ], + "description": "Timestamp when connection was deleted (ISO 8601)", + "example": null + }, + "dialect": { + "type": "string", + "enum": [ + "snowflake", + "bigquery", + "redshift", + "postgres", + "mysql", + "mariadb", + "databricks", + "databricks_lakebase", + "trino", + "athena", + "duckdb", + "motherduck", + "sqlserver", + "clickhouse", + "singlestore" + ], + "description": "Database dialect type", + "example": "snowflake" + }, + "environmentConnectionSwitchesSchemaModel": { + "type": [ + "boolean", + "null" + ], + "description": "Whether environment connections switch schema model", + "example": false + }, + "id": { + "type": "string", + "format": "uuid", + "description": "Unique connection identifier", + "example": "550e8400-e29b-41d4-a716-446655440000" + }, + "name": { + "type": "string", + "description": "Connection display name", + "example": "Production Snowflake" + }, + "updatedAt": { + "type": "string", + "description": "Timestamp when connection was last updated (ISO 8601)", + "example": "2024-01-15T10:30:00Z" + }, + "userAttributeNameForConnectionEnvironments": { + "type": [ + "string", + "null" + ], + "description": "User attribute name used for connection environments", + "example": "region" + }, + "userAttributeValuesForDefaultEnvironment": { + "type": [ + "array", + "null" + ], + "items": { + "type": "string" + }, + "description": "Default user attribute values for the base environment", + "example": [ + "us-east", + "us-west" + ] + } + }, + "required": [ + "baseRole", + "branchConnectionEnvironmentOverridesUserAttr", + "createdAt", + "database", + "defaultSchema", + "deletedAt", + "dialect", + "environmentConnectionSwitchesSchemaModel", + "id", + "name", + "updatedAt", + "userAttributeNameForConnectionEnvironments", + "userAttributeValuesForDefaultEnvironment" + ], + "description": "Connection object", + "title": "Connection" + } + }, + "required": [ + "connection" + ], + "description": "Get connection response", + "title": "ConnectionsGetResponse" } } } }, "401": { - "description": "Missing or invalid API key.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiError401" - } - } - } + "description": "Authentication required" }, "403": { - "description": "Omni Agent is not enabled for this organization.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiError403" - } - } - } + "description": "Permission denied — caller lacks READ on the connection" }, - "500": { - "description": "AI service error." + "404": { + "description": "Connection does not exist" } } - } - }, - "/api/v1/ai/jobs": { - "post": { - "description": "Submit a new AI job for asynchronous execution. The AI will analyze the prompt, generate and execute queries against the specified model, and produce a summarized answer. Jobs are processed by a background worker and typically complete within 15–60 seconds. Use GET /api/v1/ai/jobs/{jobId} to poll for status, or configure a webhookUrl to receive a notification when the job completes. Optionally continue an existing conversation by providing a conversationId.", - "operationId": "aiJobSubmit", - "summary": "Submit an AI job", + }, + "patch": { + "description": "Update connection settings including base role, environment user attributes, and credentials.\n\nCredential fields:\n- `passwordUnencrypted`: Update password (all dialects) or service account JSON (BigQuery)\n- `privateKey`: Add/rotate RSA keypair for Snowflake keypair authentication\n\nNote: Credentials are encrypted at rest and never returned in API responses.", + "operationId": "connectionsUpdate", + "summary": "Update connection", "tags": [ - "AI" + "Connections" ], "parameters": [ { "schema": { "type": "string", - "description": "Target user membership ID (for org-scoped API keys)" + "format": "uuid", + "description": "Connection ID", + "example": "550e8400-e29b-41d4-a716-446655440000" }, - "required": false, - "description": "Target user membership ID (for org-scoped API keys)", - "name": "userId", - "in": "query" + "required": true, + "description": "Connection ID", + "name": "id", + "in": "path" } ], "requestBody": { - "required": true, "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/AiJobSubmitBody" + "type": "object", + "properties": { + "baseRole": { + "type": "string", + "description": "Default role to assign to this connection", + "example": "QUERIER" + }, + "environmentUserAttribute": { + "type": [ + "object", + "null" + ], + "properties": { + "attributeName": { + "type": "string", + "description": "Name of the user attribute for environment selection", + "example": "region" + }, + "defaultValues": { + "type": [ + "array", + "null" + ], + "items": { + "type": "string" + }, + "description": "Default values for the user attribute", + "example": [ + "us-east", + "us-west" + ] + } + }, + "required": [ + "attributeName", + "defaultValues" + ], + "description": "User attribute settings for connection environments" + }, + "passwordUnencrypted": { + "type": "string", + "description": "New password or service account key. For BigQuery, this must be the JSON service account key file content." + }, + "privateKey": { + "type": "string", + "description": "RSA private key for keypair authentication (Snowflake only). Must be PEM-encoded PKCS#8 format, minimum 2048-bit." + } + }, + "description": "Request body for updating connection attributes and credentials. At least one field must be provided.", + "title": "ConnectionsUpdateBody" } } } }, "responses": { - "201": { - "description": "Job created and queued for execution. Use the returned jobId to poll for status or retrieve results.", + "200": { + "description": "Connection updated successfully", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/AiJobSubmitResponse" + "type": "object", + "properties": { + "message": { + "type": "string", + "description": "Status message describing what was updated", + "example": "Updated connection default role." + }, + "success": { + "type": "boolean", + "description": "Whether the operation succeeded", + "example": true + } + }, + "required": [ + "message", + "success" + ], + "description": "Update connection response", + "title": "ConnectionsUpdateResponse" } } } }, "400": { - "description": "Invalid request body. Common causes: missing or empty prompt, invalid UUID for modelId/branchId/conversationId, invalid webhook URL format.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiError400" - } - } - } + "description": "Invalid request body - at least one field must be provided" }, "401": { - "description": "Missing or invalid API key.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiError401" - } - } - } + "description": "Authentication required" }, "403": { - "description": "Insufficient permissions. The AI jobs API must be enabled for the organization, AI query generation must be enabled, and the user must have appropriate model access. User-scoped API keys cannot act on behalf of other users.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiError403" - } - } - } + "description": "Permission denied - connection admin role required" }, "404": { - "description": "The specified model was not found in the organization, the branchId does not belong to the specified model, or the topicName does not exist in the model (or is excluded by ai_chat_topics restrictions).", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiError404" - } - } - } - }, - "409": { - "description": "An active job already exists for the specified conversationId. Wait for the current job to complete before submitting another job to the same conversation.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiError409" - } - } - } + "description": "Connection not found" } } - } - }, - "/api/v1/ai/jobs/{jobId}": { - "get": { - "description": "Get the current status of an AI job, including its state, progress information, and result summary. The response fields vary by state — for example, progress is only present during EXECUTING, and resultSummary is only present when COMPLETE. Poll this endpoint every 2–5 seconds until the job reaches a terminal state (COMPLETE, FAILED, or CANCELLED).", - "operationId": "aiJobStatus", - "summary": "Get AI job status", + }, + "delete": { + "description": "Archive a connection (move to trash). Archived connections can be restored from the trash in the connection settings UI.\n\nA connection that is already archived returns 410.", + "operationId": "connectionsDelete", + "summary": "Delete connection", "tags": [ - "AI" + "Connections" ], "parameters": [ { "schema": { "type": "string", "format": "uuid", - "description": "The unique identifier of the AI job", - "example": "123e4567-e89b-12d3-a456-426614174000" + "description": "Connection ID", + "example": "550e8400-e29b-41d4-a716-446655440000" }, "required": true, - "description": "The unique identifier of the AI job", - "name": "jobId", + "description": "Connection ID", + "name": "id", "in": "path" } ], "responses": { "200": { - "description": "Job status retrieved successfully. Check the state field to determine if the job is still running or has reached a terminal state.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AiJobStatusResponse" - } - } - } - }, - "400": { - "description": "Invalid job ID format. Must be a valid UUID.", + "description": "Connection moved to trash", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ApiError400" + "type": "object", + "properties": { + "message": { + "type": "string", + "description": "Status message describing the result", + "example": "Connection moved to trash." + }, + "success": { + "type": "boolean", + "description": "True when the connection was archived", + "example": true + } + }, + "required": [ + "message", + "success" + ], + "description": "Archive connection response", + "title": "ConnectionsDeleteResponse" } } } }, "401": { - "description": "Missing or invalid API key.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiError401" - } - } - } + "description": "Authentication required" + }, + "403": { + "description": "Permission denied - connection admin role required" }, "404": { - "description": "Job not found. The job may not exist or may belong to a different organization.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiError404" - } - } - } + "description": "Connection not found" + }, + "410": { + "description": "Connection has already been archived" } } } }, - "/api/v1/ai/jobs/{jobId}/cancel": { - "post": { - "description": "Request cancellation of an AI job. This endpoint is idempotent — calling it on an already-cancelled or completed job returns success with the current state. For QUEUED jobs, cancellation is immediate. For EXECUTING jobs, the worker will stop after completing its current iteration. Jobs in DELIVERING state cannot be cancelled as they are already finalizing results. Only the job owner or organization admins can cancel jobs.", - "operationId": "aiJobCancel", - "summary": "Cancel an AI job", + "/api/v1/connections/{connectionId}/dbt": { + "get": { + "operationId": "connectionsDbtGet", + "summary": "Get dbt configuration", "tags": [ - "AI" + "Connections" ], "parameters": [ { "schema": { "type": "string", "format": "uuid", - "description": "The unique identifier of the AI job", - "example": "123e4567-e89b-12d3-a456-426614174000" + "description": "Connection ID", + "example": "550e8400-e29b-41d4-a716-446655440000" }, "required": true, - "description": "The unique identifier of the AI job", - "name": "jobId", + "description": "Connection ID", + "name": "connectionId", "in": "path" } ], "responses": { "200": { - "description": "Cancellation request processed. The state field indicates the job's state after the attempt — CANCELLED if successful, or the current terminal state if the job had already completed.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AiJobCancelResponse" - } - } - } - }, - "400": { - "description": "Invalid job ID format. Must be a valid UUID.", + "description": "dbt configuration for the connection", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ApiError400" + "anyOf": [ + { + "type": "object", + "properties": { + "autogenRelationships": { + "type": "boolean", + "description": "Whether relationships are auto-generated from dbt", + "example": true + }, + "branch": { + "type": "string", + "description": "Git branch name", + "example": "main" + }, + "dbtVersion": { + "type": "string", + "description": "dbt version being used", + "example": "Auto" + }, + "enableSemanticLayer": { + "type": "boolean", + "description": "Whether the dbt semantic layer integration is enabled", + "example": false + }, + "enableVirtualSchemas": { + "type": "boolean", + "description": "Whether virtual schemas are enabled", + "example": false + }, + "projectRootPath": { + "type": [ + "string", + "null" + ], + "description": "Path to dbt project root", + "example": "dbt_project" + }, + "sshUrl": { + "type": "string", + "description": "SSH URL for git repository", + "example": "git@github.com:org/repo.git" + }, + "supportsDbt": { + "type": "boolean", + "enum": [ + true + ], + "description": "Indicates dbt is supported and configured", + "example": true + } + }, + "required": [ + "autogenRelationships", + "branch", + "dbtVersion", + "enableSemanticLayer", + "enableVirtualSchemas", + "projectRootPath", + "sshUrl", + "supportsDbt" + ], + "description": "dbt repository configuration response", + "title": "DbtConfiguredResponse" + }, + { + "type": "object", + "properties": { + "message": { + "type": "string", + "description": "Message explaining dbt status", + "example": "dbt not configured for this connection" + }, + "supportsDbt": { + "type": "boolean", + "description": "Whether the connection dialect supports dbt", + "example": true + } + }, + "required": [ + "message", + "supportsDbt" + ], + "description": "Response when dbt is not configured", + "title": "DbtNotConfiguredResponse" + } + ], + "description": "dbt configuration response", + "title": "ConnectionsDbtGetResponse" } } } }, "401": { - "description": "Missing or invalid API key.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiError401" - } - } - } + "description": "Authentication required" }, "403": { - "description": "Permission denied. Only the job owner or organization admins can cancel jobs.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiError403" - } - } - } + "description": "Permission denied - connection admin role required" }, "404": { - "description": "Job not found. The job may not exist or may belong to a different organization.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiError404" - } - } - } - }, - "409": { - "description": "Concurrent modification conflict. The job state was changed by another request. Retry the cancellation.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiError409" - } - } - } + "description": "Connection not found" } } - } - }, - "/api/v1/ai/jobs/{jobId}/result": { - "get": { - "description": "Retrieve the full result of a completed AI job, including all actions taken by the AI (queries generated, data retrieved) and the final summarized answer. Results are only available for jobs in COMPLETE state and are retained for 14 days after completion. The response is streamed directly from storage.", - "operationId": "aiJobResult", - "summary": "Get AI job result", + }, + "put": { + "operationId": "connectionsDbtUpdate", + "summary": "Update dbt configuration", "tags": [ - "AI" + "Connections" ], "parameters": [ { "schema": { "type": "string", "format": "uuid", - "description": "The unique identifier of the AI job", - "example": "123e4567-e89b-12d3-a456-426614174000" + "description": "Connection ID", + "example": "550e8400-e29b-41d4-a716-446655440000" }, "required": true, - "description": "The unique identifier of the AI job", - "name": "jobId", + "description": "Connection ID", + "name": "connectionId", "in": "path" } ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "autogenRelationships": { + "type": "boolean", + "description": "Automatically generate relationships from dbt", + "example": true + }, + "branch": { + "type": "string", + "minLength": 1, + "description": "Git branch name", + "example": "main" + }, + "dbtVersion": { + "type": [ + "string", + "null" + ], + "description": "dbt version to use. Supported: Auto, 1.10, 1.11", + "example": "1.11" + }, + "enableSemanticLayer": { + "type": "boolean", + "default": false, + "description": "Enable dbt semantic layer integration", + "example": false + }, + "enableVirtualSchemas": { + "type": "boolean", + "description": "Enable virtual schemas from dbt", + "example": false + }, + "projectRootPath": { + "anyOf": [ + { + "type": "string", + "pattern": "^(?!\\/)(?!.*\\.\\.)[\\w ./-]+$" + }, + { + "type": "string", + "enum": [ + "" + ] + }, + { + "type": [ + "object", + "null" + ], + "enum": [ + null + ] + }, + { + "type": "null" + } + ], + "default": null, + "description": "Path to dbt project root within repository", + "example": "dbt_project" + }, + "rotateKeys": { + "type": "boolean", + "default": false, + "description": "Rotate SSH deploy keys", + "example": false + }, + "sshUrl": { + "type": "string", + "minLength": 1, + "description": "SSH URL for git repository", + "example": "git@github.com:org/repo.git" + } + }, + "required": [ + "autogenRelationships", + "branch", + "enableVirtualSchemas", + "sshUrl" + ], + "description": "dbt repository configuration", + "title": "ConnectionsDbtUpdateBody" + } + } + } + }, "responses": { "200": { - "description": "Full job result including the AI's actions, query results (with CSV data), and the final Markdown-formatted answer.", + "description": "dbt configuration updated successfully", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/AiJobResultResponse" + "type": "object", + "properties": { + "message": { + "type": "string", + "description": "Success message", + "example": "dbt configuration updated successfully" + }, + "success": { + "type": "boolean", + "description": "Whether the operation succeeded", + "example": true + } + }, + "required": [ + "message", + "success" + ], + "description": "dbt update response", + "title": "ConnectionsDbtUpdateResponse" } } } }, "400": { - "description": "Invalid job ID format. Must be a valid UUID.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiError400" - } - } - } + "description": "Invalid request body or validation error" }, "401": { - "description": "Missing or invalid API key.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiError401" - } - } - } + "description": "Authentication required" + }, + "403": { + "description": "Permission denied - connection admin role required" }, "404": { - "description": "Job not found, not in COMPLETE state, or result is no longer available (results are retained for 14 days).", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiError404" - } - } - } + "description": "Connection not found" } } - } - }, - "/api/v1/ai/jobs/{jobId}/vis": { - "get": { - "description": "Render the visualization from a completed AI job as a PNG image. The endpoint extracts the visualization configuration from the job result, loads Arrow IPC data, and renders it server-side using Vega. For style-only follow-ups (e.g., \"make it a bar chart\"), the endpoint walks back through previous jobs in the conversation to find the original query data.", - "operationId": "aiJobVisualization", - "summary": "Render AI job visualization", + }, + "delete": { + "operationId": "connectionsDbtDelete", + "summary": "Delete dbt configuration", "tags": [ - "AI" + "Connections" ], "parameters": [ { "schema": { "type": "string", "format": "uuid", - "description": "The unique identifier of the AI job", - "example": "123e4567-e89b-12d3-a456-426614174000" + "description": "Connection ID", + "example": "550e8400-e29b-41d4-a716-446655440000" }, "required": true, - "description": "The unique identifier of the AI job", - "name": "jobId", + "description": "Connection ID", + "name": "connectionId", "in": "path" } ], "responses": { "200": { - "description": "Visualization rendered as a PNG image. The Content-Type header is image/png.", - "content": { - "image/png": { - "schema": { - "format": "binary", - "type": "string" - } - } - } - }, - "400": { - "description": "Invalid job ID format. Must be a valid UUID.", + "description": "dbt configuration deleted successfully", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ApiError400" + "type": "object", + "properties": { + "message": { + "type": "string", + "description": "Success message", + "example": "dbt repository unlinked successfully" + }, + "success": { + "type": "boolean", + "description": "Whether the operation succeeded", + "example": true + } + }, + "required": [ + "message", + "success" + ], + "description": "dbt delete response", + "title": "ConnectionsDbtDeleteResponse" } } } }, "401": { - "description": "Missing or invalid API key.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiError401" - } - } - } + "description": "Authentication required" }, - "404": { - "description": "Job not found, not in COMPLETE state, or the apiAiVis feature flag is not enabled.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiError404" - } - } - } + "403": { + "description": "Permission denied - connection admin role required" }, - "422": { - "description": "The job completed but cannot be rendered as a visualization. Common causes: no visualization action in the job result, no Arrow IPC data available, missing summary fields, or the chart type is not renderable as an image (e.g., tables, KPIs).", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiError422" - } - } - } + "404": { + "description": "Connection not found or dbt not configured" } } } }, - "/api/v1/api-keys": { + "/api/v1/connections/{connectionId}/dbt/environments": { "get": { - "description": "Returns all API tokens in the organization, including organization-level keys, personal access tokens, and MCP OAuth grants. Secrets are never returned. Requires organization admin permissions.", - "operationId": "apiKeysList", - "summary": "List API tokens", + "description": "List all dbt environments for a connection.", + "operationId": "connectionsDbtEnvironmentsList", + "summary": "List dbt environments", "tags": [ - "API Tokens" + "Connections" ], "parameters": [ { "schema": { "type": "string", "format": "uuid", - "description": "Cursor from the previous response (token UUID)" + "description": "Connection ID", + "example": "550e8400-e29b-41d4-a716-446655440000" + }, + "required": true, + "description": "Connection ID", + "name": "connectionId", + "in": "path" + }, + { + "schema": { + "type": "string", + "description": "Cursor for pagination (from previous response nextCursor)", + "example": "eyJpZCI6IjEyMzQ1In0" }, "required": false, - "description": "Cursor from the previous response (token UUID)", + "description": "Cursor for pagination (from previous response nextCursor)", "name": "cursor", "in": "query" }, { "schema": { - "type": "number", + "type": "integer", "minimum": 1, "maximum": 100, "default": 20, - "description": "Number of results per page (1-100)", + "description": "Number of results per page (1-100, integer)", "example": 20 }, "required": false, - "description": "Number of results per page (1-100)", + "description": "Number of results per page (1-100, integer)", "name": "pageSize", "in": "query" }, @@ -8619,120 +32672,58 @@ "schema": { "type": "string", "enum": [ - "createdAt", "name" ], - "default": "createdAt" + "default": "name", + "description": "Field to sort results by", + "example": "name" }, "required": false, + "description": "Field to sort results by", "name": "sortField", "in": "query" - }, - { - "schema": { - "type": "string", - "enum": [ - "organization", - "personal", - "mcp" - ], - "description": "Filter by API token type. When omitted, all types are returned.", - "example": "personal" - }, - "required": false, - "description": "Filter by API token type. When omitted, all types are returned.", - "name": "type", - "in": "query" - } - ], - "responses": { - "200": { - "description": "Paginated list of API tokens", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiKeyListResponse" - } - } - } - }, - "400": { - "description": "Invalid query parameters" - }, - "401": { - "description": "Authentication required" - }, - "403": { - "description": "Insufficient permissions" - } - } - } - }, - "/api/v1/api-keys/{id}": { - "get": { - "description": "Returns a single API token by id. Requires organization admin permissions.", - "operationId": "apiKeysGet", - "summary": "Get API token", - "tags": [ - "API Tokens" - ], - "parameters": [ - { - "schema": { - "type": "string", - "format": "uuid", - "description": "Token UUID", - "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" - }, - "required": true, - "description": "Token UUID", - "name": "id", - "in": "path" } ], "responses": { "200": { - "description": "The requested API token", + "description": "List of dbt environments", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ApiKey" + "$ref": "#/components/schemas/DbtEnvironmentListResponse" } } } }, - "400": { - "description": "Malformed `id` (must be a UUID)" - }, "401": { "description": "Authentication required" }, "403": { - "description": "Insufficient permissions" + "description": "Permission denied or connection does not support dbt" }, "404": { - "description": "Token not found in this organization" + "description": "Connection not found" } } }, - "put": { - "description": "Enables or disables an organization-level API token. Personal access tokens and MCP OAuth grants do not support this operation. Requires organization admin permissions.", - "operationId": "apiKeysUpdate", - "summary": "Enable or disable an organization API token", + "post": { + "description": "Create a new dbt environment for a connection.", + "operationId": "connectionsDbtEnvironmentsCreate", + "summary": "Create dbt environment", "tags": [ - "API Tokens" + "Connections" ], "parameters": [ { "schema": { "type": "string", "format": "uuid", - "description": "Token UUID", - "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" + "description": "Connection ID", + "example": "550e8400-e29b-41d4-a716-446655440000" }, "required": true, - "description": "Token UUID", - "name": "id", + "description": "Connection ID", + "name": "connectionId", "in": "path" } ], @@ -8741,87 +32732,50 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ApiKeyUpdateBody" + "$ref": "#/components/schemas/DbtEnvironmentCreateBody" } } } }, "responses": { - "200": { - "description": "The updated API token", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiKey" - } - } - } - }, - "400": { - "description": "Invalid body, malformed `id`, target is not an organization token, or missing/malformed `Authorization` header" - }, - "403": { - "description": "Invalid bearer token, or caller lacks organization admin permissions" - }, - "404": { - "description": "Token not found in this organization" - }, - "405": { - "description": "Method not allowed" - } - } - }, - "delete": { - "description": "Revokes an API token by permanently deleting it. Works for all token types. Requires organization admin permissions.", - "operationId": "apiKeysDelete", - "summary": "Revoke an API token", - "tags": [ - "API Tokens" - ], - "parameters": [ - { - "schema": { - "type": "string", - "format": "uuid", - "description": "Token UUID", - "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" - }, - "required": true, - "description": "Token UUID", - "name": "id", - "in": "path" - } - ], - "responses": { - "200": { - "description": "The token was revoked", + "201": { + "description": "dbt environment created successfully", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ApiKeyDeleteResponse" + "allOf": [ + { + "$ref": "#/components/schemas/DbtEnvironmentItem" + }, + { + "description": "Created dbt environment", + "title": "DbtEnvironmentCreateResponse" + } + ] } } } }, "400": { - "description": "Malformed `id`, or missing/malformed `Authorization` header" + "description": "Invalid request body" + }, + "401": { + "description": "Authentication required" }, "403": { - "description": "Invalid bearer token, or caller lacks organization admin permissions" + "description": "Permission denied or connection does not support dbt" }, "404": { - "description": "Token not found in this organization" - }, - "405": { - "description": "Method not allowed" + "description": "Connection not found" } } } }, - "/api/v1/connections": { - "get": { - "operationId": "connectionsList", - "summary": "List connections", + "/api/v1/connections/{connectionId}/dbt/environments/{environmentId}": { + "put": { + "description": "Update an existing dbt environment for a connection.", + "operationId": "connectionsDbtEnvironmentsUpdate", + "summary": "Update dbt environment", "tags": [ "Connections" ], @@ -8829,532 +32783,252 @@ { "schema": { "type": "string", - "description": "Filter by database name (case-insensitive contains)", - "example": "analytics" - }, - "required": false, - "description": "Filter by database name (case-insensitive contains)", - "name": "database", - "in": "query" - }, - { - "schema": { - "type": "string", - "description": "Filter by dialect(s). Comma-separated list for multiple values", - "example": "snowflake,bigquery" - }, - "required": false, - "description": "Filter by dialect(s). Comma-separated list for multiple values", - "name": "dialect", - "in": "query" - }, - { - "schema": { - "type": "boolean", - "description": "Include soft-deleted connections in results", - "example": false - }, - "required": false, - "description": "Include soft-deleted connections in results", - "name": "includeDeleted", - "in": "query" - }, - { - "schema": { - "type": "string", - "description": "Filter by connection name (case-insensitive contains)", - "example": "Production" - }, - "required": false, - "description": "Filter by connection name (case-insensitive contains)", - "name": "name", - "in": "query" - }, - { - "schema": { - "type": "string", - "enum": [ - "asc", - "desc" - ], - "description": "Sort direction", - "example": "desc" + "format": "uuid", + "description": "Connection ID", + "example": "550e8400-e29b-41d4-a716-446655440000" }, - "required": false, - "description": "Sort direction", - "name": "sortDirection", - "in": "query" + "required": true, + "description": "Connection ID", + "name": "connectionId", + "in": "path" }, { "schema": { "type": "string", - "enum": [ - "database", - "dialect", - "name" - ], - "description": "Field to sort by", - "example": "name" + "format": "uuid", + "description": "Environment ID", + "example": "247dc6dc-2a58-4688-9521-c5ed3e99c1e8" }, - "required": false, - "description": "Field to sort by", - "name": "sortField", - "in": "query" + "required": true, + "description": "Environment ID", + "name": "environmentId", + "in": "path" } ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DbtEnvironmentUpdateBody" + } + } + } + }, "responses": { "200": { - "description": "List of connections", + "description": "dbt environment updated successfully", "content": { "application/json": { "schema": { - "type": "object", - "properties": { - "connections": { - "type": "array", - "items": { - "type": "object", - "properties": { - "baseRole": { - "type": [ - "string", - "null" - ], - "description": "Default role for users on this connection", - "example": "QUERIER" - }, - "branchConnectionEnvironmentOverridesUserAttr": { - "type": [ - "boolean", - "null" - ], - "description": "Whether branch environments override user attributes", - "example": false - }, - "database": { - "type": [ - "string", - "null" - ], - "description": "Database name", - "example": "analytics_db" - }, - "defaultSchema": { - "type": [ - "string", - "null" - ], - "description": "Default schema for the connection", - "example": "public" - }, - "deletedAt": { - "type": [ - "string", - "null" - ], - "description": "Timestamp when connection was deleted (ISO 8601)", - "example": null - }, - "dialect": { - "type": "string", - "enum": [ - "snowflake", - "bigquery", - "redshift", - "postgres", - "mysql", - "mariadb", - "databricks", - "databricks_lakebase", - "trino", - "athena", - "duckdb", - "motherduck", - "sqlserver", - "clickhouse", - "singlestore" - ], - "description": "Database dialect type", - "example": "snowflake" - }, - "environmentConnectionSwitchesSchemaModel": { - "type": [ - "boolean", - "null" - ], - "description": "Whether environment connections switch schema model", - "example": false - }, - "id": { - "type": "string", - "format": "uuid", - "description": "Unique connection identifier", - "example": "550e8400-e29b-41d4-a716-446655440000" - }, - "name": { - "type": "string", - "description": "Connection display name", - "example": "Production Snowflake" - }, - "userAttributeNameForConnectionsEnvironments": { - "type": [ - "string", - "null" - ], - "description": "User attribute name used for connection environments", - "example": "region" - }, - "userAttributeValuesForDefaultEnvironment": { - "type": [ - "array", - "null" - ], - "items": { - "type": "string" - }, - "description": "Default user attribute values for the base environment", - "example": [ - "us-east", - "us-west" - ] - } - }, - "required": [ - "baseRole", - "branchConnectionEnvironmentOverridesUserAttr", - "database", - "defaultSchema", - "deletedAt", - "dialect", - "environmentConnectionSwitchesSchemaModel", - "id", - "name", - "userAttributeNameForConnectionsEnvironments", - "userAttributeValuesForDefaultEnvironment" - ], - "description": "Connection object", - "title": "Connection" - }, - "description": "List of connections" + "allOf": [ + { + "$ref": "#/components/schemas/DbtEnvironmentItem" + }, + { + "description": "Updated dbt environment", + "title": "DbtEnvironmentUpdateResponse" } - }, - "required": [ - "connections" - ], - "description": "List connections response", - "title": "ConnectionsListResponse" + ] } } } }, + "400": { + "description": "Invalid request body" + }, "401": { "description": "Authentication required" }, "403": { - "description": "Permission denied - admin role required" + "description": "Permission denied or connection does not support dbt" + }, + "404": { + "description": "Connection or environment not found" } } }, - "post": { - "description": "Create a new database connection. The request body varies by dialect - see dialect-specific documentation for required fields.", - "operationId": "connectionsCreate", - "summary": "Create connection", - "tags": [ - "Connections" - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "acceptsLicense": { - "type": "boolean", - "description": "Acceptance of the license terms. Required for Oracle connections.", - "example": true - }, - "allowsUserSpecificTimezones": { - "type": "boolean", - "default": false, - "description": "Whether to allow users to specify their own timezones", - "example": false - }, - "alwaysScopeViewNames": { - "type": "boolean", - "description": "Whether to always include schema (and catalog) prefixes in generated view names, even for tables in the default schema. Defaults to true for dialects that support multiple catalogs, false otherwise.", - "example": true - }, - "authenticationType": { - "type": "string", - "description": "Authentication type. Applicable for BigQuery, MSSQL, Snowflake, Databricks, and Athena.", - "example": "snowflake-password" - }, - "awsRoleArn": { - "type": "string", - "description": "AWS IAM role ARN. Applicable for Athena only.", - "example": "arn:aws:iam::123456789012:role/OmniAthenaRole" - }, - "baseRole": { - "type": "string", - "enum": [ - "NO_ACCESS", - "VIEWER", - "RESTRICTED_QUERIER", - "QUERIER", - "MODELER", - "CONNECTION_ADMIN" - ], - "description": "The default role for users accessing the connection", - "example": "QUERIER" - }, - "database": { - "type": "string", - "description": "The default database/catalog to connect to. For BigQuery, this is the project ID. For Athena, this is the data catalog.", - "example": "analytics_db" - }, - "defaultSchema": { - "type": "string", - "description": "The default schema to use. Required for MSSQL.", - "example": "public" - }, - "dialect": { - "type": "string", - "enum": [ - "athena", - "bigquery", - "clickhouse", - "databricks", - "databricks_lakebase", - "exasol", - "mariadb", - "motherduck", - "mssql", - "mysql", - "oracle", - "postgres", - "redshift", - "sap_hana", - "snowflake", - "starrocks", - "trino" - ], - "description": "The database dialect", - "example": "snowflake" - }, - "enableDbSemanticLayerIntegration": { - "type": "boolean", - "default": false, - "description": "Enable the dialect-native semantic layer integration. Applicable for Snowflake and Databricks.", - "example": false - }, - "enableDbSemanticLayerTopics": { - "type": "boolean", - "default": false, - "description": "Enable the dialect-native semantic layer topics. Applicable for Snowflake and Databricks.", - "example": false - }, - "externalOauthAudience": { - "type": "string", - "description": "External OAuth audience claim. Applicable for Snowflake." - }, - "externalOauthAuthorizationUrl": { - "type": "string", - "format": "uri", - "description": "External OAuth authorization URL (must be HTTPS). Applicable for Snowflake.", - "example": "https://oauth.example.com/authorize" - }, - "externalOauthTokenUrl": { - "type": "string", - "format": "uri", - "description": "External OAuth token URL (must be HTTPS). Applicable for Snowflake.", - "example": "https://oauth.example.com/token" - }, - "host": { - "type": "string", - "description": "The hostname or IP address of the database server. For Snowflake, provide only the account identifier.", - "example": "myaccount" - }, - "hostOverride": { - "type": "string", - "description": "Custom Snowflake host (when not using the account identifier). Mutually exclusive with `host`.", - "example": "myaccount.snowflakecomputing.com" - }, - "includeOtherCatalogs": { - "type": "string", - "description": "Comma-separated list of other catalogs/databases to include. Only applicable for databases that support multi-catalog queries.", - "example": "other_project1,other_project2" - }, - "includeSchemas": { - "type": "string", - "description": "Comma-separated list of schemas to include. Leave empty to include all schemas.", - "example": "public,analytics" - }, - "inferRelationshipsFromColumnNames": { - "type": "boolean", - "default": true, - "description": "Whether to infer relationships from column-name conventions during schema refresh. Defaults to true.", - "example": true - }, - "inferRelationshipsFromForeignKeys": { - "type": "boolean", - "default": false, - "description": "Whether to infer relationships from declared foreign keys during schema refresh. Currently honored for Postgres and Snowflake.", - "example": false - }, - "maxBillingBytes": { - "type": "string", - "description": "Maximum bytes that can be billed for a BigQuery query. Applicable for BigQuery only.", - "example": "1000000000" - }, - "name": { - "type": "string", - "description": "A descriptive name for the connection", - "example": "Production Warehouse" - }, - "oauthClientId": { - "type": "string", - "description": "OAuth client ID for admin schema refresh. Applicable for Snowflake and Databricks." - }, - "oauthClientSecretUnencrypted": { - "type": "string", - "description": "OAuth client secret for admin schema refresh. Applicable for Snowflake and Databricks." - }, - "offloadedSchemas": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Schemas whose tables should be queried via the offloaded engine. Accepts a comma-separated string or an array of schema names.", - "example": [ - "analytics_archive" - ] - }, - "passwordUnencrypted": { - "type": "string", - "description": "The password to authenticate with. For BigQuery, this must be the JSON service account key file content. For Snowflake with keypair authentication, this can be omitted." - }, - "port": { - "type": "integer", - "description": "The port number for the database connection. Not required for Snowflake, MotherDuck, BigQuery, Databricks, and Athena.", - "example": 5432 - }, - "privateKey": { - "type": "string", - "description": "An RSA key for keypair authentication. Omni will automatically add PEM headers if none are provided. Applicable for Snowflake only." - }, - "queryTimeoutSeconds": { - "type": "integer", - "maximum": 3600, - "description": "The timeout in seconds for queries. Maximum value is 3600 (1 hour). Only applicable for databases that support query timeouts.", - "example": 900 - }, - "queryTimezone": { - "type": "string", - "description": "The timezone to use for queries", - "example": "NONE" - }, - "region": { - "type": "string", - "description": "Required for BigQuery and Athena connections. For BigQuery, specify a region like \"us\". For Athena, specify an AWS region like \"us-east-1\".", - "example": "us-east-1" - }, - "scratchSchema": { - "type": "string", - "description": "Schema to use for data input (upload) tables. If not specified, a suitable default will be chosen.", - "example": "omni_scratch" - }, - "systemTimezone": { - "type": "string", - "description": "The timezone to use for the system", - "example": "UTC" - }, - "trustServerCertificate": { - "type": "boolean", - "default": false, - "description": "Whether to trust the server certificate. Applicable for MSSQL, Exasol, ClickHouse, Trino, and SAP HANA.", - "example": false - }, - "useMachineAuth": { - "type": "boolean", - "description": "Whether to authenticate using machine credentials (OAuth M2M). Applicable for Athena and Databricks.", - "example": false - }, - "username": { - "type": "string", - "description": "The username to authenticate with. For BigQuery, this is the client email from the service account.", - "example": "analytics_user" - }, - "warehouse": { - "type": "string", - "description": "Required for Snowflake (specify the warehouse) and Databricks (specify the HTTP path).", - "example": "COMPUTE_WH" - } - }, - "required": [ - "dialect", - "name", - "passwordUnencrypted" - ], - "description": "Request body for creating a database connection. Required fields: dialect, name, passwordUnencrypted. Additional fields may be required depending on the dialect.", - "title": "ConnectionsCreateBody" + "delete": { + "description": "Delete a dbt environment from a connection.", + "operationId": "connectionsDbtEnvironmentsDelete", + "summary": "Delete dbt environment", + "tags": [ + "Connections" + ], + "parameters": [ + { + "schema": { + "type": "string", + "format": "uuid", + "description": "Connection ID", + "example": "550e8400-e29b-41d4-a716-446655440000" + }, + "required": true, + "description": "Connection ID", + "name": "connectionId", + "in": "path" + }, + { + "schema": { + "type": "string", + "format": "uuid", + "description": "Environment ID", + "example": "247dc6dc-2a58-4688-9521-c5ed3e99c1e8" + }, + "required": true, + "description": "Environment ID", + "name": "environmentId", + "in": "path" + } + ], + "responses": { + "200": { + "description": "dbt environment deleted successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DbtEnvironmentDeleteResponse" + } } } + }, + "401": { + "description": "Authentication required" + }, + "403": { + "description": "Permission denied or connection does not support dbt" + }, + "404": { + "description": "Connection or environment not found" } - }, + } + } + }, + "/api/v1/connections/{connectionId}/schedules": { + "get": { + "operationId": "connectionsSchedulesList", + "summary": "List schema refresh schedules", + "tags": [ + "Connections" + ], + "parameters": [ + { + "schema": { + "type": "string", + "format": "uuid", + "description": "Connection ID", + "example": "550e8400-e29b-41d4-a716-446655440000" + }, + "required": true, + "description": "Connection ID", + "name": "connectionId", + "in": "path" + } + ], "responses": { - "201": { - "description": "Connection created successfully", + "200": { + "description": "List of schema refresh schedules", "content": { "application/json": { "schema": { "type": "object", "properties": { - "data": { - "type": "string", - "format": "uuid", - "description": "Created connection ID", - "example": "550e8400-e29b-41d4-a716-446655440000" - }, - "success": { - "type": "boolean", - "description": "Whether the operation succeeded", - "example": true + "schedules": { + "type": "array", + "items": { + "type": "object", + "properties": { + "connectionId": { + "type": "string", + "format": "uuid", + "description": "Connection ID this schedule belongs to", + "example": "550e8400-e29b-41d4-a716-446655440000" + }, + "createdAt": { + "type": "string", + "description": "Schedule creation timestamp (ISO 8601)", + "example": "2024-01-15T10:30:00Z" + }, + "description": { + "type": "string", + "description": "Human-readable schedule description", + "example": "Runs daily at 2:00 AM EST" + }, + "disabledAt": { + "type": [ + "string", + "null" + ], + "description": "Timestamp when schedule was disabled (ISO 8601)", + "example": null + }, + "hardRefresh": { + "type": "boolean", + "description": "When true, the scheduled refresh performs a hard refresh that fully discards and rebuilds the schema model. When false, it performs a soft refresh that merges newly generated views with the existing model.", + "example": false + }, + "schedule": { + "type": "string", + "description": "AWS EventBridge cron expression (6 fields: minute hour day-of-month month day-of-week year). See https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-cron-expressions.html", + "example": "0 2 * * ? *" + }, + "scheduleId": { + "type": "string", + "format": "uuid", + "description": "Unique schedule identifier", + "example": "550e8400-e29b-41d4-a716-446655440001" + }, + "timezone": { + "type": "string", + "description": "IANA timezone for schedule execution", + "example": "America/New_York" + }, + "updatedAt": { + "type": "string", + "description": "Schedule last update timestamp (ISO 8601)", + "example": "2024-01-15T10:30:00Z" + } + }, + "required": [ + "connectionId", + "createdAt", + "description", + "disabledAt", + "hardRefresh", + "schedule", + "scheduleId", + "timezone", + "updatedAt" + ], + "description": "Schema refresh schedule object", + "title": "ConnectionSchedule" + }, + "description": "List of schema refresh schedules" } }, "required": [ - "data", - "success" + "schedules" ], - "description": "Create connection response", - "title": "ConnectionsCreateResponse" + "description": "List schedules response", + "title": "ConnectionsSchedulesListResponse" } } } }, - "400": { - "description": "Invalid request body or dialect" - }, "401": { "description": "Authentication required" }, "403": { - "description": "Permission denied - admin role required" + "description": "Permission denied - connection admin role required" + }, + "404": { + "description": "Connection not found" } } - } - }, - "/api/v1/connections/{id}": { - "patch": { - "description": "Update connection settings including base role, environment user attributes, and credentials.\n\nCredential fields:\n- `passwordUnencrypted`: Update password (all dialects) or service account JSON (BigQuery)\n- `privateKey`: Add/rotate RSA keypair for Snowflake keypair authentication\n\nNote: Credentials are encrypted at rest and never returned in API responses.", - "operationId": "connectionsUpdate", - "summary": "Update connection", + }, + "post": { + "operationId": "connectionsSchedulesCreate", + "summary": "Create schema refresh schedule", "tags": [ "Connections" ], @@ -9368,7 +33042,7 @@ }, "required": true, "description": "Connection ID", - "name": "id", + "name": "connectionId", "in": "path" } ], @@ -9378,89 +33052,111 @@ "schema": { "type": "object", "properties": { - "baseRole": { - "type": "string", - "description": "Default role to assign to this connection", - "example": "QUERIER" - }, - "environmentUserAttribute": { - "type": [ - "object", - "null" - ], - "properties": { - "attributeName": { - "type": "string", - "description": "Name of the user attribute for environment selection", - "example": "region" - }, - "defaultValues": { - "type": [ - "array", - "null" - ], - "items": { - "type": "string" - }, - "description": "Default values for the user attribute", - "example": [ - "us-east", - "us-west" - ] - } - }, - "required": [ - "attributeName", - "defaultValues" - ], - "description": "User attribute settings for connection environments" + "hardRefresh": { + "type": "boolean", + "default": false, + "description": "When true, the scheduled refresh performs a hard refresh that fully discards and rebuilds the schema model. When false (the default), it performs a soft refresh that merges newly generated views with the existing model.", + "example": false }, - "passwordUnencrypted": { + "schedule": { "type": "string", - "description": "New password or service account key. For BigQuery, this must be the JSON service account key file content." + "description": "AWS EventBridge cron expression (6 fields: minute hour day-of-month month day-of-week year). See https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-cron-expressions.html", + "example": "0 2 * * ? *" }, - "privateKey": { + "timezone": { "type": "string", - "description": "RSA private key for keypair authentication (Snowflake only). Must be PEM-encoded PKCS#8 format, minimum 2048-bit." + "description": "IANA timezone for schedule execution", + "example": "America/New_York" } }, - "description": "Request body for updating connection attributes and credentials. At least one field must be provided.", - "title": "ConnectionsUpdateBody" + "required": [ + "schedule", + "timezone" + ], + "description": "Request body for creating a schema refresh schedule", + "title": "ConnectionsSchedulesCreateBody" } } } }, "responses": { - "200": { - "description": "Connection updated successfully", + "201": { + "description": "Schema refresh schedule created successfully", "content": { "application/json": { "schema": { "type": "object", "properties": { - "message": { + "connectionId": { + "type": "string", + "format": "uuid", + "description": "Connection ID this schedule belongs to", + "example": "550e8400-e29b-41d4-a716-446655440000" + }, + "createdAt": { + "type": "string", + "description": "Schedule creation timestamp (ISO 8601)", + "example": "2024-01-15T10:30:00Z" + }, + "description": { "type": "string", - "description": "Status message describing what was updated", - "example": "Updated connection default role." + "description": "Human-readable schedule description", + "example": "Runs daily at 2:00 AM EST" }, - "success": { + "disabledAt": { + "type": [ + "string", + "null" + ], + "description": "Timestamp when schedule was disabled (ISO 8601)", + "example": null + }, + "hardRefresh": { "type": "boolean", - "description": "Whether the operation succeeded", - "example": true + "description": "When true, the scheduled refresh performs a hard refresh that fully discards and rebuilds the schema model. When false, it performs a soft refresh that merges newly generated views with the existing model.", + "example": false + }, + "schedule": { + "type": "string", + "description": "AWS EventBridge cron expression (6 fields: minute hour day-of-month month day-of-week year). See https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-cron-expressions.html", + "example": "0 2 * * ? *" + }, + "scheduleId": { + "type": "string", + "format": "uuid", + "description": "Unique schedule identifier", + "example": "550e8400-e29b-41d4-a716-446655440001" + }, + "timezone": { + "type": "string", + "description": "IANA timezone for schedule execution", + "example": "America/New_York" + }, + "updatedAt": { + "type": "string", + "description": "Schedule last update timestamp (ISO 8601)", + "example": "2024-01-15T10:30:00Z" } }, "required": [ - "message", - "success" + "connectionId", + "createdAt", + "description", + "disabledAt", + "hardRefresh", + "schedule", + "scheduleId", + "timezone", + "updatedAt" ], - "description": "Update connection response", - "title": "ConnectionsUpdateResponse" + "description": "Created schedule response", + "title": "ConnectionsSchedulesCreateResponse" } } } }, "400": { - "description": "Invalid request body - at least one field must be provided" + "description": "Invalid cron expression or timezone" }, "401": { "description": "Authentication required" @@ -9474,10 +33170,10 @@ } } }, - "/api/v1/connections/{connectionId}/dbt": { + "/api/v1/connections/{connectionId}/schedules/{scheduleId}": { "get": { - "operationId": "connectionsDbtGet", - "summary": "Get dbt configuration", + "operationId": "connectionsSchedulesGet", + "summary": "Get schema refresh schedule", "tags": [ "Connections" ], @@ -9493,102 +33189,92 @@ "description": "Connection ID", "name": "connectionId", "in": "path" + }, + { + "schema": { + "type": "string", + "format": "uuid", + "description": "Schedule ID", + "example": "550e8400-e29b-41d4-a716-446655440001" + }, + "required": true, + "description": "Schedule ID", + "name": "scheduleId", + "in": "path" } ], "responses": { "200": { - "description": "dbt configuration for the connection", + "description": "Schema refresh schedule details", "content": { "application/json": { "schema": { - "anyOf": [ - { - "type": "object", - "properties": { - "autogenRelationships": { - "type": "boolean", - "description": "Whether relationships are auto-generated from dbt", - "example": true - }, - "branch": { - "type": "string", - "description": "Git branch name", - "example": "main" - }, - "dbtVersion": { - "type": "string", - "description": "dbt version being used", - "example": "Auto" - }, - "enableSemanticLayer": { - "type": "boolean", - "description": "Whether the dbt semantic layer integration is enabled", - "example": false - }, - "enableVirtualSchemas": { - "type": "boolean", - "description": "Whether virtual schemas are enabled", - "example": false - }, - "projectRootPath": { - "type": [ - "string", - "null" - ], - "description": "Path to dbt project root", - "example": "dbt_project" - }, - "sshUrl": { - "type": "string", - "description": "SSH URL for git repository", - "example": "git@github.com:org/repo.git" - }, - "supportsDbt": { - "type": "boolean", - "enum": [ - true - ], - "description": "Indicates dbt is supported and configured", - "example": true - } - }, - "required": [ - "autogenRelationships", - "branch", - "dbtVersion", - "enableSemanticLayer", - "enableVirtualSchemas", - "projectRootPath", - "sshUrl", - "supportsDbt" - ], - "description": "dbt repository configuration response", - "title": "DbtConfiguredResponse" + "type": "object", + "properties": { + "connectionId": { + "type": "string", + "format": "uuid", + "description": "Connection ID this schedule belongs to", + "example": "550e8400-e29b-41d4-a716-446655440000" }, - { - "type": "object", - "properties": { - "message": { - "type": "string", - "description": "Message explaining dbt status", - "example": "dbt not configured for this connection" - }, - "supportsDbt": { - "type": "boolean", - "description": "Whether the connection dialect supports dbt", - "example": true - } - }, - "required": [ - "message", - "supportsDbt" + "createdAt": { + "type": "string", + "description": "Schedule creation timestamp (ISO 8601)", + "example": "2024-01-15T10:30:00Z" + }, + "description": { + "type": "string", + "description": "Human-readable schedule description", + "example": "Runs daily at 2:00 AM EST" + }, + "disabledAt": { + "type": [ + "string", + "null" ], - "description": "Response when dbt is not configured", - "title": "DbtNotConfiguredResponse" + "description": "Timestamp when schedule was disabled (ISO 8601)", + "example": null + }, + "hardRefresh": { + "type": "boolean", + "description": "When true, the scheduled refresh performs a hard refresh that fully discards and rebuilds the schema model. When false, it performs a soft refresh that merges newly generated views with the existing model.", + "example": false + }, + "schedule": { + "type": "string", + "description": "AWS EventBridge cron expression (6 fields: minute hour day-of-month month day-of-week year). See https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-cron-expressions.html", + "example": "0 2 * * ? *" + }, + "scheduleId": { + "type": "string", + "format": "uuid", + "description": "Unique schedule identifier", + "example": "550e8400-e29b-41d4-a716-446655440001" + }, + "timezone": { + "type": "string", + "description": "IANA timezone for schedule execution", + "example": "America/New_York" + }, + "updatedAt": { + "type": "string", + "description": "Schedule last update timestamp (ISO 8601)", + "example": "2024-01-15T10:30:00Z" } + }, + "required": [ + "connectionId", + "createdAt", + "description", + "disabledAt", + "hardRefresh", + "schedule", + "scheduleId", + "timezone", + "updatedAt" ], - "description": "dbt configuration response", - "title": "ConnectionsDbtGetResponse" + "description": "Get schedule response", + "title": "ConnectionsSchedulesGetResponse" } } } @@ -9600,13 +33286,13 @@ "description": "Permission denied - connection admin role required" }, "404": { - "description": "Connection not found" + "description": "Connection or schedule not found" } } }, "put": { - "operationId": "connectionsDbtUpdate", - "summary": "Update dbt configuration", + "operationId": "connectionsSchedulesUpdate", + "summary": "Update schema refresh schedule", "tags": [ "Connections" ], @@ -9622,129 +33308,131 @@ "description": "Connection ID", "name": "connectionId", "in": "path" + }, + { + "schema": { + "type": "string", + "format": "uuid", + "description": "Schedule ID", + "example": "550e8400-e29b-41d4-a716-446655440001" + }, + "required": true, + "description": "Schedule ID", + "name": "scheduleId", + "in": "path" } ], "requestBody": { "content": { "application/json": { "schema": { - "type": "object", - "properties": { - "autogenRelationships": { - "type": "boolean", - "description": "Automatically generate relationships from dbt", - "example": true - }, - "branch": { - "type": "string", - "minLength": 1, - "description": "Git branch name", - "example": "main" - }, - "dbtVersion": { - "type": [ - "string", - "null" - ], - "description": "dbt version to use. Supported: Auto, 1.10, 1.11", - "example": "1.11" - }, - "enableSemanticLayer": { + "type": "object", + "properties": { + "hardRefresh": { "type": "boolean", "default": false, - "description": "Enable dbt semantic layer integration", - "example": false - }, - "enableVirtualSchemas": { - "type": "boolean", - "description": "Enable virtual schemas from dbt", + "description": "When true, the scheduled refresh performs a hard refresh that fully discards and rebuilds the schema model. When false (the default), it performs a soft refresh that merges newly generated views with the existing model.", "example": false }, - "projectRootPath": { - "anyOf": [ - { - "type": "string", - "pattern": "^(?!\\/)(?!.*\\.\\.)[\\w ./-]+$" - }, - { - "type": "string", - "enum": [ - "" - ] - }, - { - "type": [ - "object", - "null" - ], - "enum": [ - null - ] - }, - { - "type": "null" - } - ], - "default": null, - "description": "Path to dbt project root within repository", - "example": "dbt_project" - }, - "rotateKeys": { - "type": "boolean", - "default": false, - "description": "Rotate SSH deploy keys", - "example": false + "schedule": { + "type": "string", + "description": "AWS EventBridge cron expression (6 fields: minute hour day-of-month month day-of-week year). See https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-cron-expressions.html", + "example": "0 2 * * ? *" }, - "sshUrl": { + "timezone": { "type": "string", - "minLength": 1, - "description": "SSH URL for git repository", - "example": "git@github.com:org/repo.git" + "description": "IANA timezone for schedule execution", + "example": "America/New_York" } }, "required": [ - "autogenRelationships", - "branch", - "enableVirtualSchemas", - "sshUrl" + "schedule", + "timezone" ], - "description": "dbt repository configuration", - "title": "ConnectionsDbtUpdateBody" + "description": "Request body for updating a schema refresh schedule", + "title": "ConnectionsSchedulesUpdateBody" } } } }, "responses": { "200": { - "description": "dbt configuration updated successfully", + "description": "Schema refresh schedule updated successfully", "content": { "application/json": { "schema": { "type": "object", "properties": { - "message": { + "connectionId": { "type": "string", - "description": "Success message", - "example": "dbt configuration updated successfully" + "format": "uuid", + "description": "Connection ID this schedule belongs to", + "example": "550e8400-e29b-41d4-a716-446655440000" }, - "success": { + "createdAt": { + "type": "string", + "description": "Schedule creation timestamp (ISO 8601)", + "example": "2024-01-15T10:30:00Z" + }, + "description": { + "type": "string", + "description": "Human-readable schedule description", + "example": "Runs daily at 2:00 AM EST" + }, + "disabledAt": { + "type": [ + "string", + "null" + ], + "description": "Timestamp when schedule was disabled (ISO 8601)", + "example": null + }, + "hardRefresh": { "type": "boolean", - "description": "Whether the operation succeeded", - "example": true + "description": "When true, the scheduled refresh performs a hard refresh that fully discards and rebuilds the schema model. When false, it performs a soft refresh that merges newly generated views with the existing model.", + "example": false + }, + "schedule": { + "type": "string", + "description": "AWS EventBridge cron expression (6 fields: minute hour day-of-month month day-of-week year). See https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-cron-expressions.html", + "example": "0 2 * * ? *" + }, + "scheduleId": { + "type": "string", + "format": "uuid", + "description": "Unique schedule identifier", + "example": "550e8400-e29b-41d4-a716-446655440001" + }, + "timezone": { + "type": "string", + "description": "IANA timezone for schedule execution", + "example": "America/New_York" + }, + "updatedAt": { + "type": "string", + "description": "Schedule last update timestamp (ISO 8601)", + "example": "2024-01-15T10:30:00Z" } }, "required": [ - "message", - "success" + "connectionId", + "createdAt", + "description", + "disabledAt", + "hardRefresh", + "schedule", + "scheduleId", + "timezone", + "updatedAt" ], - "description": "dbt update response", - "title": "ConnectionsDbtUpdateResponse" + "description": "Updated schedule response", + "title": "ConnectionsSchedulesUpdateResponse" } } } }, "400": { - "description": "Invalid request body or validation error" + "description": "Invalid cron expression or timezone" }, "401": { "description": "Authentication required" @@ -9753,13 +33441,13 @@ "description": "Permission denied - connection admin role required" }, "404": { - "description": "Connection not found" + "description": "Connection or schedule not found" } } }, "delete": { - "operationId": "connectionsDbtDelete", - "summary": "Delete dbt configuration", + "operationId": "connectionsSchedulesDelete", + "summary": "Delete schema refresh schedule", "tags": [ "Connections" ], @@ -9775,21 +33463,28 @@ "description": "Connection ID", "name": "connectionId", "in": "path" + }, + { + "schema": { + "type": "string", + "format": "uuid", + "description": "Schedule ID", + "example": "550e8400-e29b-41d4-a716-446655440001" + }, + "required": true, + "description": "Schedule ID", + "name": "scheduleId", + "in": "path" } ], "responses": { "200": { - "description": "dbt configuration deleted successfully", + "description": "Schema refresh schedule deleted successfully", "content": { "application/json": { "schema": { "type": "object", "properties": { - "message": { - "type": "string", - "description": "Success message", - "example": "dbt repository unlinked successfully" - }, "success": { "type": "boolean", "description": "Whether the operation succeeded", @@ -9797,11 +33492,10 @@ } }, "required": [ - "message", "success" ], - "description": "dbt delete response", - "title": "ConnectionsDbtDeleteResponse" + "description": "Delete schedule response", + "title": "ConnectionsSchedulesDeleteResponse" } } } @@ -9813,96 +33507,78 @@ "description": "Permission denied - connection admin role required" }, "404": { - "description": "Connection not found or dbt not configured" + "description": "Connection or schedule not found" } } } }, - "/api/v1/connections/{connectionId}/dbt/environments": { + "/api/v1/connection-environments": { "get": { - "description": "List all dbt environments for a connection.", - "operationId": "connectionsDbtEnvironmentsList", - "summary": "List dbt environments", + "operationId": "connectionEnvironmentsList", + "summary": "List connection environments", "tags": [ "Connections" ], - "parameters": [ - { - "schema": { - "type": "string", - "format": "uuid", - "description": "Connection ID", - "example": "550e8400-e29b-41d4-a716-446655440000" - }, - "required": true, - "description": "Connection ID", - "name": "connectionId", - "in": "path" - }, - { - "schema": { - "type": "string", - "description": "Cursor for pagination (from previous response nextCursor)", - "example": "eyJpZCI6IjEyMzQ1In0" - }, - "required": false, - "description": "Cursor for pagination (from previous response nextCursor)", - "name": "cursor", - "in": "query" - }, - { - "schema": { - "type": "number", - "minimum": 1, - "maximum": 100, - "default": 20, - "description": "Number of results per page (1-100)", - "example": 20 - }, - "required": false, - "description": "Number of results per page (1-100)", - "name": "pageSize", - "in": "query" - }, - { - "schema": { - "type": "string", - "enum": [ - "asc", - "desc" - ], - "default": "desc", - "description": "Sort direction for results", - "example": "desc" - }, - "required": false, - "description": "Sort direction for results", - "name": "sortDirection", - "in": "query" - }, - { - "schema": { - "type": "string", - "enum": [ - "name" - ], - "default": "name", - "description": "Field to sort results by", - "example": "name" - }, - "required": false, - "description": "Field to sort results by", - "name": "sortField", - "in": "query" - } - ], "responses": { "200": { - "description": "List of dbt environments", + "description": "List of connection environments", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/DbtEnvironmentListResponse" + "type": "object", + "properties": { + "connectionEnvironments": { + "type": "array", + "items": { + "type": "object", + "properties": { + "baseConnectionId": { + "type": "string", + "format": "uuid", + "description": "ID of the base connection", + "example": "550e8400-e29b-41d4-a716-446655440000" + }, + "connectionId": { + "type": "string", + "format": "uuid", + "description": "ID of the environment connection", + "example": "550e8400-e29b-41d4-a716-446655440002" + }, + "id": { + "type": "string", + "format": "uuid", + "description": "Unique connection environment identifier", + "example": "550e8400-e29b-41d4-a716-446655440001" + }, + "userAttributeValues": { + "type": "array", + "items": { + "type": "string" + }, + "description": "User attribute values for this environment", + "example": [ + "us-east", + "production" + ] + } + }, + "required": [ + "baseConnectionId", + "connectionId", + "id", + "userAttributeValues" + ], + "description": "Connection environment object", + "title": "ConnectionEnvironment" + }, + "description": "List of connection environments" + } + }, + "required": [ + "connectionEnvironments" + ], + "description": "List connection environments response", + "title": "ConnectionsEnvironmentsListResponse" } } } @@ -9911,83 +33587,134 @@ "description": "Authentication required" }, "403": { - "description": "Permission denied or connection does not support dbt" - }, - "404": { - "description": "Connection not found" + "description": "Permission denied - admin role required" } } }, "post": { - "description": "Create a new dbt environment for a connection.", - "operationId": "connectionsDbtEnvironmentsCreate", - "summary": "Create dbt environment", + "operationId": "connectionEnvironmentsCreate", + "summary": "Create connection environments", "tags": [ "Connections" ], - "parameters": [ - { - "schema": { - "type": "string", - "format": "uuid", - "description": "Connection ID", - "example": "550e8400-e29b-41d4-a716-446655440000" - }, - "required": true, - "description": "Connection ID", - "name": "connectionId", - "in": "path" - } - ], "requestBody": { - "required": true, "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/DbtEnvironmentCreateBody" + "type": "object", + "properties": { + "baseConnectionId": { + "type": "string", + "format": "uuid", + "description": "ID of the base connection", + "example": "550e8400-e29b-41d4-a716-446655440000" + }, + "environmentConnectionIds": { + "type": "array", + "items": { + "type": "string", + "format": "uuid" + }, + "description": "IDs of connections to use as environments", + "example": [ + "550e8400-e29b-41d4-a716-446655440002", + "550e8400-e29b-41d4-a716-446655440003" + ] + } + }, + "required": [ + "baseConnectionId", + "environmentConnectionIds" + ], + "description": "Request body for creating connection environments", + "title": "ConnectionsEnvironmentsCreateBody" } } } }, "responses": { "201": { - "description": "dbt environment created successfully", + "description": "Connection environments created successfully", "content": { "application/json": { "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/DbtEnvironmentItem" - }, - { - "description": "Created dbt environment", - "title": "DbtEnvironmentCreateResponse" + "type": "object", + "properties": { + "connectionEnvironments": { + "type": "array", + "items": { + "type": "object", + "properties": { + "baseConnectionId": { + "type": "string", + "format": "uuid", + "description": "ID of the base connection", + "example": "550e8400-e29b-41d4-a716-446655440000" + }, + "connectionId": { + "type": "string", + "format": "uuid", + "description": "ID of the environment connection", + "example": "550e8400-e29b-41d4-a716-446655440002" + }, + "id": { + "type": "string", + "format": "uuid", + "description": "Unique connection environment identifier", + "example": "550e8400-e29b-41d4-a716-446655440001" + }, + "userAttributeValues": { + "type": "array", + "items": { + "type": "string" + }, + "description": "User attribute values for this environment", + "example": [ + "us-east", + "production" + ] + } + }, + "required": [ + "baseConnectionId", + "connectionId", + "id", + "userAttributeValues" + ], + "description": "Connection environment object", + "title": "ConnectionEnvironment" + }, + "description": "Created connection environments" } - ] + }, + "required": [ + "connectionEnvironments" + ], + "description": "Create connection environments response", + "title": "ConnectionsEnvironmentsCreateResponse" } } } }, "400": { - "description": "Invalid request body" + "description": "Invalid request body or connection IDs" }, "401": { "description": "Authentication required" }, "403": { - "description": "Permission denied or connection does not support dbt" + "description": "Permission denied - admin role required" }, "404": { - "description": "Connection not found" + "description": "Base connection or environment connection not found" } } } }, - "/api/v1/connections/{connectionId}/dbt/environments/{environmentId}": { + "/api/v1/connection-environments/{id}": { "put": { - "description": "Update an existing dbt environment for a connection.", - "operationId": "connectionsDbtEnvironmentsUpdate", - "summary": "Update dbt environment", + "operationId": "connectionEnvironmentsUpdate", + "summary": "Update connection environment", "tags": [ "Connections" ], @@ -9996,52 +33723,61 @@ "schema": { "type": "string", "format": "uuid", - "description": "Connection ID", - "example": "550e8400-e29b-41d4-a716-446655440000" - }, - "required": true, - "description": "Connection ID", - "name": "connectionId", - "in": "path" - }, - { - "schema": { - "type": "string", - "format": "uuid", - "description": "Environment ID", - "example": "247dc6dc-2a58-4688-9521-c5ed3e99c1e8" + "description": "Connection environment ID", + "example": "550e8400-e29b-41d4-a716-446655440001" }, "required": true, - "description": "Environment ID", - "name": "environmentId", + "description": "Connection environment ID", + "name": "id", "in": "path" } ], "requestBody": { - "required": true, "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/DbtEnvironmentUpdateBody" + "type": "object", + "properties": { + "userAttributeValues": { + "type": "array", + "items": { + "type": "string" + }, + "description": "User attribute values for this environment", + "example": [ + "us-east", + "production" + ] + } + }, + "required": [ + "userAttributeValues" + ], + "description": "Request body for updating a connection environment", + "title": "ConnectionsEnvironmentsUpdateBody" } } } }, "responses": { "200": { - "description": "dbt environment updated successfully", + "description": "Connection environment updated successfully", "content": { "application/json": { "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/DbtEnvironmentItem" - }, - { - "description": "Updated dbt environment", - "title": "DbtEnvironmentUpdateResponse" + "type": "object", + "properties": { + "success": { + "type": "boolean", + "description": "Whether the operation succeeded", + "example": true } - ] + }, + "required": [ + "success" + ], + "description": "Update connection environment response", + "title": "ConnectionsEnvironmentsUpdateResponse" } } } @@ -10053,53 +33789,52 @@ "description": "Authentication required" }, "403": { - "description": "Permission denied or connection does not support dbt" + "description": "Permission denied - admin role required" }, "404": { - "description": "Connection or environment not found" + "description": "Connection environment not found" } - } - }, - "delete": { - "description": "Delete a dbt environment from a connection.", - "operationId": "connectionsDbtEnvironmentsDelete", - "summary": "Delete dbt environment", - "tags": [ - "Connections" - ], - "parameters": [ - { - "schema": { - "type": "string", - "format": "uuid", - "description": "Connection ID", - "example": "550e8400-e29b-41d4-a716-446655440000" - }, - "required": true, - "description": "Connection ID", - "name": "connectionId", - "in": "path" - }, + } + }, + "delete": { + "operationId": "connectionEnvironmentsDelete", + "summary": "Delete connection environment", + "tags": [ + "Connections" + ], + "parameters": [ { "schema": { "type": "string", "format": "uuid", - "description": "Environment ID", - "example": "247dc6dc-2a58-4688-9521-c5ed3e99c1e8" + "description": "Connection environment ID", + "example": "550e8400-e29b-41d4-a716-446655440001" }, "required": true, - "description": "Environment ID", - "name": "environmentId", + "description": "Connection environment ID", + "name": "id", "in": "path" } ], "responses": { "200": { - "description": "dbt environment deleted successfully", + "description": "Connection environment deleted successfully", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/DbtEnvironmentDeleteResponse" + "type": "object", + "properties": { + "success": { + "type": "boolean", + "description": "Whether the operation succeeded", + "example": true + } + }, + "required": [ + "success" + ], + "description": "Delete connection environment response", + "title": "ConnectionsEnvironmentsDeleteResponse" } } } @@ -10108,361 +33843,388 @@ "description": "Authentication required" }, "403": { - "description": "Permission denied or connection does not support dbt" + "description": "Permission denied - admin role required" }, "404": { - "description": "Connection or environment not found" + "description": "Connection environment not found" } } } }, - "/api/v1/connections/{connectionId}/schedules": { + "/api/v1/content": { "get": { - "operationId": "connectionsSchedulesList", - "summary": "List schema refresh schedules", + "operationId": "contentList", + "summary": "List content", "tags": [ - "Connections" + "Content" ], "parameters": [ + { + "schema": { + "type": "string", + "description": "Cursor for pagination (from previous response nextCursor)", + "example": "eyJpZCI6IjEyMzQ1In0" + }, + "required": false, + "description": "Cursor for pagination (from previous response nextCursor)", + "name": "cursor", + "in": "query" + }, + { + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 100, + "default": 20, + "description": "Number of results per page (1-100, integer)", + "example": 20 + }, + "required": false, + "description": "Number of results per page (1-100, integer)", + "name": "pageSize", + "in": "query" + }, { "schema": { "type": "string", "format": "uuid", - "description": "Connection ID", - "example": "550e8400-e29b-41d4-a716-446655440000" + "description": "Filter by creator user ID" }, - "required": true, - "description": "Connection ID", - "name": "connectionId", - "in": "path" + "required": false, + "description": "Filter by creator user ID", + "name": "creatorId", + "in": "query" + }, + { + "schema": { + "type": "string", + "format": "uuid", + "description": "Filter by folder ID (cannot be used with path)" + }, + "required": false, + "description": "Filter by folder ID (cannot be used with path)", + "name": "folderId", + "in": "query" + }, + { + "schema": { + "type": "string", + "description": "Comma-separated list of fields to include (e.g., _count,labels)" + }, + "required": false, + "description": "Comma-separated list of fields to include (e.g., _count,labels)", + "name": "include", + "in": "query" + }, + { + "schema": { + "type": "string", + "description": "Filter by folder path (cannot be used with folderId)", + "example": "/reports/sales" + }, + "required": false, + "description": "Filter by folder path (cannot be used with folderId)", + "name": "path", + "in": "query" + }, + { + "schema": { + "type": "string", + "enum": [ + "organization", + "restricted" + ], + "description": "Filter by share scope", + "example": "organization" + }, + "required": false, + "description": "Filter by share scope", + "name": "scope", + "in": "query" + }, + { + "schema": { + "type": "string", + "enum": [ + "asc", + "desc" + ], + "description": "Sort direction", + "example": "asc" + }, + "required": false, + "description": "Sort direction", + "name": "sortDirection", + "in": "query" + }, + { + "schema": { + "type": "string", + "enum": [ + "name", + "favorites" + ], + "description": "Field to sort by", + "example": "name" + }, + "required": false, + "description": "Field to sort by", + "name": "sortField", + "in": "query" } ], "responses": { "200": { - "description": "List of schema refresh schedules", + "description": "List of content (documents and folders)", "content": { "application/json": { "schema": { - "type": "object", - "properties": { - "schedules": { - "type": "array", - "items": { - "type": "object", - "properties": { - "connectionId": { - "type": "string", - "format": "uuid", - "description": "Connection ID this schedule belongs to", - "example": "550e8400-e29b-41d4-a716-446655440000" - }, - "createdAt": { - "type": "string", - "description": "Schedule creation timestamp (ISO 8601)", - "example": "2024-01-15T10:30:00Z" - }, - "description": { - "type": "string", - "description": "Human-readable schedule description", - "example": "Runs daily at 2:00 AM EST" - }, - "disabledAt": { - "type": [ - "string", - "null" - ], - "description": "Timestamp when schedule was disabled (ISO 8601)", - "example": null - }, - "schedule": { - "type": "string", - "description": "AWS EventBridge cron expression (6 fields: minute hour day-of-month month day-of-week year). See https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-cron-expressions.html", - "example": "0 2 * * ? *" - }, - "scheduleId": { - "type": "string", - "format": "uuid", - "description": "Unique schedule identifier", - "example": "550e8400-e29b-41d4-a716-446655440001" - }, - "timezone": { - "type": "string", - "description": "IANA timezone for schedule execution", - "example": "America/New_York" - }, - "updatedAt": { - "type": "string", - "description": "Schedule last update timestamp (ISO 8601)", - "example": "2024-01-15T10:30:00Z" - } - }, - "required": [ - "connectionId", - "createdAt", - "description", - "disabledAt", - "schedule", - "scheduleId", - "timezone", - "updatedAt" - ], - "description": "Schema refresh schedule object", - "title": "ConnectionSchedule" - }, - "description": "List of schema refresh schedules" - } - }, - "required": [ - "schedules" - ], - "description": "List schedules response", - "title": "ConnectionsSchedulesListResponse" + "$ref": "#/components/schemas/ContentListResponse" } } } }, + "400": { + "description": "Invalid query parameters (cannot use both folderId and path)" + }, "401": { "description": "Authentication required" }, - "403": { - "description": "Permission denied - connection admin role required" - }, "404": { - "description": "Connection not found" + "description": "Folder not found (when filtering by path)" } } - }, + } + }, + "/api/v1/dashboards/{identifier}/download": { "post": { - "operationId": "connectionsSchedulesCreate", - "summary": "Create schema refresh schedule", + "operationId": "dashboardsDownload", + "summary": "Initiate dashboard download", "tags": [ - "Connections" + "Dashboards" ], "parameters": [ + { + "schema": { + "type": "string", + "description": "Dashboard identifier (short ID or UUID)", + "example": "12db1a0a" + }, + "required": true, + "description": "Dashboard identifier (short ID or UUID)", + "name": "identifier", + "in": "path" + }, { "schema": { "type": "string", "format": "uuid", - "description": "Connection ID", - "example": "550e8400-e29b-41d4-a716-446655440000" + "description": "Target user membership ID (for org-scoped API keys)" }, - "required": true, - "description": "Connection ID", - "name": "connectionId", - "in": "path" + "required": false, + "description": "Target user membership ID (for org-scoped API keys)", + "name": "userId", + "in": "query" } ], "requestBody": { "content": { "application/json": { "schema": { - "type": "object", - "properties": { - "schedule": { - "type": "string", - "description": "AWS EventBridge cron expression (6 fields: minute hour day-of-month month day-of-week year). See https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-cron-expressions.html", - "example": "0 2 * * ? *" - }, - "timezone": { - "type": "string", - "description": "IANA timezone for schedule execution", - "example": "America/New_York" - } - }, - "required": [ - "schedule", - "timezone" - ], - "description": "Request body for creating a schema refresh schedule", - "title": "ConnectionsSchedulesCreateBody" + "$ref": "#/components/schemas/DashboardsDownloadBody" } } } }, "responses": { - "201": { - "description": "Schema refresh schedule created successfully", + "200": { + "description": "Download job initiated successfully", "content": { "application/json": { "schema": { - "type": "object", - "properties": { - "connectionId": { - "type": "string", - "format": "uuid", - "description": "Connection ID this schedule belongs to", - "example": "550e8400-e29b-41d4-a716-446655440000" - }, - "createdAt": { - "type": "string", - "description": "Schedule creation timestamp (ISO 8601)", - "example": "2024-01-15T10:30:00Z" - }, - "description": { - "type": "string", - "description": "Human-readable schedule description", - "example": "Runs daily at 2:00 AM EST" - }, - "disabledAt": { - "type": [ - "string", - "null" - ], - "description": "Timestamp when schedule was disabled (ISO 8601)", - "example": null - }, - "schedule": { - "type": "string", - "description": "AWS EventBridge cron expression (6 fields: minute hour day-of-month month day-of-week year). See https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-cron-expressions.html", - "example": "0 2 * * ? *" - }, - "scheduleId": { - "type": "string", - "format": "uuid", - "description": "Unique schedule identifier", - "example": "550e8400-e29b-41d4-a716-446655440001" - }, - "timezone": { - "type": "string", - "description": "IANA timezone for schedule execution", - "example": "America/New_York" - }, - "updatedAt": { - "type": "string", - "description": "Schedule last update timestamp (ISO 8601)", - "example": "2024-01-15T10:30:00Z" - } - }, - "required": [ - "connectionId", - "createdAt", - "description", - "disabledAt", - "schedule", - "scheduleId", - "timezone", - "updatedAt" - ], - "description": "Created schedule response", - "title": "ConnectionsSchedulesCreateResponse" + "$ref": "#/components/schemas/DashboardsDownloadResponse" } } } }, "400": { - "description": "Invalid cron expression or timezone" + "description": "Invalid request body or filter configuration" }, "401": { "description": "Authentication required" }, "403": { - "description": "Permission denied - connection admin role required" + "description": "Permission denied - cannot download this dashboard" }, "404": { - "description": "Connection not found" + "description": "Dashboard not found" + }, + "409": { + "description": "Download already in progress for this dashboard" + }, + "500": { + "description": "Failed to initiate download" } } } }, - "/api/v1/connections/{connectionId}/schedules/{scheduleId}": { + "/api/v1/dashboards/{identifier}/download/{jobId}": { "get": { - "operationId": "connectionsSchedulesGet", - "summary": "Get schema refresh schedule", + "operationId": "dashboardsDownloadFile", + "summary": "Get download file", "tags": [ - "Connections" + "Dashboards" ], "parameters": [ + { + "schema": { + "type": "string", + "description": "Dashboard identifier (short ID or UUID)", + "example": "12db1a0a" + }, + "required": true, + "description": "Dashboard identifier (short ID or UUID)", + "name": "identifier", + "in": "path" + }, + { + "schema": { + "type": "string", + "description": "Download job ID (UUID)", + "example": "123e4567-e89b-12d3-a456-426614174000" + }, + "required": true, + "description": "Download job ID (UUID)", + "name": "jobId", + "in": "path" + }, { "schema": { "type": "string", "format": "uuid", - "description": "Connection ID", - "example": "550e8400-e29b-41d4-a716-446655440000" + "description": "Target user membership ID (for org-scoped API keys)" + }, + "required": false, + "description": "Target user membership ID (for org-scoped API keys)", + "name": "userId", + "in": "query" + } + ], + "responses": { + "200": { + "description": "File ready - binary content streamed" + }, + "202": { + "description": "Download job still in progress" + }, + "401": { + "description": "Authentication required" + }, + "404": { + "description": "Dashboard or download job not found" + }, + "410": { + "description": "Download job failed" + }, + "500": { + "description": "Failed to retrieve download artifact" + } + } + } + }, + "/api/v1/dashboards/{identifier}/download/{jobId}/status": { + "get": { + "operationId": "dashboardsDownloadStatus", + "summary": "Get download job status", + "tags": [ + "Dashboards" + ], + "parameters": [ + { + "schema": { + "type": "string", + "description": "Dashboard identifier (short ID or UUID)", + "example": "12db1a0a" }, "required": true, - "description": "Connection ID", - "name": "connectionId", + "description": "Dashboard identifier (short ID or UUID)", + "name": "identifier", + "in": "path" + }, + { + "schema": { + "type": "string", + "description": "Download job ID (UUID)", + "example": "123e4567-e89b-12d3-a456-426614174000" + }, + "required": true, + "description": "Download job ID (UUID)", + "name": "jobId", "in": "path" }, { "schema": { "type": "string", "format": "uuid", - "description": "Schedule ID", - "example": "550e8400-e29b-41d4-a716-446655440001" + "description": "Target user membership ID (for org-scoped API keys)" + }, + "required": false, + "description": "Target user membership ID (for org-scoped API keys)", + "name": "userId", + "in": "query" + } + ], + "responses": { + "200": { + "description": "Download job status" + }, + "401": { + "description": "Authentication required" + }, + "404": { + "description": "Dashboard or download job not found" + } + } + } + }, + "/api/v1/dashboards/{identifier}/filters": { + "get": { + "operationId": "dashboardsGetFilters", + "summary": "Get dashboard filters", + "tags": [ + "Dashboards" + ], + "parameters": [ + { + "schema": { + "type": "string", + "description": "Dashboard identifier (short ID or UUID)", + "example": "12db1a0a" }, "required": true, - "description": "Schedule ID", - "name": "scheduleId", + "description": "Dashboard identifier (short ID or UUID)", + "name": "identifier", "in": "path" + }, + { + "schema": { + "type": "string", + "format": "uuid", + "description": "Target user membership ID (for org-scoped API keys)" + }, + "required": false, + "description": "Target user membership ID (for org-scoped API keys)", + "name": "userId", + "in": "query" } ], "responses": { "200": { - "description": "Schema refresh schedule details", + "description": "Dashboard filter and control configuration", "content": { "application/json": { "schema": { - "type": "object", - "properties": { - "connectionId": { - "type": "string", - "format": "uuid", - "description": "Connection ID this schedule belongs to", - "example": "550e8400-e29b-41d4-a716-446655440000" - }, - "createdAt": { - "type": "string", - "description": "Schedule creation timestamp (ISO 8601)", - "example": "2024-01-15T10:30:00Z" - }, - "description": { - "type": "string", - "description": "Human-readable schedule description", - "example": "Runs daily at 2:00 AM EST" - }, - "disabledAt": { - "type": [ - "string", - "null" - ], - "description": "Timestamp when schedule was disabled (ISO 8601)", - "example": null - }, - "schedule": { - "type": "string", - "description": "AWS EventBridge cron expression (6 fields: minute hour day-of-month month day-of-week year). See https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-cron-expressions.html", - "example": "0 2 * * ? *" - }, - "scheduleId": { - "type": "string", - "format": "uuid", - "description": "Unique schedule identifier", - "example": "550e8400-e29b-41d4-a716-446655440001" - }, - "timezone": { - "type": "string", - "description": "IANA timezone for schedule execution", - "example": "America/New_York" - }, - "updatedAt": { - "type": "string", - "description": "Schedule last update timestamp (ISO 8601)", - "example": "2024-01-15T10:30:00Z" - } - }, - "required": [ - "connectionId", - "createdAt", - "description", - "disabledAt", - "schedule", - "scheduleId", - "timezone", - "updatedAt" - ], - "description": "Get schedule response", - "title": "ConnectionsSchedulesGetResponse" + "$ref": "#/components/schemas/DashboardFiltersResponse" } } } @@ -10471,440 +34233,378 @@ "description": "Authentication required" }, "403": { - "description": "Permission denied - connection admin role required" + "description": "Permission denied - VIEWER role required" }, "404": { - "description": "Connection or schedule not found" + "description": "Dashboard not found" } } }, - "put": { - "operationId": "connectionsSchedulesUpdate", - "summary": "Update schema refresh schedule", + "patch": { + "operationId": "dashboardsUpdateFilters", + "summary": "Update dashboard filters", "tags": [ - "Connections" + "Dashboards" ], "parameters": [ { "schema": { "type": "string", - "format": "uuid", - "description": "Connection ID", - "example": "550e8400-e29b-41d4-a716-446655440000" + "description": "Dashboard identifier (short ID or UUID)", + "example": "12db1a0a" }, "required": true, - "description": "Connection ID", - "name": "connectionId", + "description": "Dashboard identifier (short ID or UUID)", + "name": "identifier", "in": "path" }, { "schema": { "type": "string", "format": "uuid", - "description": "Schedule ID", - "example": "550e8400-e29b-41d4-a716-446655440001" + "description": "Target user membership ID (for org-scoped API keys)" }, - "required": true, - "description": "Schedule ID", - "name": "scheduleId", - "in": "path" + "required": false, + "description": "Target user membership ID (for org-scoped API keys)", + "name": "userId", + "in": "query" } ], "requestBody": { "content": { "application/json": { "schema": { - "type": "object", - "properties": { - "schedule": { - "type": "string", - "description": "AWS EventBridge cron expression (6 fields: minute hour day-of-month month day-of-week year). See https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-cron-expressions.html", - "example": "0 2 * * ? *" - }, - "timezone": { - "type": "string", - "description": "IANA timezone for schedule execution", - "example": "America/New_York" - } - }, - "required": [ - "schedule", - "timezone" - ], - "description": "Request body for updating a schema refresh schedule", - "title": "ConnectionsSchedulesUpdateBody" + "$ref": "#/components/schemas/DashboardsUpdateFiltersBody" } } } }, "responses": { "200": { - "description": "Schema refresh schedule updated successfully", + "description": "Filters updated successfully", "content": { "application/json": { "schema": { - "type": "object", - "properties": { - "connectionId": { - "type": "string", - "format": "uuid", - "description": "Connection ID this schedule belongs to", - "example": "550e8400-e29b-41d4-a716-446655440000" - }, - "createdAt": { - "type": "string", - "description": "Schedule creation timestamp (ISO 8601)", - "example": "2024-01-15T10:30:00Z" - }, - "description": { - "type": "string", - "description": "Human-readable schedule description", - "example": "Runs daily at 2:00 AM EST" - }, - "disabledAt": { - "type": [ - "string", - "null" - ], - "description": "Timestamp when schedule was disabled (ISO 8601)", - "example": null - }, - "schedule": { - "type": "string", - "description": "AWS EventBridge cron expression (6 fields: minute hour day-of-month month day-of-week year). See https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-cron-expressions.html", - "example": "0 2 * * ? *" - }, - "scheduleId": { - "type": "string", - "format": "uuid", - "description": "Unique schedule identifier", - "example": "550e8400-e29b-41d4-a716-446655440001" - }, - "timezone": { - "type": "string", - "description": "IANA timezone for schedule execution", - "example": "America/New_York" - }, - "updatedAt": { - "type": "string", - "description": "Schedule last update timestamp (ISO 8601)", - "example": "2024-01-15T10:30:00Z" - } - }, - "required": [ - "connectionId", - "createdAt", - "description", - "disabledAt", - "schedule", - "scheduleId", - "timezone", - "updatedAt" - ], - "description": "Updated schedule response", - "title": "ConnectionsSchedulesUpdateResponse" + "$ref": "#/components/schemas/DashboardFiltersResponse" } } } }, "400": { - "description": "Invalid cron expression or timezone" + "description": "Invalid request body - must include at least one filter, control, or filterOrder" }, "401": { "description": "Authentication required" }, - "403": { - "description": "Permission denied - connection admin role required" + "403": { + "description": "Permission denied - EDITOR role required" + }, + "404": { + "description": "Dashboard not found or document does not have a dashboard" + }, + "409": { + "description": "Conflict - draft already exists. Set clearExistingDraft to true to proceed." + } + } + } + }, + "/api/v1/documents": { + "get": { + "operationId": "documentsList", + "summary": "List documents", + "tags": [ + "Documents" + ], + "parameters": [ + { + "schema": { + "type": "string", + "format": "uuid", + "description": "Filter by creator membership ID" + }, + "required": false, + "description": "Filter by creator membership ID", + "name": "creatorId", + "in": "query" + }, + { + "schema": { + "type": "string", + "description": "Cursor for pagination" + }, + "required": false, + "description": "Cursor for pagination", + "name": "cursor", + "in": "query" + }, + { + "schema": { + "type": "string", + "format": "uuid", + "description": "Filter by folder ID" + }, + "required": false, + "description": "Filter by folder ID", + "name": "folderId", + "in": "query" + }, + { + "schema": { + "type": "string", + "description": "Comma-separated list of additional fields to include: _count, labels, includeDeleted, onlyFavorites, onlySharedWithMe. onlySharedWithMe requires userId or user-scoped key and cannot be combined with onlyFavorites or folderId.", + "example": "_count,labels" + }, + "required": false, + "description": "Comma-separated list of additional fields to include: _count, labels, includeDeleted, onlyFavorites, onlySharedWithMe. onlySharedWithMe requires userId or user-scoped key and cannot be combined with onlyFavorites or folderId.", + "name": "include", + "in": "query" + }, + { + "schema": { + "type": "string", + "description": "Comma-separated list of label names to filter by", + "example": "verified,important" + }, + "required": false, + "description": "Comma-separated list of label names to filter by", + "name": "labels", + "in": "query" + }, + { + "schema": { + "type": "integer", + "exclusiveMinimum": 0, + "default": 50, + "description": "Number of records per page" + }, + "required": false, + "description": "Number of records per page", + "name": "pageSize", + "in": "query" + }, + { + "schema": { + "type": "string", + "enum": [ + "asc", + "desc" + ], + "default": "asc", + "description": "Sort direction" + }, + "required": false, + "description": "Sort direction", + "name": "sortDirection", + "in": "query" }, - "404": { - "description": "Connection or schedule not found" - } - } - }, - "delete": { - "operationId": "connectionsSchedulesDelete", - "summary": "Delete schema refresh schedule", - "tags": [ - "Connections" - ], - "parameters": [ { "schema": { "type": "string", - "format": "uuid", - "description": "Connection ID", - "example": "550e8400-e29b-41d4-a716-446655440000" + "enum": [ + "name", + "favorites", + "updatedAt", + "visits" + ], + "default": "name", + "description": "Field to sort by" }, - "required": true, - "description": "Connection ID", - "name": "connectionId", - "in": "path" + "required": false, + "description": "Field to sort by", + "name": "sortField", + "in": "query" }, { "schema": { "type": "string", "format": "uuid", - "description": "Schedule ID", - "example": "550e8400-e29b-41d4-a716-446655440001" + "description": "Filter documents visible to this membership ID" }, - "required": true, - "description": "Schedule ID", - "name": "scheduleId", - "in": "path" + "required": false, + "description": "Filter documents visible to this membership ID", + "name": "userId", + "in": "query" } ], "responses": { "200": { - "description": "Schema refresh schedule deleted successfully", + "description": "Paginated list of documents", "content": { "application/json": { "schema": { - "type": "object", - "properties": { - "success": { - "type": "boolean", - "description": "Whether the operation succeeded", - "example": true - } - }, - "required": [ - "success" - ], - "description": "Delete schedule response", - "title": "ConnectionsSchedulesDeleteResponse" + "$ref": "#/components/schemas/DocumentsListResponse" + } + } + } + }, + "401": { + "description": "Authentication required" + } + } + }, + "post": { + "operationId": "documentsCreate", + "summary": "Create document", + "tags": [ + "Documents" + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DocumentsCreateBody" + } + } + } + }, + "responses": { + "201": { + "description": "Document created successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DocumentsCreateResponse" } } } }, + "400": { + "description": "Invalid request body" + }, "401": { "description": "Authentication required" }, "403": { - "description": "Permission denied - connection admin role required" + "description": "Permission denied" }, "404": { - "description": "Connection or schedule not found" + "description": "Model or branch not found" } } } }, - "/api/v1/connection-environments": { + "/api/v1/documents/{identifier}": { "get": { - "operationId": "connectionEnvironmentsList", - "summary": "List connection environments", + "description": "Retrieves a document's configuration in a format compatible with PUT for round-trip editing. GET a document, modify the response, and PUT it back to update. Only dashboard documents are supported; analysis documents return 400.", + "operationId": "documentsGet", + "summary": "Get document", "tags": [ - "Connections" + "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" + } ], "responses": { "200": { - "description": "List of connection environments", + "description": "Document details", "content": { "application/json": { "schema": { - "type": "object", - "properties": { - "connectionEnvironments": { - "type": "array", - "items": { - "type": "object", - "properties": { - "baseConnectionId": { - "type": "string", - "format": "uuid", - "description": "ID of the base connection", - "example": "550e8400-e29b-41d4-a716-446655440000" - }, - "connectionId": { - "type": "string", - "format": "uuid", - "description": "ID of the environment connection", - "example": "550e8400-e29b-41d4-a716-446655440002" - }, - "id": { - "type": "string", - "format": "uuid", - "description": "Unique connection environment identifier", - "example": "550e8400-e29b-41d4-a716-446655440001" - }, - "userAttributeValues": { - "type": "array", - "items": { - "type": "string" - }, - "description": "User attribute values for this environment", - "example": [ - "us-east", - "production" - ] - } - }, - "required": [ - "baseConnectionId", - "connectionId", - "id", - "userAttributeValues" - ], - "description": "Connection environment object", - "title": "ConnectionEnvironment" - }, - "description": "List of connection environments" - } - }, - "required": [ - "connectionEnvironments" - ], - "description": "List connection environments response", - "title": "ConnectionsEnvironmentsListResponse" + "$ref": "#/components/schemas/DocumentsGetResponse" } } } }, + "400": { + "description": "Analysis documents are not supported" + }, "401": { "description": "Authentication required" }, "403": { - "description": "Permission denied - admin role required" + "description": "Insufficient permissions to view the document" + }, + "404": { + "description": "Document not found" } } }, - "post": { - "operationId": "connectionEnvironmentsCreate", - "summary": "Create connection environments", + "put": { + "deprecated": true, + "description": "**Deprecated** — use `PATCH /api/v2/documents/{identifier}/draft` (and the related `/draft` routes). Removal scheduled per the `Sunset` response header.\n\nUpdates a document with the specified identifier. This endpoint performs a full resource replacement — all required fields must be provided and existing query presentations are replaced entirely. Only dashboard documents are supported; analysis documents and documents without an associated dashboard return 400. For published documents, the update goes through a draft/publish workflow automatically; if a draft already exists, the request returns 409 unless `clearExistingDraft` is set to `true`.", + "operationId": "documentsPut", + "summary": "Replace document (full replacement)", "tags": [ - "Connections" + "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": { - "type": "object", - "properties": { - "baseConnectionId": { - "type": "string", - "format": "uuid", - "description": "ID of the base connection", - "example": "550e8400-e29b-41d4-a716-446655440000" - }, - "environmentConnectionIds": { - "type": "array", - "items": { - "type": "string", - "format": "uuid" - }, - "description": "IDs of connections to use as environments", - "example": [ - "550e8400-e29b-41d4-a716-446655440002", - "550e8400-e29b-41d4-a716-446655440003" - ] - } - }, - "required": [ - "baseConnectionId", - "environmentConnectionIds" - ], - "description": "Request body for creating connection environments", - "title": "ConnectionsEnvironmentsCreateBody" + "$ref": "#/components/schemas/DocumentsPutBody" } } } }, "responses": { - "201": { - "description": "Connection environments created successfully", + "200": { + "description": "Document replaced successfully", "content": { "application/json": { "schema": { - "type": "object", - "properties": { - "connectionEnvironments": { - "type": "array", - "items": { - "type": "object", - "properties": { - "baseConnectionId": { - "type": "string", - "format": "uuid", - "description": "ID of the base connection", - "example": "550e8400-e29b-41d4-a716-446655440000" - }, - "connectionId": { - "type": "string", - "format": "uuid", - "description": "ID of the environment connection", - "example": "550e8400-e29b-41d4-a716-446655440002" - }, - "id": { - "type": "string", - "format": "uuid", - "description": "Unique connection environment identifier", - "example": "550e8400-e29b-41d4-a716-446655440001" - }, - "userAttributeValues": { - "type": "array", - "items": { - "type": "string" - }, - "description": "User attribute values for this environment", - "example": [ - "us-east", - "production" - ] - } - }, - "required": [ - "baseConnectionId", - "connectionId", - "id", - "userAttributeValues" - ], - "description": "Connection environment object", - "title": "ConnectionEnvironment" - }, - "description": "Created connection environments" - } - }, - "required": [ - "connectionEnvironments" - ], - "description": "Create connection environments response", - "title": "ConnectionsEnvironmentsCreateResponse" + "$ref": "#/components/schemas/DocumentsPutResponse" } } } }, "400": { - "description": "Invalid request body or connection IDs" + "description": "Invalid request body, missing required fields, or validation error (also returned for analysis documents and documents without an associated dashboard)" }, "401": { "description": "Authentication required" }, "403": { - "description": "Permission denied - admin role required" + "description": "Insufficient permissions to update the document" }, "404": { - "description": "Base connection or environment connection not found" + "description": "Document not found" + }, + "409": { + "description": "Draft already exists - set clearExistingDraft to true to discard it and proceed" } } - } - }, - "/api/v1/connection-environments/{id}": { - "put": { - "operationId": "connectionEnvironmentsUpdate", - "summary": "Update connection environment", + }, + "patch": { + "deprecated": true, + "description": "**Deprecated** — use `PATCH /api/v2/documents/{identifier}/draft` (and the related `/draft` routes). Removal scheduled per the `Sunset` response header.\n\nUpdates a document's name, description, and/or identifier. This is a partial update — only provided fields are modified, and at least one of `name`, `description`, or `identifier` must be supplied. When `identifier` is changed, the previous identifier is retained in the document identifier history and continues to redirect. For published documents, the update goes through a draft/publish workflow automatically.", + "operationId": "documentsUpdate", + "summary": "Rename document", "tags": [ - "Connections" + "Documents" ], "parameters": [ { "schema": { "type": "string", - "format": "uuid", - "description": "Connection environment ID", - "example": "550e8400-e29b-41d4-a716-446655440001" + "description": "Document identifier (either document ID or identifier slug)", + "example": "abc123" }, "required": true, - "description": "Connection environment ID", - "name": "id", + "description": "Document identifier (either document ID or identifier slug)", + "name": "identifier", "in": "path" } ], @@ -10912,105 +34612,65 @@ "content": { "application/json": { "schema": { - "type": "object", - "properties": { - "userAttributeValues": { - "type": "array", - "items": { - "type": "string" - }, - "description": "User attribute values for this environment", - "example": [ - "us-east", - "production" - ] - } - }, - "required": [ - "userAttributeValues" - ], - "description": "Request body for updating a connection environment", - "title": "ConnectionsEnvironmentsUpdateBody" + "$ref": "#/components/schemas/DocumentsUpdateBody" } } } }, "responses": { "200": { - "description": "Connection environment updated successfully", + "description": "Document updated successfully", "content": { "application/json": { "schema": { - "type": "object", - "properties": { - "success": { - "type": "boolean", - "description": "Whether the operation succeeded", - "example": true - } - }, - "required": [ - "success" - ], - "description": "Update connection environment response", - "title": "ConnectionsEnvironmentsUpdateResponse" + "$ref": "#/components/schemas/DocumentsUpdateResponse" } } } }, "400": { - "description": "Invalid request body" + "description": "Invalid request body or validation error (e.g. missing name/description/identifier, name too long, identifier already in use)" }, "401": { "description": "Authentication required" }, "403": { - "description": "Permission denied - admin role required" + "description": "Permission denied - EDITOR role required" }, "404": { - "description": "Connection environment not found" + "description": "Document not found" + }, + "409": { + "description": "Draft already exists - set clearExistingDraft to true to discard it and proceed" } } }, "delete": { - "operationId": "connectionEnvironmentsDelete", - "summary": "Delete connection environment", + "operationId": "documentsDelete", + "summary": "Delete document", "tags": [ - "Connections" + "Documents" ], "parameters": [ { "schema": { "type": "string", - "format": "uuid", - "description": "Connection environment ID", - "example": "550e8400-e29b-41d4-a716-446655440001" + "description": "Document identifier (either document ID or identifier slug)", + "example": "abc123" }, "required": true, - "description": "Connection environment ID", - "name": "id", + "description": "Document identifier (either document ID or identifier slug)", + "name": "identifier", "in": "path" } ], "responses": { "200": { - "description": "Connection environment deleted successfully", + "description": "Document deleted successfully", "content": { "application/json": { "schema": { - "type": "object", - "properties": { - "success": { - "type": "boolean", - "description": "Whether the operation succeeded", - "example": true - } - }, - "required": [ - "success" - ], - "description": "Delete connection environment response", - "title": "ConnectionsEnvironmentsDeleteResponse" + "$ref": "#/components/schemas/SuccessResponse" } } } @@ -11019,628 +34679,594 @@ "description": "Authentication required" }, "403": { - "description": "Permission denied - admin role required" + "description": "Permission denied - MANAGER role required" }, "404": { - "description": "Connection environment not found" + "description": "Document not found" } } } }, - "/api/v1/content": { + "/api/v1/documents/{identifier}/queries": { "get": { - "operationId": "contentList", - "summary": "List content", + "operationId": "documentsGetQueries", + "summary": "List document queries", "tags": [ - "Content" + "Documents" ], "parameters": [ { "schema": { "type": "string", - "description": "Cursor for pagination (from previous response nextCursor)", - "example": "eyJpZCI6IjEyMzQ1In0" - }, - "required": false, - "description": "Cursor for pagination (from previous response nextCursor)", - "name": "cursor", - "in": "query" - }, - { - "schema": { - "type": "number", - "minimum": 1, - "maximum": 100, - "default": 20, - "description": "Number of results per page (1-100)", - "example": 20 - }, - "required": false, - "description": "Number of results per page (1-100)", - "name": "pageSize", - "in": "query" - }, - { - "schema": { - "type": "string", - "format": "uuid", - "description": "Filter by creator user ID" - }, - "required": false, - "description": "Filter by creator user ID", - "name": "creatorId", - "in": "query" - }, - { - "schema": { - "type": "string", - "format": "uuid", - "description": "Filter by folder ID (cannot be used with path)" - }, - "required": false, - "description": "Filter by folder ID (cannot be used with path)", - "name": "folderId", - "in": "query" - }, - { - "schema": { - "type": "string", - "description": "Comma-separated list of fields to include (e.g., _count,labels)" - }, - "required": false, - "description": "Comma-separated list of fields to include (e.g., _count,labels)", - "name": "include", - "in": "query" - }, - { - "schema": { - "type": "string", - "description": "Filter by folder path (cannot be used with folderId)", - "example": "/reports/sales" + "description": "Document identifier (either document ID or identifier slug)", + "example": "abc123" }, - "required": false, - "description": "Filter by folder path (cannot be used with folderId)", - "name": "path", - "in": "query" + "required": true, + "description": "Document identifier (either document ID or identifier slug)", + "name": "identifier", + "in": "path" + } + ], + "responses": { + "200": { + "description": "List of queries in the document", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DocumentsGetQueriesResponse" + } + } + } }, - { - "schema": { - "type": "string", - "enum": [ - "organization", - "restricted" - ], - "description": "Filter by share scope", - "example": "organization" - }, - "required": false, - "description": "Filter by share scope", - "name": "scope", - "in": "query" + "401": { + "description": "Authentication required" }, - { - "schema": { - "type": "string", - "enum": [ - "asc", - "desc" - ], - "description": "Sort direction", - "example": "asc" - }, - "required": false, - "description": "Sort direction", - "name": "sortDirection", - "in": "query" + "403": { + "description": "Permission denied" }, + "404": { + "description": "Document not found" + } + } + } + }, + "/api/v1/documents/{identifier}/move": { + "put": { + "operationId": "documentsMove", + "summary": "Move document", + "tags": [ + "Documents" + ], + "parameters": [ { "schema": { "type": "string", - "enum": [ - "name", - "favorites" - ], - "description": "Field to sort by", - "example": "name" + "description": "Document identifier (either document ID or identifier slug)", + "example": "abc123" }, - "required": false, - "description": "Field to sort by", - "name": "sortField", - "in": "query" + "required": true, + "description": "Document identifier (either document ID or identifier slug)", + "name": "identifier", + "in": "path" } ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DocumentsMoveBody" + } + } + } + }, "responses": { "200": { - "description": "List of content (documents and folders)", + "description": "Document moved successfully", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ContentListResponse" + "$ref": "#/components/schemas/SuccessResponse" } } } }, "400": { - "description": "Invalid query parameters (cannot use both folderId and path)" + "description": "Invalid folder path or scope" }, "401": { "description": "Authentication required" }, + "403": { + "description": "Permission denied - MANAGER role required" + }, "404": { - "description": "Folder not found (when filtering by path)" + "description": "Document or folder not found" } } } }, - "/api/v1/dashboards/{identifier}/download": { - "post": { - "operationId": "dashboardsDownload", - "summary": "Initiate dashboard download", + "/api/v1/documents/{identifier}/permissions": { + "get": { + "operationId": "documentsGetPermissions", + "summary": "Get document permissions", "tags": [ - "Dashboards" + "Documents" ], "parameters": [ { "schema": { "type": "string", - "description": "Dashboard identifier (short ID or UUID)", - "example": "12db1a0a" + "description": "Document identifier (either document ID or identifier slug)", + "example": "abc123" }, "required": true, - "description": "Dashboard identifier (short ID or UUID)", + "description": "Document identifier (either document ID or identifier slug)", "name": "identifier", "in": "path" }, { "schema": { "type": "string", - "description": "Target user membership ID (for org-scoped API keys)" + "format": "uuid", + "description": "User membership ID to check permissions for" }, - "required": false, - "description": "Target user membership ID (for org-scoped API keys)", + "required": true, + "description": "User membership ID to check permissions for", "name": "userId", "in": "query" } ], + "responses": { + "200": { + "description": "User permissions for the document", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DocumentsGetPermissionsResponse" + } + } + } + }, + "401": { + "description": "Authentication required" + }, + "403": { + "description": "Permission denied" + }, + "404": { + "description": "Document or user not found" + } + } + }, + "put": { + "operationId": "documentsUpdatePermissionSettings", + "summary": "Update document permission settings", + "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/DashboardsDownloadBody" + "$ref": "#/components/schemas/DocumentsUpdatePermissionSettingsBody" } } } }, "responses": { "200": { - "description": "Download job initiated successfully", + "description": "Permission settings updated successfully", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/DashboardsDownloadResponse" + "$ref": "#/components/schemas/SuccessResponse" } } } }, "400": { - "description": "Invalid request body or filter configuration" + "description": "Invalid request body" }, "401": { "description": "Authentication required" }, "403": { - "description": "Permission denied - cannot download this dashboard" + "description": "Permission denied - MANAGER role required" }, "404": { - "description": "Dashboard not found" - }, - "409": { - "description": "Download already in progress for this dashboard" - }, - "500": { - "description": "Failed to initiate download" + "description": "Document not found" } } - } - }, - "/api/v1/dashboards/{identifier}/download/{jobId}": { - "get": { - "operationId": "dashboardsDownloadFile", - "summary": "Get download file", + }, + "post": { + "operationId": "documentsAddPermits", + "summary": "Add document permits", "tags": [ - "Dashboards" + "Documents" ], "parameters": [ { "schema": { "type": "string", - "description": "Dashboard identifier (short ID or UUID)", - "example": "12db1a0a" + "description": "Document identifier (either document ID or identifier slug)", + "example": "abc123" }, "required": true, - "description": "Dashboard identifier (short ID or UUID)", + "description": "Document identifier (either document ID or identifier slug)", "name": "identifier", "in": "path" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DocumentsAddPermitsBody" + } + } + } + }, + "responses": { + "200": { + "description": "Permissions added successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SuccessResponse" + } + } + } + }, + "400": { + "description": "Invalid request body - userIds or userGroupIds required" + }, + "401": { + "description": "Authentication required" + }, + "403": { + "description": "Permission denied - MANAGER role required" }, + "404": { + "description": "Document not found" + } + } + }, + "patch": { + "operationId": "documentsUpdatePermits", + "summary": "Update document permits", + "tags": [ + "Documents" + ], + "parameters": [ { "schema": { "type": "string", - "description": "Download job ID (UUID)", - "example": "123e4567-e89b-12d3-a456-426614174000" + "description": "Document identifier (either document ID or identifier slug)", + "example": "abc123" }, "required": true, - "description": "Download job ID (UUID)", - "name": "jobId", + "description": "Document identifier (either document ID or identifier slug)", + "name": "identifier", "in": "path" - }, - { - "schema": { - "type": "string", - "description": "Target user membership ID (for org-scoped API keys)" - }, - "required": false, - "description": "Target user membership ID (for org-scoped API keys)", - "name": "userId", - "in": "query" } ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DocumentsUpdatePermitsBody" + } + } + } + }, "responses": { "200": { - "description": "File ready - binary content streamed" + "description": "Permissions updated successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SuccessResponse" + } + } + } }, - "202": { - "description": "Download job still in progress" + "400": { + "description": "Invalid request body - userIds or userGroupIds required" }, "401": { "description": "Authentication required" }, - "404": { - "description": "Dashboard or download job not found" - }, - "410": { - "description": "Download job failed" + "403": { + "description": "Permission denied - MANAGER role required" }, - "500": { - "description": "Failed to retrieve download artifact" + "404": { + "description": "Document not found" } } - } - }, - "/api/v1/dashboards/{identifier}/download/{jobId}/status": { - "get": { - "operationId": "dashboardsDownloadStatus", - "summary": "Get download job status", + }, + "delete": { + "operationId": "documentsRevokePermits", + "summary": "Revoke document permits", "tags": [ - "Dashboards" + "Documents" ], "parameters": [ { "schema": { "type": "string", - "description": "Dashboard identifier (short ID or UUID)", - "example": "12db1a0a" + "description": "Document identifier (either document ID or identifier slug)", + "example": "abc123" }, "required": true, - "description": "Dashboard identifier (short ID or UUID)", + "description": "Document identifier (either document ID or identifier slug)", "name": "identifier", "in": "path" - }, - { - "schema": { - "type": "string", - "description": "Download job ID (UUID)", - "example": "123e4567-e89b-12d3-a456-426614174000" - }, - "required": true, - "description": "Download job ID (UUID)", - "name": "jobId", - "in": "path" - }, - { - "schema": { - "type": "string", - "description": "Target user membership ID (for org-scoped API keys)" - }, - "required": false, - "description": "Target user membership ID (for org-scoped API keys)", - "name": "userId", - "in": "query" } ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DocumentsRevokePermitsBody" + } + } + } + }, "responses": { "200": { - "description": "Download job status" + "description": "Permissions revoked successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SuccessResponse" + } + } + } + }, + "400": { + "description": "Invalid request body - userIds or userGroupIds required" }, "401": { "description": "Authentication required" }, + "403": { + "description": "Permission denied - MANAGER role required" + }, "404": { - "description": "Dashboard or download job not found" + "description": "Document not found" } } } }, - "/api/v1/dashboards/{identifier}/filters": { - "get": { - "operationId": "dashboardsGetFilters", - "summary": "Get dashboard filters", + "/api/v1/documents/{identifier}/draft": { + "post": { + "operationId": "documentsCreateDraft", + "summary": "Create document draft", "tags": [ - "Dashboards" + "Documents" ], "parameters": [ { "schema": { "type": "string", - "description": "Dashboard identifier (short ID or UUID)", - "example": "12db1a0a" + "description": "Document identifier (either document ID or identifier slug)", + "example": "abc123" }, "required": true, - "description": "Dashboard identifier (short ID or UUID)", + "description": "Document identifier (either document ID or identifier slug)", "name": "identifier", "in": "path" - }, - { - "schema": { - "type": "string", - "description": "Target user membership ID (for org-scoped API keys)" - }, - "required": false, - "description": "Target user membership ID (for org-scoped API keys)", - "name": "userId", - "in": "query" } ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DocumentsCreateDraftBody" + } + } + } + }, "responses": { "200": { - "description": "Dashboard filter and control configuration", + "description": "Draft created or existing draft returned", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/DashboardFiltersResponse" + "$ref": "#/components/schemas/DocumentsCreateDraftResponse" } } } }, + "400": { + "description": "Document is not eligible for publishing workflow" + }, "401": { "description": "Authentication required" }, "403": { - "description": "Permission denied - VIEWER role required" + "description": "Permission denied - EDITOR role required" }, "404": { - "description": "Dashboard not found" + "description": "Document or branch not found" } } }, - "patch": { - "operationId": "dashboardsUpdateFilters", - "summary": "Update dashboard filters", + "delete": { + "operationId": "documentsDiscardDraft", + "summary": "Discard document draft", "tags": [ - "Dashboards" + "Documents" ], "parameters": [ { "schema": { "type": "string", - "description": "Dashboard identifier (short ID or UUID)", - "example": "12db1a0a" + "description": "Document identifier (either document ID or identifier slug)", + "example": "abc123" }, "required": true, - "description": "Dashboard identifier (short ID or UUID)", + "description": "Document identifier (either document ID or identifier slug)", "name": "identifier", "in": "path" - }, - { - "schema": { - "type": "string", - "description": "Target user membership ID (for org-scoped API keys)" - }, - "required": false, - "description": "Target user membership ID (for org-scoped API keys)", - "name": "userId", - "in": "query" } ], "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/DashboardsUpdateFiltersBody" + "$ref": "#/components/schemas/DocumentsDiscardDraftBody" } } } }, "responses": { "200": { - "description": "Filters updated successfully", + "description": "Draft discarded successfully", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/DashboardFiltersResponse" + "$ref": "#/components/schemas/DocumentsDiscardDraftResponse" } } } }, - "400": { - "description": "Invalid request body - must include at least one filter, control, or filterOrder" - }, "401": { "description": "Authentication required" }, "403": { - "description": "Permission denied - EDITOR role required" + "description": "Permission denied" }, "404": { - "description": "Dashboard not found or document does not have a dashboard" - }, - "409": { - "description": "Conflict - draft already exists. Set clearExistingDraft to true to proceed." + "description": "Document or draft not found" } } } }, - "/api/v1/documents": { + "/api/v1/documents/{identifier}/drafts": { "get": { - "operationId": "documentsList", - "summary": "List documents", + "description": "Lists drafts for a document with branch context. By default only active drafts are returned; pass `include=archived` to also include soft-deleted drafts (retained ~7 days). Results are sorted by `createdAt` descending.", + "operationId": "documentsListDrafts", + "summary": "List document drafts", "tags": [ "Documents" ], - "parameters": [ - { - "schema": { - "type": "string", - "format": "uuid", - "description": "Filter by creator membership ID" - }, - "required": false, - "description": "Filter by creator membership ID", - "name": "creatorId", - "in": "query" - }, - { - "schema": { - "type": "string", - "description": "Cursor for pagination" - }, - "required": false, - "description": "Cursor for pagination", - "name": "cursor", - "in": "query" - }, - { - "schema": { - "type": "string", - "format": "uuid", - "description": "Filter by folder ID" - }, - "required": false, - "description": "Filter by folder ID", - "name": "folderId", - "in": "query" - }, - { - "schema": { - "type": "string", - "description": "Comma-separated list of additional fields to include: _count, labels, includeDeleted, onlyFavorites, onlySharedWithMe. onlySharedWithMe requires userId or user-scoped key and cannot be combined with onlyFavorites or folderId.", - "example": "_count,labels" - }, - "required": false, - "description": "Comma-separated list of additional fields to include: _count, labels, includeDeleted, onlyFavorites, onlySharedWithMe. onlySharedWithMe requires userId or user-scoped key and cannot be combined with onlyFavorites or folderId.", - "name": "include", - "in": "query" - }, - { - "schema": { - "type": "string", - "description": "Comma-separated list of label names to filter by", - "example": "verified,important" - }, - "required": false, - "description": "Comma-separated list of label names to filter by", - "name": "labels", - "in": "query" - }, - { - "schema": { - "type": "integer", - "exclusiveMinimum": 0, - "default": 50, - "description": "Number of records per page" - }, - "required": false, - "description": "Number of records per page", - "name": "pageSize", - "in": "query" - }, - { - "schema": { - "type": "string", - "enum": [ - "asc", - "desc" - ], - "default": "asc", - "description": "Sort direction" - }, - "required": false, - "description": "Sort direction", - "name": "sortDirection", - "in": "query" - }, + "parameters": [ { "schema": { "type": "string", - "enum": [ - "name", - "favorites", - "updatedAt", - "visits" - ], - "default": "name", - "description": "Field to sort by" + "description": "Document identifier (either document ID or identifier slug)", + "example": "abc123" }, - "required": false, - "description": "Field to sort by", - "name": "sortField", - "in": "query" + "required": true, + "description": "Document identifier (either document ID or identifier slug)", + "name": "identifier", + "in": "path" }, { "schema": { "type": "string", - "format": "uuid", - "description": "Filter documents visible to this membership ID" + "description": "Comma-separated list of additional drafts to include. Only \"archived\" is recognized — when present, soft-deleted drafts (retained ~7 days) are returned alongside active drafts.", + "example": "archived" }, "required": false, - "description": "Filter documents visible to this membership ID", - "name": "userId", + "description": "Comma-separated list of additional drafts to include. Only \"archived\" is recognized — when present, soft-deleted drafts (retained ~7 days) are returned alongside active drafts.", + "name": "include", "in": "query" } ], "responses": { "200": { - "description": "Paginated list of documents", + "description": "List of drafts for the document", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/DocumentsListResponse" + "$ref": "#/components/schemas/DocumentsListDraftsResponse" } } } }, + "400": { + "description": "Invalid query parameters" + }, "401": { "description": "Authentication required" + }, + "403": { + "description": "Insufficient permissions to view the document" + }, + "404": { + "description": "Document not found" } } - }, + } + }, + "/api/v1/documents/{identifier}/duplicate": { "post": { - "operationId": "documentsCreate", - "summary": "Create document", + "operationId": "documentsDuplicate", + "summary": "Duplicate document", "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" + }, + { + "schema": { + "type": "string", + "format": "uuid", + "description": "Target user membership ID (for org-scoped API keys)" + }, + "required": false, + "description": "Target user membership ID (for org-scoped API keys)", + "name": "userId", + "in": "query" + } + ], "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/DocumentsCreateBody" + "$ref": "#/components/schemas/DocumentsDuplicateBody" } } } }, "responses": { "201": { - "description": "Document created successfully", + "description": "Document duplicated successfully", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/DocumentsCreateResponse" + "$ref": "#/components/schemas/DocumentsDuplicateResponse" } } } }, "400": { - "description": "Invalid request body" + "description": "Invalid name or folder path" }, "401": { "description": "Authentication required" @@ -11649,16 +35275,15 @@ "description": "Permission denied" }, "404": { - "description": "Model or branch not found" + "description": "Document or folder not found" } } } }, - "/api/v1/documents/{identifier}": { - "get": { - "description": "Retrieves a document's configuration in a format compatible with PUT for round-trip editing. GET a document, modify the response, and PUT it back to update. Only dashboard documents are supported; analysis documents return 400.", - "operationId": "documentsGet", - "summary": "Get document", + "/api/v1/documents/{identifier}/favorite": { + "put": { + "operationId": "documentsAddFavorite", + "summary": "Add document to favorites", "tags": [ "Documents" ], @@ -11673,37 +35298,37 @@ "description": "Document identifier (either document ID or identifier slug)", "name": "identifier", "in": "path" + }, + { + "schema": { + "type": "string", + "format": "uuid", + "description": "Target user membership ID (for org-scoped API keys)" + }, + "required": false, + "description": "Target user membership ID (for org-scoped API keys)", + "name": "userId", + "in": "query" } ], "responses": { - "200": { - "description": "Document details", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DocumentsGetResponse" - } - } - } - }, - "400": { - "description": "Analysis documents are not supported" + "204": { + "description": "Favorite added successfully" }, "401": { "description": "Authentication required" }, "403": { - "description": "Insufficient permissions to view the document" + "description": "Permission denied" }, "404": { "description": "Document not found" } } }, - "put": { - "description": "Updates a document with the specified identifier. This endpoint performs a full resource replacement — all required fields must be provided and existing query presentations are replaced entirely. Only dashboard documents are supported; analysis documents and documents without an associated dashboard return 400. For published documents, the update goes through a draft/publish workflow automatically; if a draft already exists, the request returns 409 unless `clearExistingDraft` is set to `true`.", - "operationId": "documentsPut", - "summary": "Replace document (full replacement)", + "delete": { + "operationId": "documentsRemoveFavorite", + "summary": "Remove document from favorites", "tags": [ "Documents" ], @@ -11718,49 +35343,39 @@ "description": "Document identifier (either document ID or identifier slug)", "name": "identifier", "in": "path" + }, + { + "schema": { + "type": "string", + "format": "uuid", + "description": "Target user membership ID (for org-scoped API keys)" + }, + "required": false, + "description": "Target user membership ID (for org-scoped API keys)", + "name": "userId", + "in": "query" } ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DocumentsPutBody" - } - } - } - }, "responses": { - "200": { - "description": "Document replaced successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DocumentsPutResponse" - } - } - } - }, - "400": { - "description": "Invalid request body, missing required fields, or validation error (also returned for analysis documents and documents without an associated dashboard)" + "204": { + "description": "Favorite removed successfully" }, "401": { "description": "Authentication required" }, "403": { - "description": "Insufficient permissions to update the document" + "description": "Permission denied" }, "404": { "description": "Document not found" - }, - "409": { - "description": "Draft already exists - set clearExistingDraft to true to discard it and proceed" } } - }, + } + }, + "/api/v1/documents/{identifier}/labels": { "patch": { - "description": "Updates a document's name, description, and/or identifier. This is a partial update — only provided fields are modified, and at least one of `name`, `description`, or `identifier` must be supplied. When `identifier` is changed, the previous identifier is retained in the document identifier history and continues to redirect. For published documents, the update goes through a draft/publish workflow automatically.", - "operationId": "documentsUpdate", - "summary": "Rename document", + "operationId": "documentsBulkUpdateLabels", + "summary": "Bulk update document labels", "tags": [ "Documents" ], @@ -11775,48 +35390,58 @@ "description": "Document identifier (either document ID or identifier slug)", "name": "identifier", "in": "path" + }, + { + "schema": { + "type": "string", + "format": "uuid", + "description": "Target user membership ID (for org-scoped API keys)" + }, + "required": false, + "description": "Target user membership ID (for org-scoped API keys)", + "name": "userId", + "in": "query" } ], "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/DocumentsUpdateBody" + "$ref": "#/components/schemas/DocumentsBulkUpdateLabelsBody" } } } }, "responses": { "200": { - "description": "Document updated successfully", + "description": "Labels updated successfully", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/DocumentsUpdateResponse" + "$ref": "#/components/schemas/DocumentsBulkUpdateLabelsResponse" } } } }, "400": { - "description": "Invalid request body or validation error (e.g. missing name/description/identifier, name too long, identifier already in use)" + "description": "Invalid request - at least one label must be specified" }, "401": { "description": "Authentication required" }, "403": { - "description": "Permission denied - EDITOR role required" + "description": "Permission denied" }, "404": { "description": "Document not found" - }, - "409": { - "description": "Draft already exists - set clearExistingDraft to true to discard it and proceed" } } - }, - "delete": { - "operationId": "documentsDelete", - "summary": "Delete document", + } + }, + "/api/v1/documents/{identifier}/labels/{labelName}": { + "put": { + "operationId": "documentsAddLabel", + "summary": "Add label to document", "tags": [ "Documents" ], @@ -11824,42 +35449,55 @@ { "schema": { "type": "string", - "description": "Document identifier (either document ID or identifier slug)", + "description": "Document identifier", "example": "abc123" }, "required": true, - "description": "Document identifier (either document ID or identifier slug)", + "description": "Document identifier", "name": "identifier", "in": "path" + }, + { + "schema": { + "type": "string", + "description": "Label name", + "example": "verified" + }, + "required": true, + "description": "Label name", + "name": "labelName", + "in": "path" + }, + { + "schema": { + "type": "string", + "format": "uuid", + "description": "Target user membership ID (for org-scoped API keys)" + }, + "required": false, + "description": "Target user membership ID (for org-scoped API keys)", + "name": "userId", + "in": "query" } ], "responses": { - "200": { - "description": "Document deleted successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SuccessResponse" - } - } - } + "204": { + "description": "Label added successfully" }, "401": { "description": "Authentication required" }, "403": { - "description": "Permission denied - MANAGER role required" + "description": "Permission denied" }, "404": { - "description": "Document not found" + "description": "Document or label not found" } } - } - }, - "/api/v1/documents/{identifier}/queries": { - "get": { - "operationId": "documentsGetQueries", - "summary": "List document queries", + }, + "delete": { + "operationId": "documentsRemoveLabel", + "summary": "Remove label from document", "tags": [ "Documents" ], @@ -11867,25 +35505,40 @@ { "schema": { "type": "string", - "description": "Document identifier (either document ID or identifier slug)", - "example": "abc123" + "description": "Document identifier", + "example": "abc123" + }, + "required": true, + "description": "Document identifier", + "name": "identifier", + "in": "path" + }, + { + "schema": { + "type": "string", + "description": "Label name", + "example": "verified" }, "required": true, - "description": "Document identifier (either document ID or identifier slug)", - "name": "identifier", + "description": "Label name", + "name": "labelName", "in": "path" + }, + { + "schema": { + "type": "string", + "format": "uuid", + "description": "Target user membership ID (for org-scoped API keys)" + }, + "required": false, + "description": "Target user membership ID (for org-scoped API keys)", + "name": "userId", + "in": "query" } ], "responses": { - "200": { - "description": "List of queries in the document", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DocumentsGetQueriesResponse" - } - } - } + "204": { + "description": "Label removed successfully" }, "401": { "description": "Authentication required" @@ -11899,10 +35552,10 @@ } } }, - "/api/v1/documents/{identifier}/move": { - "post": { - "operationId": "documentsMove", - "summary": "Move document", + "/api/v1/documents/{identifier}/transfer-ownership": { + "put": { + "operationId": "documentsTransferOwnership", + "summary": "Transfer document ownership", "tags": [ "Documents" ], @@ -11923,14 +35576,14 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/DocumentsMoveBody" + "$ref": "#/components/schemas/DocumentsTransferOwnershipBody" } } } }, "responses": { "200": { - "description": "Document moved successfully", + "description": "Ownership transferred successfully", "content": { "application/json": { "schema": { @@ -11940,24 +35593,24 @@ } }, "400": { - "description": "Invalid folder path or scope" + "description": "Invalid user ID" }, "401": { "description": "Authentication required" }, "403": { - "description": "Permission denied - MANAGER role required" + "description": "Permission denied - MANAGER role or owner required" }, "404": { - "description": "Document or folder not found" + "description": "Document or user not found" } } } }, - "/api/v1/documents/{identifier}/permissions": { + "/api/v1/documents/{identifier}/access-list": { "get": { - "operationId": "documentsGetPermissions", - "summary": "Get document permissions", + "operationId": "documentsAccessList", + "summary": "List document access principals", "tags": [ "Documents" ], @@ -11976,22 +35629,90 @@ { "schema": { "type": "string", - "format": "uuid", - "description": "User membership ID to check permissions for" + "description": "Cursor for pagination (from previous response nextCursor)", + "example": "eyJpZCI6IjEyMzQ1In0" }, - "required": true, - "description": "User membership ID to check permissions for", - "name": "userId", + "required": false, + "description": "Cursor for pagination (from previous response nextCursor)", + "name": "cursor", + "in": "query" + }, + { + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 100, + "default": 20, + "description": "Number of results per page (1-100, integer)", + "example": 20 + }, + "required": false, + "description": "Number of results per page (1-100, integer)", + "name": "pageSize", + "in": "query" + }, + { + "schema": { + "type": "string", + "enum": [ + "asc", + "desc" + ], + "default": "asc", + "description": "Sort direction (default: asc)", + "example": "desc" + }, + "required": false, + "description": "Sort direction (default: asc)", + "name": "sortDirection", + "in": "query" + }, + { + "schema": { + "type": "string", + "description": "Field to sort results by" + }, + "required": false, + "description": "Field to sort results by", + "name": "sortField", + "in": "query" + }, + { + "schema": { + "type": "string", + "enum": [ + "direct", + "folder" + ], + "description": "Filter by access source: direct or folder" + }, + "required": false, + "description": "Filter by access source: direct or folder", + "name": "accessSource", + "in": "query" + }, + { + "schema": { + "type": "string", + "enum": [ + "user", + "userGroup" + ], + "description": "Filter by principal type: user or userGroup" + }, + "required": false, + "description": "Filter by principal type: user or userGroup", + "name": "type", "in": "query" } ], "responses": { "200": { - "description": "User permissions for the document", + "description": "List of users and groups with access", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/DocumentsGetPermissionsResponse" + "$ref": "#/components/schemas/DocumentsAccessListResponse" } } } @@ -12000,16 +35721,19 @@ "description": "Authentication required" }, "403": { - "description": "Permission denied" + "description": "Permission denied - VIEWER role required" }, "404": { - "description": "Document or user not found" + "description": "Document not found" } } - }, - "put": { - "operationId": "documentsUpdatePermissionSettings", - "summary": "Update document permission settings", + } + }, + "/api/v1/documents/{identifier}/favorites": { + "get": { + "description": "Lists users who have favorited the document, paginated and sorted by favoritedAt. Document-centric counterpart to GET /api/v1/documents?include=onlyFavorites: useful for migration scripts that need to preserve favorites when replacing documents, without iterating every user in the organization.", + "operationId": "documentsListFavorites", + "summary": "List users who favorited the document", "tags": [ "Documents" ], @@ -12024,98 +35748,127 @@ "description": "Document identifier (either document ID or identifier slug)", "name": "identifier", "in": "path" + }, + { + "schema": { + "type": "string", + "description": "Cursor for pagination (from previous response nextCursor)", + "example": "eyJpZCI6IjEyMzQ1In0" + }, + "required": false, + "description": "Cursor for pagination (from previous response nextCursor)", + "name": "cursor", + "in": "query" + }, + { + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 100, + "default": 20, + "description": "Number of results per page (1-100, integer)", + "example": 20 + }, + "required": false, + "description": "Number of results per page (1-100, integer)", + "name": "pageSize", + "in": "query" + }, + { + "schema": { + "type": "string", + "enum": [ + "asc", + "desc" + ], + "default": "asc", + "description": "Sort direction by favoritedAt (default: asc — oldest first)", + "example": "desc" + }, + "required": false, + "description": "Sort direction by favoritedAt (default: asc — oldest first)", + "name": "sortDirection", + "in": "query" } ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DocumentsUpdatePermissionSettingsBody" - } - } - } - }, "responses": { "200": { - "description": "Permission settings updated successfully", + "description": "Paginated list of users who favorited the document", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SuccessResponse" + "$ref": "#/components/schemas/DocumentsListFavoritesResponse" } } } }, "400": { - "description": "Invalid request body" + "description": "Invalid query parameters" }, "401": { "description": "Authentication required" }, "403": { - "description": "Permission denied - MANAGER role required" + "description": "Permission denied — caller lacks MANAGER on the document, or used a user-scoped (personal access token) API key (org-scoped only)" }, "404": { "description": "Document not found" } } - }, + } + }, + "/api/v2/documents": { "post": { - "operationId": "documentsAddPermits", - "summary": "Add document permits", + "description": "Create a brand-new document and publish it live. Accepts creation metadata (`modelId`, `name`, optional `identifier` / `description` / `folderId`) plus the same content slice as the PATCH body — `queryPresentations`, `controls`, `settings`, `containers`. The server mints internal tile identifiers, so callers omit `miniUuid`. Tiles in `queryPresentations` are merged by key over the single empty seed tile at key `\"1\"`; write to `\"1\"` (or send it as `null`) to replace the seed.\n\nWhen `containers` is omitted, every dashboard-eligible tile is auto-placed in a default layout. When `containers` is present, it fully defines the layout — tiles it does not reference are stored but not rendered.\n\nThe new document is published live before the response returns. As a first publish of brand-new content it is not subject to the org’s `requirePullRequestToPublish` policy (which gates edits to existing content).", + "operationId": "documentsV2Create", + "summary": "Create document", "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": { + "required": true, "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/DocumentsAddPermitsBody" + "$ref": "#/components/schemas/DocumentsV2CreateBody" } } } }, "responses": { - "200": { - "description": "Permissions added successfully", + "201": { + "description": "Document created and published successfully.", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SuccessResponse" + "$ref": "#/components/schemas/DocumentsV2CreateResponse" } } } }, "400": { - "description": "Invalid request body - userIds or userGroupIds required" + "description": "Invalid request body or schema validation error (e.g. unknown top-level field, name too long, query presentation cap exceeded), or the `identifier` is already in use." }, "401": { - "description": "Authentication required" + "description": "Authentication required." }, "403": { - "description": "Permission denied - MANAGER role required" + "description": "Insufficient permissions to create a document on this model." }, "404": { - "description": "Document not found" + "description": "Base model or branch not found." + }, + "405": { + "description": "Method not allowed." } } - }, - "patch": { - "operationId": "documentsUpdatePermits", - "summary": "Update document permits", + } + }, + "/api/v2/documents/{identifier}": { + "get": { + "description": "Read the document's current draft state (or the published state if no draft exists). Returns the full `DocumentsV2ReadResponse` shape.\n\nThe response is structured so a caller can take it verbatim and submit it as the body of the draft PATCH routes. Tiles in `queryPresentations.data` are keyed by a stable record key (e.g. `\"1\"`, `\"2\"`) — the server uses that key to identify existing tiles for updates, so callers do not need to track or send any other identifier. Control IDs and container `instanceKey` / `referenceKey` values also round-trip unchanged.", + "operationId": "documentsV2Get", + "summary": "Read document state", "tags": [ "Documents" ], @@ -12123,52 +35876,46 @@ { "schema": { "type": "string", - "description": "Document identifier (either document ID or identifier slug)", + "description": "Document identifier — either the URL slug (e.g. `abc123`) or the canonical workbook UUID.", "example": "abc123" }, "required": true, - "description": "Document identifier (either document ID or identifier slug)", + "description": "Document identifier — either the URL slug (e.g. `abc123`) or the canonical workbook UUID.", "name": "identifier", "in": "path" } ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DocumentsUpdatePermitsBody" - } - } - } - }, "responses": { "200": { - "description": "Permissions updated successfully", + "description": "Document state. A workbook-only document (no dashboard layout yet) returns only the workbook-scoped fields (`name`, `description`, `queryPresentations`); the dashboard-scoped `containers`, `controls`, and `settings` are omitted until a layout exists.", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SuccessResponse" + "$ref": "#/components/schemas/DocumentsV2ReadResponse" } } } }, - "400": { - "description": "Invalid request body - userIds or userGroupIds required" - }, "401": { - "description": "Authentication required" + "description": "Authentication required." }, "403": { - "description": "Permission denied - MANAGER role required" + "description": "Insufficient permissions to read the document." }, "404": { - "description": "Document not found" + "description": "Document not found." + }, + "422": { + "description": "The document cannot be read as a dashboard: a classic-layout dashboard (upgrade to the advanced layout first) or an app document." } } - }, - "delete": { - "operationId": "documentsRevokePermits", - "summary": "Revoke document permits", + } + }, + "/api/v2/documents/{identifier}/draft": { + "patch": { + "description": "Create a new draft on the published document and apply the patch. No auto-publish — the response includes the new `draftIdentifier` for follow-up calls.\n\nPass an optional `branchId` to attach the draft to a branch; omit it for a draft on the main (unpublished) workspace.", + "operationId": "documentsV2PatchDraft", + "summary": "Create draft and patch document", "tags": [ "Documents" ], @@ -12176,11 +35923,11 @@ { "schema": { "type": "string", - "description": "Document identifier (either document ID or identifier slug)", + "description": "Document identifier — either the URL slug (e.g. `abc123`) or the canonical workbook UUID.", "example": "abc123" }, "required": true, - "description": "Document identifier (either document ID or identifier slug)", + "description": "Document identifier — either the URL slug (e.g. `abc123`) or the canonical workbook UUID.", "name": "identifier", "in": "path" } @@ -12189,41 +35936,51 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/DocumentsRevokePermitsBody" + "$ref": "#/components/schemas/DocumentsV2CreateDraftBody" } } } }, "responses": { "200": { - "description": "Permissions revoked successfully", + "description": "Draft created and patch applied successfully.", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SuccessResponse" + "$ref": "#/components/schemas/DocumentsV2PatchDraftResponse" } } } }, "400": { - "description": "Invalid request body - userIds or userGroupIds required" + "description": "Invalid request body or schema validation error (e.g. unknown top-level field, name too long, query presentation cap exceeded)." }, "401": { - "description": "Authentication required" + "description": "Authentication required." }, "403": { - "description": "Permission denied - MANAGER role required" + "description": "Insufficient permissions to update the document." }, "404": { - "description": "Document not found" + "description": "Document or branch not found." + }, + "405": { + "description": "Method not allowed." + }, + "409": { + "description": "The target is not a published document (drafts only attach to published documents), or a concurrent request just created the layout for this document — retry." + }, + "422": { + "description": "The document cannot satisfy the patch: a classic-layout dashboard (upgrade to the advanced layout first), an app document, or a workbook-only document patched without a `containers` payload (or with an empty one)." } } } }, - "/api/v1/documents/{identifier}/draft": { - "post": { - "operationId": "documentsCreateDraft", - "summary": "Create document draft", + "/api/v2/documents/{identifier}/draft/{draftIdentifier}": { + "get": { + "description": "Read the named draft's state. Returns the full `DocumentsV2ReadResponse` shape — same as the live-state read endpoint.\n\nThe response is structured so a caller can take it verbatim and submit it as the body of the draft PATCH routes. Tiles in `queryPresentations.data` are keyed by a stable record key (e.g. `\"1\"`, `\"2\"`) — the server uses that key to identify existing tiles for updates, so callers do not need to track or send any other identifier. Control IDs and container `instanceKey` / `referenceKey` values also round-trip unchanged.", + "operationId": "documentsV2GetDraft", + "summary": "Read draft state", "tags": [ "Documents" ], @@ -12231,52 +35988,55 @@ { "schema": { "type": "string", - "description": "Document identifier (either document ID or identifier slug)", + "description": "Draft workbook identifier (see `POST /api/v1/documents/{identifier}/draft`).", + "example": "def456" + }, + "required": true, + "description": "Draft workbook identifier (see `POST /api/v1/documents/{identifier}/draft`).", + "name": "draftIdentifier", + "in": "path" + }, + { + "schema": { + "type": "string", + "description": "Published document identifier.", "example": "abc123" }, "required": true, - "description": "Document identifier (either document ID or identifier slug)", + "description": "Published document identifier.", "name": "identifier", "in": "path" } ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DocumentsCreateDraftBody" - } - } - } - }, "responses": { "200": { - "description": "Draft created or existing draft returned", + "description": "Draft state.", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/DocumentsCreateDraftResponse" + "$ref": "#/components/schemas/DocumentsV2ReadResponse" } } } }, - "400": { - "description": "Document is not eligible for publishing workflow" - }, "401": { - "description": "Authentication required" + "description": "Authentication required." }, "403": { - "description": "Permission denied - EDITOR role required" + "description": "Insufficient permissions to read the draft." }, "404": { - "description": "Document or branch not found" + "description": "Document or draft not found." + }, + "422": { + "description": "The draft cannot be read as a dashboard: a classic-layout dashboard (upgrade to the advanced layout first) or an app document." } } }, - "delete": { - "operationId": "documentsDiscardDraft", - "summary": "Discard document draft", + "patch": { + "description": "Apply the patch to an existing draft addressed by `draftIdentifier`. Pure apply — no draft creation, no publish.", + "operationId": "documentsV2PatchDraftByIdentifier", + "summary": "Patch draft", "tags": [ "Documents" ], @@ -12284,11 +36044,22 @@ { "schema": { "type": "string", - "description": "Document identifier (either document ID or identifier slug)", + "description": "Draft workbook identifier (see `POST /api/v1/documents/{identifier}/draft`).", + "example": "def456" + }, + "required": true, + "description": "Draft workbook identifier (see `POST /api/v1/documents/{identifier}/draft`).", + "name": "draftIdentifier", + "in": "path" + }, + { + "schema": { + "type": "string", + "description": "Published document identifier.", "example": "abc123" }, "required": true, - "description": "Document identifier (either document ID or identifier slug)", + "description": "Published document identifier.", "name": "identifier", "in": "path" } @@ -12297,38 +36068,51 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/DocumentsDiscardDraftBody" + "$ref": "#/components/schemas/DocumentsV2PatchDraftBody" } } } }, "responses": { "200": { - "description": "Draft discarded successfully", + "description": "Patch applied to draft successfully.", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/DocumentsDiscardDraftResponse" + "$ref": "#/components/schemas/DocumentsV2PatchDraftResponse" } } } }, + "400": { + "description": "Invalid request body or schema validation error (e.g. unknown top-level field, name too long, query presentation cap exceeded)." + }, "401": { - "description": "Authentication required" + "description": "Authentication required." }, "403": { - "description": "Permission denied" + "description": "Insufficient permissions to update the draft." }, "404": { - "description": "Document or draft not found" + "description": "Document or draft not found." + }, + "405": { + "description": "Method not allowed." + }, + "409": { + "description": "The target is not a published document (drafts only attach to published documents), or a concurrent request just created the layout for this document — retry." + }, + "422": { + "description": "The draft cannot satisfy the patch: a classic-layout dashboard (upgrade to the advanced layout first), an app document, or a workbook-only draft patched without a `containers` payload (or with an empty one)." } } } }, - "/api/v1/documents/{identifier}/duplicate": { + "/api/v2/documents/{identifier}/draft/publish": { "post": { - "operationId": "documentsDuplicate", - "summary": "Duplicate document", + "description": "Publish the document's current main (non-branch) draft, promoting it to the published version. No request body — the draft is consumed, so the response echoes the now-published document metadata.\n\nOnly the main draft is publishable here; a branch-attached draft is published by merging its branch (`POST /api/v1/models/{modelId}/branch/{branchName}/merge`), so a document with no main draft returns 404. Documents that require a pull request to publish return 400.", + "operationId": "documentsV2PublishDraft", + "summary": "Publish draft", "tags": [ "Documents" ], @@ -12336,545 +36120,1048 @@ { "schema": { "type": "string", - "description": "Document identifier (either document ID or identifier slug)", + "description": "Document identifier — either the URL slug (e.g. `abc123`) or the canonical workbook UUID.", "example": "abc123" }, "required": true, - "description": "Document identifier (either document ID or identifier slug)", + "description": "Document identifier — either the URL slug (e.g. `abc123`) or the canonical workbook UUID.", "name": "identifier", "in": "path" + } + ], + "responses": { + "200": { + "description": "Draft published successfully.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DocumentsV2PublishDraftResponse" + } + } + } }, - { - "schema": { - "type": "string", - "format": "uuid", - "description": "Target user membership ID (for org-scoped API keys)" - }, - "required": false, - "description": "Target user membership ID (for org-scoped API keys)", - "name": "userId", - "in": "query" + "400": { + "description": "The document requires a pull request to publish (response detail: \"Can't publish because this document can only be edited through a branch\")." + }, + "401": { + "description": "Authentication required." + }, + "403": { + "description": "Insufficient permissions to publish the draft." + }, + "404": { + "description": "Document not found, or it has no main draft to publish (a branch-attached draft is published by merging its branch)." + }, + "405": { + "description": "Method not allowed." + }, + "409": { + "description": "The target is not a published document." } + } + } + }, + "/api/v1/embed/sso/generate-session": { + "post": { + "operationId": "embedSsoGenerateSession", + "summary": "Generate embedded SSO session", + "tags": [ + "Embed" ], "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/DocumentsDuplicateBody" + "$ref": "#/components/schemas/EmbedSsoGenerateSessionBody" } } } }, "responses": { - "201": { - "description": "Document duplicated successfully", + "200": { + "description": "Session token generated", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/DocumentsDuplicateResponse" + "$ref": "#/components/schemas/EmbedSsoGenerateSessionResponse" } } } }, "400": { - "description": "Invalid name or folder path" + "description": "Invalid request body" }, "401": { - "description": "Authentication required" + "description": "Authentication required (API key with embed scope)" }, "403": { - "description": "Permission denied" - }, - "404": { - "description": "Document or folder not found" + "description": "Permission denied - embed not enabled" } } } }, - "/api/v1/documents/{identifier}/favorite": { - "put": { - "operationId": "documentsAddFavorite", - "summary": "Add document to favorites", + "/api/v1/ai/eval/prompt-sets": { + "get": { + "description": "List eval prompt sets, sorted alphabetically by name. When `model_ids` is omitted, returns prompt sets for every shared model the caller can access. Requires at least the Querier role on each requested model.", + "operationId": "aiEvalPromptSetsList", + "summary": "List eval prompt sets", "tags": [ - "Documents" + "AI Eval" ], "parameters": [ { "schema": { "type": "string", - "description": "Document identifier (either document ID or identifier slug)", - "example": "abc123" + "enum": [ + "true", + "false" + ], + "description": "When `true`, returns archived prompt sets instead of active ones. Defaults to `false`.", + "example": "false" }, - "required": true, - "description": "Document identifier (either document ID or identifier slug)", - "name": "identifier", - "in": "path" + "required": false, + "description": "When `true`, returns archived prompt sets instead of active ones. Defaults to `false`.", + "name": "archived", + "in": "query" }, { "schema": { - "type": "string", - "format": "uuid", - "description": "Target user membership ID (for org-scoped API keys)" + "type": "array", + "items": { + "type": "string", + "format": "uuid" + }, + "description": "Optional list of model IDs to filter prompt sets by. When omitted, returns prompt sets for every model the caller can access. Supply multiple times to filter by more than one model (e.g., `?model_ids=A&model_ids=B`)." }, "required": false, - "description": "Target user membership ID (for org-scoped API keys)", - "name": "userId", + "description": "Optional list of model IDs to filter prompt sets by. When omitted, returns prompt sets for every model the caller can access. Supply multiple times to filter by more than one model (e.g., `?model_ids=A&model_ids=B`).", + "name": "model_ids", "in": "query" } ], "responses": { - "204": { - "description": "Favorite added successfully" + "200": { + "description": "List of prompt sets, sorted alphabetically by name.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalPromptSetsListResponse" + } + } + } + }, + "400": { + "description": "Invalid query params (e.g. `model_ids` contains a non-UUID, or `archived` is not `true`/`false`).", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError400" + } + } + } }, "401": { - "description": "Authentication required" + "description": "Missing or invalid API key.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError401" + } + } + } }, "403": { - "description": "Permission denied" + "description": "Insufficient permissions. The caller must have at least the Querier role on each requested model.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError403" + } + } + } }, "404": { - "description": "Document not found" + "description": "No eval-accessible models for this caller.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError404" + } + } + } + } + } + }, + "post": { + "description": "Create a new eval prompt set bound to a shared model. Initial prompts can be supplied; additional prompts can be added later via PATCH.", + "operationId": "aiEvalPromptSetsCreate", + "summary": "Create an eval prompt set", + "tags": [ + "AI Eval" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalPromptSetsCreateBody" + } + } + } + }, + "responses": { + "201": { + "description": "Prompt set created successfully.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalPromptSetsCreateResponse" + } + } + } + }, + "400": { + "description": "Invalid request body.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError400" + } + } + } + }, + "401": { + "description": "Missing or invalid API key.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError401" + } + } + } + }, + "403": { + "description": "Insufficient permissions. The caller must have at least the Querier role on the model.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError403" + } + } + } } } - }, - "delete": { - "operationId": "documentsRemoveFavorite", - "summary": "Remove document from favorites", + } + }, + "/api/v1/ai/eval/prompt-sets/{promptSetId}": { + "get": { + "description": "Get a single prompt set with all of its prompts.", + "operationId": "aiEvalPromptSetsGet", + "summary": "Get an eval prompt set", "tags": [ - "Documents" + "AI Eval" ], "parameters": [ { "schema": { "type": "string", - "description": "Document identifier (either document ID or identifier slug)", - "example": "abc123" + "format": "uuid", + "description": "The unique identifier of the eval prompt set.", + "example": "550e8400-e29b-41d4-a716-446655440000" }, "required": true, - "description": "Document identifier (either document ID or identifier slug)", - "name": "identifier", + "description": "The unique identifier of the eval prompt set.", + "name": "promptSetId", "in": "path" - }, - { - "schema": { - "type": "string", - "format": "uuid", - "description": "Target user membership ID (for org-scoped API keys)" - }, - "required": false, - "description": "Target user membership ID (for org-scoped API keys)", - "name": "userId", - "in": "query" } ], "responses": { - "204": { - "description": "Favorite removed successfully" + "200": { + "description": "Prompt set details.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalPromptSetsGetResponse" + } + } + } + }, + "400": { + "description": "Invalid `promptSetId` — must be a UUID.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError400" + } + } + } }, "401": { - "description": "Authentication required" + "description": "Missing or invalid API key.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError401" + } + } + } }, "403": { - "description": "Permission denied" + "description": "Insufficient permissions.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError403" + } + } + } }, "404": { - "description": "Document not found" + "description": "Prompt set not found.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError404" + } + } + } } } - } - }, - "/api/v1/documents/{identifier}/labels": { + }, "patch": { - "operationId": "documentsBulkUpdateLabels", - "summary": "Bulk update document labels", + "description": "Update a prompt set's name, description, and/or prompts. When `prompts` is supplied, it fully replaces the existing list — existing prompts omitted from the list are deleted, entries without an `id` are created, and entries with a matching `id` are updated in place.", + "operationId": "aiEvalPromptSetsUpdate", + "summary": "Update an eval prompt set", "tags": [ - "Documents" + "AI Eval" ], "parameters": [ { "schema": { "type": "string", - "description": "Document identifier (either document ID or identifier slug)", - "example": "abc123" + "format": "uuid", + "description": "The unique identifier of the eval prompt set.", + "example": "550e8400-e29b-41d4-a716-446655440000" }, "required": true, - "description": "Document identifier (either document ID or identifier slug)", - "name": "identifier", + "description": "The unique identifier of the eval prompt set.", + "name": "promptSetId", "in": "path" - }, - { - "schema": { - "type": "string", - "format": "uuid", - "description": "Target user membership ID (for org-scoped API keys)" - }, - "required": false, - "description": "Target user membership ID (for org-scoped API keys)", - "name": "userId", - "in": "query" } ], "requestBody": { + "required": true, "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/DocumentsBulkUpdateLabelsBody" + "$ref": "#/components/schemas/EvalPromptSetsUpdateBody" } } } }, "responses": { "200": { - "description": "Labels updated successfully", + "description": "Prompt set updated successfully.", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/DocumentsBulkUpdateLabelsResponse" + "$ref": "#/components/schemas/EvalPromptSetsUpdateResponse" } } } }, "400": { - "description": "Invalid request - at least one label must be specified" + "description": "Invalid request body.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError400" + } + } + } }, "401": { - "description": "Authentication required" + "description": "Missing or invalid API key.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError401" + } + } + } }, "403": { - "description": "Permission denied" + "description": "Insufficient permissions.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError403" + } + } + } }, "404": { - "description": "Document not found" + "description": "Prompt set not found.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError404" + } + } + } + }, + "422": { + "description": "A `prompts[].id` in the request does not belong to this prompt set.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError422" + } + } + } } } - } - }, - "/api/v1/documents/{identifier}/labels/{labelName}": { - "put": { - "operationId": "documentsAddLabel", - "summary": "Add label to document", + }, + "delete": { + "description": "Archive (soft-delete) a prompt set. As part of the archive, Omni attempts to cancel every in-flight agentic job associated with the set; the returned `cancelled_job_count` reports how many were cancelled. The archive is committed before run cancellations start. Cancellation is best-effort — the database cancel is authoritative, but the Redis stop-signal that halts a running worker can lag. If the archive itself or a whole run-cancellation fails, the endpoint returns 500, but the prompt set is already archived. The call is idempotent — retrying drains any remaining runs.", + "operationId": "aiEvalPromptSetsArchive", + "summary": "Archive an eval prompt set", "tags": [ - "Documents" + "AI Eval" ], "parameters": [ { "schema": { "type": "string", - "description": "Document identifier", - "example": "abc123" + "format": "uuid", + "description": "The unique identifier of the eval prompt set.", + "example": "550e8400-e29b-41d4-a716-446655440000" }, "required": true, - "description": "Document identifier", - "name": "identifier", + "description": "The unique identifier of the eval prompt set.", + "name": "promptSetId", "in": "path" + } + ], + "responses": { + "200": { + "description": "Prompt set archived successfully.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalPromptSetsDeleteResponse" + } + } + } }, - { - "schema": { - "type": "string", - "description": "Label name", - "example": "verified" - }, - "required": true, - "description": "Label name", - "name": "labelName", - "in": "path" + "400": { + "description": "Invalid `promptSetId` — must be a UUID.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError400" + } + } + } + }, + "401": { + "description": "Missing or invalid API key.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError401" + } + } + } + }, + "403": { + "description": "Insufficient permissions.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError403" + } + } + } + }, + "404": { + "description": "Prompt set not found.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError404" + } + } + } }, + "500": { + "description": "Archive committed but a run-cancellation failed; the set is already archived — safe to retry.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError500" + } + } + } + } + } + } + }, + "/api/v1/ai/eval/prompt-sets/{promptSetId}/unarchive": { + "post": { + "description": "Restore an archived prompt set.", + "operationId": "aiEvalPromptSetsUnarchive", + "summary": "Restore an archived eval prompt set", + "tags": [ + "AI Eval" + ], + "parameters": [ { "schema": { "type": "string", "format": "uuid", - "description": "Target user membership ID (for org-scoped API keys)" + "description": "The unique identifier of the eval prompt set.", + "example": "550e8400-e29b-41d4-a716-446655440000" }, - "required": false, - "description": "Target user membership ID (for org-scoped API keys)", - "name": "userId", - "in": "query" + "required": true, + "description": "The unique identifier of the eval prompt set.", + "name": "promptSetId", + "in": "path" } ], "responses": { - "204": { - "description": "Label added successfully" + "200": { + "description": "Prompt set restored successfully.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalPromptSetsUnarchiveResponse" + } + } + } + }, + "400": { + "description": "Invalid `promptSetId` — must be a UUID.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError400" + } + } + } }, "401": { - "description": "Authentication required" + "description": "Missing or invalid API key.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError401" + } + } + } }, "403": { - "description": "Permission denied" + "description": "Insufficient permissions.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError403" + } + } + } }, "404": { - "description": "Document or label not found" + "description": "Prompt set not found.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError404" + } + } + } } } - }, - "delete": { - "operationId": "documentsRemoveLabel", - "summary": "Remove label from document", + } + }, + "/api/v1/ai/eval/runs": { + "get": { + "description": "List runs for a prompt set, newest first, filtered to runs whose model the caller can access. The `prompt_set_id` query parameter is required.", + "operationId": "aiEvalRunsList", + "summary": "List eval runs", "tags": [ - "Documents" + "AI Eval" ], "parameters": [ { "schema": { "type": "string", - "description": "Document identifier", - "example": "abc123" - }, - "required": true, - "description": "Document identifier", - "name": "identifier", - "in": "path" - }, - { - "schema": { - "type": "string", - "description": "Label name", - "example": "verified" + "enum": [ + "true", + "false" + ], + "description": "When `true`, returns archived runs instead of active ones. Defaults to `false`.", + "example": "false" }, - "required": true, - "description": "Label name", - "name": "labelName", - "in": "path" + "required": false, + "description": "When `true`, returns archived runs instead of active ones. Defaults to `false`.", + "name": "archived", + "in": "query" }, { "schema": { "type": "string", "format": "uuid", - "description": "Target user membership ID (for org-scoped API keys)" + "description": "Required — the prompt set whose runs should be listed.", + "example": "550e8400-e29b-41d4-a716-446655440000" }, - "required": false, - "description": "Target user membership ID (for org-scoped API keys)", - "name": "userId", + "required": true, + "description": "Required — the prompt set whose runs should be listed.", + "name": "prompt_set_id", "in": "query" } ], "responses": { - "204": { - "description": "Label removed successfully" + "200": { + "description": "List of runs for the prompt set.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalRunsListResponse" + } + } + } + }, + "400": { + "description": "Missing or invalid `prompt_set_id`.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError400" + } + } + } }, "401": { - "description": "Authentication required" + "description": "Missing or invalid API key.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError401" + } + } + } }, "403": { - "description": "Permission denied" + "description": "Insufficient permissions.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError403" + } + } + } }, "404": { - "description": "Document not found" + "description": "Prompt set not found.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError404" + } + } + } } } - } - }, - "/api/v1/documents/{identifier}/transfer-ownership": { - "put": { - "operationId": "documentsTransferOwnership", - "summary": "Transfer document ownership", + }, + "post": { + "description": "Create and start a new run against an existing prompt set. The run enqueues one agentic job per prompt and begins executing immediately. Returns the newly created run with its initial per-prompt result rows.", + "operationId": "aiEvalRunsCreate", + "summary": "Start an eval run", "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" - } + "AI Eval" ], "requestBody": { + "required": true, "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/DocumentsTransferOwnershipBody" + "$ref": "#/components/schemas/EvalRunsCreateBody" } } } }, "responses": { - "200": { - "description": "Ownership transferred successfully", + "201": { + "description": "Run created and jobs enqueued.", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SuccessResponse" + "$ref": "#/components/schemas/EvalRunsCreateResponse" } } } }, "400": { - "description": "Invalid user ID" + "description": "Invalid request body.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError400" + } + } + } }, "401": { - "description": "Authentication required" + "description": "Missing or invalid API key.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError401" + } + } + } }, "403": { - "description": "Permission denied - MANAGER role or owner required" + "description": "Insufficient permissions. The caller must have at least the Querier role on the prompt set's model.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError403" + } + } + } }, "404": { - "description": "Document or user not found" + "description": "The prompt set was not found, or `run_config.branch_id` does not match an existing branch in the organization.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError404" + } + } + } + }, + "422": { + "description": "`run_config.branch_id` does not belong to the prompt set's model.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError422" + } + } + } + }, + "429": { + "description": "Per-user active-run cap reached.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError429" + } + } + } + }, + "500": { + "description": "Run created and jobs enqueued, but it could not be re-read for the response. The run exists — list runs for the prompt set to find it rather than retrying, since a retry starts a duplicate run.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError500" + } + } + } + }, + "503": { + "description": "AI eval is paused for this organization.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError503" + } + } + } } } } }, - "/api/v1/documents/{identifier}/access-list": { + "/api/v1/ai/eval/runs/{runId}": { "get": { - "operationId": "documentsAccessList", - "summary": "List document access principals", + "description": "Get an eval run with every per-prompt result row, including the underlying agentic job state and any scoring data.", + "operationId": "aiEvalRunsGet", + "summary": "Get an eval run", "tags": [ - "Documents" + "AI Eval" ], "parameters": [ { "schema": { "type": "string", - "description": "Document identifier (either document ID or identifier slug)", - "example": "abc123" + "format": "uuid", + "description": "The unique identifier of the eval run.", + "example": "660e8400-e29b-41d4-a716-446655440001" }, "required": true, - "description": "Document identifier (either document ID or identifier slug)", - "name": "identifier", + "description": "The unique identifier of the eval run.", + "name": "runId", "in": "path" + } + ], + "responses": { + "200": { + "description": "Run detail.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalRunsGetResponse" + } + } + } }, - { - "schema": { - "type": "string", - "description": "Cursor for pagination (from previous response nextCursor)", - "example": "eyJpZCI6IjEyMzQ1In0" - }, - "required": false, - "description": "Cursor for pagination (from previous response nextCursor)", - "name": "cursor", - "in": "query" - }, - { - "schema": { - "type": "number", - "minimum": 1, - "maximum": 100, - "default": 20, - "description": "Number of results per page (1-100)", - "example": 20 - }, - "required": false, - "description": "Number of results per page (1-100)", - "name": "pageSize", - "in": "query" + "401": { + "description": "Missing or invalid API key.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError401" + } + } + } }, - { - "schema": { - "type": "string", - "enum": [ - "asc", - "desc" - ], - "default": "asc", - "description": "Sort direction (default: asc)", - "example": "desc" - }, - "required": false, - "description": "Sort direction (default: asc)", - "name": "sortDirection", - "in": "query" + "403": { + "description": "Insufficient permissions.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError403" + } + } + } }, + "404": { + "description": "Run not found.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError404" + } + } + } + } + } + }, + "delete": { + "description": "Archive (soft-delete) an eval run. Any non-terminal per-prompt agentic jobs are cancelled as part of the archive (best-effort), and a still-RUNNING run is flipped to CANCELLED before archival. The call is idempotent; archiving an already-terminal or already-archived run is a no-op.", + "operationId": "aiEvalRunsArchive", + "summary": "Archive an eval run", + "tags": [ + "AI Eval" + ], + "parameters": [ { "schema": { "type": "string", - "description": "Field to sort results by" + "format": "uuid", + "description": "The unique identifier of the eval run.", + "example": "660e8400-e29b-41d4-a716-446655440001" }, - "required": false, - "description": "Field to sort results by", - "name": "sortField", - "in": "query" + "required": true, + "description": "The unique identifier of the eval run.", + "name": "runId", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Run archived successfully.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalRunsDeleteResponse" + } + } + } }, - { - "schema": { - "type": "string", - "enum": [ - "direct", - "folder" - ], - "description": "Filter by access source: direct or folder" - }, - "required": false, - "description": "Filter by access source: direct or folder", - "name": "accessSource", - "in": "query" + "401": { + "description": "Missing or invalid API key.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError401" + } + } + } + }, + "403": { + "description": "Insufficient permissions.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError403" + } + } + } }, + "404": { + "description": "Run not found.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError404" + } + } + } + }, + "500": { + "description": "A still-running run may already be flipped to CANCELLED and archived even though the rest of the cascade failed — safe to retry.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError500" + } + } + } + } + } + } + }, + "/api/v1/ai/eval/runs/{runId}/cancel": { + "post": { + "description": "Cancel an in-flight eval run. Any non-terminal per-prompt jobs are cancelled and the run is archived — the response returns the updated run inline (`status: CANCELLED`, `is_archived: true`); use `/unarchive` to surface it in the default `archived=false` list again.", + "operationId": "aiEvalRunsCancel", + "summary": "Cancel an eval run", + "tags": [ + "AI Eval" + ], + "parameters": [ { "schema": { "type": "string", - "enum": [ - "user", - "userGroup" - ], - "description": "Filter by principal type: user or userGroup" + "format": "uuid", + "description": "The unique identifier of the eval run.", + "example": "660e8400-e29b-41d4-a716-446655440001" }, - "required": false, - "description": "Filter by principal type: user or userGroup", - "name": "type", - "in": "query" + "required": true, + "description": "The unique identifier of the eval run.", + "name": "runId", + "in": "path" } ], "responses": { "200": { - "description": "List of users and groups with access", + "description": "Cancellation processed.", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/DocumentsAccessListResponse" + "$ref": "#/components/schemas/EvalRunsCancelResponse" } } } }, "401": { - "description": "Authentication required" + "description": "Missing or invalid API key.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError401" + } + } + } }, "403": { - "description": "Permission denied - VIEWER role required" + "description": "Insufficient permissions.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError403" + } + } + } }, "404": { - "description": "Document not found" + "description": "Run not found.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError404" + } + } + } + }, + "500": { + "description": "The run was cancelled and archived, but could not be re-read for the response — safe to retry.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError500" + } + } + } } } } }, - "/api/v1/embed/sso/generate-session": { + "/api/v1/ai/eval/runs/{runId}/unarchive": { "post": { - "operationId": "embedSsoGenerateSession", - "summary": "Generate embedded SSO session", + "description": "Restore an archived eval run.", + "operationId": "aiEvalRunsUnarchive", + "summary": "Restore an archived eval run", "tags": [ - "Embed" + "AI Eval" ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/EmbedSsoGenerateSessionBody" - } - } + "parameters": [ + { + "schema": { + "type": "string", + "format": "uuid", + "description": "The unique identifier of the eval run.", + "example": "660e8400-e29b-41d4-a716-446655440001" + }, + "required": true, + "description": "The unique identifier of the eval run.", + "name": "runId", + "in": "path" } - }, + ], "responses": { "200": { - "description": "Session token generated", + "description": "Run restored successfully.", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/EmbedSsoGenerateSessionResponse" + "$ref": "#/components/schemas/EvalRunsUnarchiveResponse" } } } }, - "400": { - "description": "Invalid request body" - }, "401": { - "description": "Authentication required (API key with embed scope)" + "description": "Missing or invalid API key.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError401" + } + } + } }, "403": { - "description": "Permission denied - embed not enabled" + "description": "Insufficient permissions.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError403" + } + } + } + }, + "404": { + "description": "Run not found.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError404" + } + } + } } } } @@ -13437,6 +37724,7 @@ { "schema": { "type": "string", + "format": "uuid", "description": "Target user membership ID (for org-scoped API keys)" }, "required": false, @@ -13540,6 +37828,7 @@ { "schema": { "type": "string", + "format": "uuid", "description": "Target user membership ID (for org-scoped API keys)" }, "required": false, @@ -13606,6 +37895,7 @@ { "schema": { "type": "string", + "format": "uuid", "description": "Target user membership ID (for org-scoped API keys)" }, "required": false, @@ -14811,6 +39101,43 @@ "description": "Branch ID for branch-based schema refresh. Required when branch-based schema refresh is enabled for the connection. Must not be provided when branch-based schema refresh is not enabled.", "name": "branch_id", "in": "query" + }, + { + "schema": { + "type": "string", + "enum": [ + "true", + "false" + ], + "description": "When true (the default), performs a hard refresh that fully discards and rebuilds the schema model. When false, performs a soft refresh that merges newly generated views with the existing model. Must be set to false when `schemas` or `tables` filters are provided.", + "example": "false" + }, + "required": false, + "description": "When true (the default), performs a hard refresh that fully discards and rebuilds the schema model. When false, performs a soft refresh that merges newly generated views with the existing model. Must be set to false when `schemas` or `tables` filters are provided.", + "name": "hard_refresh", + "in": "query" + }, + { + "schema": { + "type": "string", + "description": "Optional comma-separated list of schemas to refresh selectively. Only the listed schemas are reloaded; the rest of the schema model is preserved. Requires `hard_refresh=false`.", + "example": "public,analytics" + }, + "required": false, + "description": "Optional comma-separated list of schemas to refresh selectively. Only the listed schemas are reloaded; the rest of the schema model is preserved. Requires `hard_refresh=false`.", + "name": "schemas", + "in": "query" + }, + { + "schema": { + "type": "string", + "description": "Optional comma-separated list of tables to refresh selectively. Only the listed tables are reloaded; the rest of the schema model is preserved. Requires `hard_refresh=false`.", + "example": "public.orders,public.customers" + }, + "required": false, + "description": "Optional comma-separated list of tables to refresh selectively. Only the listed tables are reloaded; the rest of the schema model is preserved. Requires `hard_refresh=false`.", + "name": "tables", + "in": "query" } ], "responses": { @@ -14825,7 +39152,7 @@ } }, "400": { - "description": "Bad request - branch_id required when branch-based schema refresh is enabled, or branch_id not allowed when it is not enabled" + "description": "Bad request - branch_id required when branch-based schema refresh is enabled, branch_id not allowed when it is not enabled, or hard refresh requested with selective schemas/tables filters" }, "401": { "description": "Authentication required" @@ -15050,15 +39377,15 @@ }, { "schema": { - "type": "number", + "type": "integer", "minimum": 1, "maximum": 100, "default": 20, - "description": "Number of results per page (1-100)", + "description": "Number of results per page (1-100, integer)", "example": 20 }, "required": false, - "description": "Number of results per page (1-100)", + "description": "Number of results per page (1-100, integer)", "name": "pageSize", "in": "query" }, @@ -15688,6 +40015,17 @@ "name": "content_filter_mode", "in": "query" }, + { + "schema": { + "type": "string", + "format": "uuid", + "description": "Filter to documents created by this user (user ID). Unknown IDs return 400." + }, + "required": false, + "description": "Filter to documents created by this user (user ID). Unknown IDs return 400.", + "name": "creator_id", + "in": "query" + }, { "schema": { "type": "string", @@ -15805,6 +40143,7 @@ { "schema": { "type": "string", + "format": "uuid", "description": "Target user membership ID (for org-scoped API keys)" }, "required": false, @@ -15897,7 +40236,7 @@ "extension", "staged", "merged", - "history" + "fully-resolved" ], "default": "combined", "description": "IDE mode for YAML operations" @@ -16084,7 +40423,7 @@ "extension", "staged", "merged", - "history" + "fully-resolved" ], "default": "combined", "description": "IDE mode for YAML operations" @@ -16124,6 +40463,51 @@ } } }, + "/api/v1/models/{modelId}/ai-agent-actions": { + "get": { + "description": "Returns the AI agent actions configured for this model — a unified list of sample queries and skills suitable for surfacing as suggested prompts above an AI prompt input. Sample queries come from both `model.sample_queries` and each topic's `sample_queries`; skills come from `model.skills` and each topic's `skills`, deduped by id with topic skills overriding model skills. Each entry's `prompt` is ready to submit verbatim to `POST /api/v1/ai/jobs`.", + "operationId": "modelAiAgentActions", + "summary": "Get model AI agent actions", + "tags": [ + "Models" + ], + "parameters": [ + { + "schema": { + "type": "string", + "format": "uuid", + "description": "Model UUID", + "example": "123e4567-e89b-12d3-a456-426614174000" + }, + "required": true, + "description": "Model UUID", + "name": "modelId", + "in": "path" + } + ], + "responses": { + "200": { + "description": "AI agent actions in display order.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AiAgentActionsResponse" + } + } + } + }, + "401": { + "description": "Missing or invalid API key." + }, + "403": { + "description": "Caller cannot read the model." + }, + "404": { + "description": "Model not found." + } + } + } + }, "/api/v1/query/run": { "post": { "operationId": "queryRun", @@ -16131,6 +40515,19 @@ "tags": [ "Query" ], + "parameters": [ + { + "schema": { + "type": "string", + "format": "uuid", + "description": "Target user membership ID (for org-scoped API keys)" + }, + "required": false, + "description": "Target user membership ID (for org-scoped API keys)", + "name": "userId", + "in": "query" + } + ], "requestBody": { "content": { "application/json": { @@ -16248,15 +40645,15 @@ }, { "schema": { - "type": "number", + "type": "integer", "minimum": 1, "maximum": 100, "default": 20, - "description": "Number of results per page (1-100)", + "description": "Number of results per page (1-100, integer)", "example": 20 }, "required": false, - "description": "Number of results per page (1-100)", + "description": "Number of results per page (1-100, integer)", "name": "pageSize", "in": "query" }, @@ -17118,7 +41515,7 @@ "description": "Schedule not found" }, "409": { - "description": "Another execution is in progress for this schedule" + "description": "Schedule cannot be triggered (paused, system-disabled, or another execution is in progress)" } } } @@ -18026,15 +42423,15 @@ }, { "schema": { - "type": "number", + "type": "integer", "minimum": 1, "maximum": 100, "default": 20, - "description": "Number of results per page (1-100)", + "description": "Number of results per page (1-100, integer)", "example": 20 }, "required": false, - "description": "Number of results per page (1-100)", + "description": "Number of results per page (1-100, integer)", "name": "pageSize", "in": "query" }, diff --git a/cmd/omni/agent_help.go b/cmd/omni/agent_help.go index 327abc9..3b42409 100644 --- a/cmd/omni/agent_help.go +++ b/cmd/omni/agent_help.go @@ -38,11 +38,29 @@ Set OMNI_API_TOKEN env var, or run: omni config init ### Download a dashboard omni dashboards download +### Read or edit a document (v2) + # Read live state. The response is a valid draft PATCH body (round-trip design). + omni documents v2-get --compact + + # Edit metadata with flags (no JSON needed), then publish the draft: + omni documents v2-patch-draft --name "Q3 Revenue" --summary "rename" + omni documents v2-publish-draft + + # Edit content by round-tripping the full state through a file: + omni documents v2-get > doc.json + # ...edit doc.json (containers, controls, queryPresentations, settings)... + omni documents v2-patch-draft --body - < doc.json + omni documents v2-publish-draft + + # Create a brand-new document (published immediately): + omni documents v2-create "My Dashboard" + ### Search Omni documentation omni ai search-omni-docs --body '{"query":"how do I..."}' ## Command Groups ai AI-powered query generation, jobs, doc search + ai-eval AI eval prompt set management connections Manage database connections content List content across the org dashboards Download dashboards, manage filters diff --git a/cmd/omni/openapi.json b/cmd/omni/openapi.json index b83fb7c..28c20c3 100644 --- a/cmd/omni/openapi.json +++ b/cmd/omni/openapi.json @@ -15,6 +15,10 @@ "description": "AI-powered data analysis. Submit natural language questions as synchronous queries or asynchronous jobs, and retrieve results including generated queries, data, and summarized answers.", "name": "AI" }, + { + "description": "AI evaluation: manage prompt sets and runs used to score AI quality against curated prompt suites.", + "name": "AI Eval" + }, { "description": "API token management", "name": "API Tokens" @@ -118,407 +122,559 @@ "description": "Update an existing variable by ID. Variable names cannot be changed after creation.", "title": "DbtEnvironmentVariableUpdate" }, - "AiGenerateQueryResponse": { + "CompositeFilter": { "type": "object", "properties": { - "error": { - "type": [ - "object", - "null" - ], - "properties": { - "detail": { - "type": "string", - "description": "Detailed error message explaining why query generation failed.", - "example": "The AI was unable to generate a query for this prompt. Try rephrasing your question to be more specific about the data you want to retrieve." - }, - "message": { - "type": "string", - "description": "Short error summary.", - "example": "No query generated" - } - }, - "required": [ - "detail", - "message" - ], - "description": "Error details if query generation failed. Null on success." - }, - "query": { - "$ref": "#/components/schemas/AiSemanticQuery" - }, - "result": { - "type": "object", - "additionalProperties": {}, - "description": "Query execution results as a JSON object. Only present when runQuery is true (the default) and the query executed successfully. The structure contains the query result data." + "cancel_query_filter": { + "type": "boolean" }, - "topic": { - "type": "string", - "description": "The topic name that was used for query generation.", - "example": "order_items" + "ignore_if_unjoinable": { + "type": "boolean" }, - "workbookUrl": { + "conjunction": { "type": "string", - "format": "uri", - "description": "URL to view and edit the generated query in an Omni workbook. Only present when workbookUrl was set to true in the request.", - "example": "https://myorg.omni.co/w/abc123/1" - } - }, - "required": [ - "error", - "query" - ] - }, - "AiSemanticQuery": { - "type": [ - "object", - "null" - ], - "properties": { - "fields": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Ordered list of fully qualified field names to include in the query (e.g., \"view_name.field_name\").", - "example": [ - "products.name", - "order_items.total_revenue" + "enum": [ + "OR", + "AND" ] }, "filters": { - "type": "object", - "additionalProperties": {}, - "description": "Filter conditions keyed by fully qualified field name. Filter values vary by field type." - }, - "limit": { - "type": "integer", - "description": "Maximum number of rows to return.", - "example": 500 - }, - "sorts": { "type": "array", "items": { - "$ref": "#/components/schemas/AiQuerySort" - }, - "description": "Sort specifications applied to the query results." - }, - "table": { - "type": "string", - "description": "The base topic or view name for the query.", - "example": "order_items" - } - }, - "required": [ - "fields" - ], - "additionalProperties": {}, - "description": "The generated semantic query definition. Null if generation failed. This query can be passed directly to the POST /api/v1/query/run endpoint." - }, - "AiQuerySort": { - "type": "object", - "properties": { - "column_name": { - "type": "string", - "description": "Fully qualified field name to sort by (e.g., \"view_name.field_name\").", - "example": "order_items.total_revenue" - }, - "sort_descending": { - "type": "boolean", - "description": "Whether to sort in descending order.", - "example": true - } - }, - "required": [ - "column_name", - "sort_descending" - ] - }, - "ApiError400": { - "type": "object", - "properties": { - "detail": { - "type": "string", - "description": "Human-readable error message describing what went wrong.", - "example": "Bad Request: prompt: Required" - }, - "status": { - "type": "integer", - "description": "HTTP status code of the error.", - "example": 400 - } - }, - "required": [ - "detail", - "status" - ] - }, - "ApiError401": { - "type": "object", - "properties": { - "detail": { - "type": "string", - "description": "Human-readable error message describing what went wrong.", - "example": "Unauthorized: Missing or invalid API key" - }, - "status": { - "type": "integer", - "description": "HTTP status code of the error.", - "example": 401 - } - }, - "required": [ - "detail", - "status" - ] - }, - "ApiError403": { - "type": "object", - "properties": { - "detail": { - "type": "string", - "description": "Human-readable error message describing what went wrong.", - "example": "Forbidden: AI query generation is not enabled for this organization" - }, - "status": { - "type": "integer", - "description": "HTTP status code of the error.", - "example": 403 - } - }, - "required": [ - "detail", - "status" - ] - }, - "ApiError404": { - "type": "object", - "properties": { - "detail": { - "type": "string", - "description": "Human-readable error message describing what went wrong.", - "example": "Model 770e8400-e29b-41d4-a716-446655440002 not found" - }, - "status": { - "type": "integer", - "description": "HTTP status code of the error.", - "example": 404 - } - }, - "required": [ - "detail", - "status" - ] - }, - "AiGenerateQueryBody": { - "allOf": [ - { - "$ref": "#/components/schemas/AiTopicParams" - }, - { - "type": "object", - "properties": { - "prompt": { - "type": "string", - "description": "The natural language prompt describing the data you want to retrieve.", - "example": "Show me total revenue by month for the last year" - }, - "queryAllViews": { - "type": "boolean", - "description": "If true and the model has query_all_views_and_fields enabled, AI can query views not in any topic." - }, - "runQuery": { - "type": "boolean", - "description": "Whether to execute the generated query and return results. Defaults to true. Set to false to only generate the query definition without executing it.", - "example": true - }, - "userId": { - "type": "string", - "format": "uuid", - "description": "User ID to execute the query as. Their permissions will be applied for row-level security. Only valid with organization-scoped API keys. Personal access tokens always act as the authenticated user.", - "example": "990e8400-e29b-41d4-a716-446655440004" - }, - "workbookUrl": { - "type": "boolean", - "description": "If true, creates a new workbook with the generated query and returns its URL. Useful for sharing results or further exploration.", - "example": false - } - }, - "required": [ - "prompt" - ] - } - ] - }, - "AiTopicParams": { - "type": "object", - "properties": { - "branchId": { - "type": "string", - "format": "uuid", - "description": "Optional branch ID for the model. Must be a branch of the shared model specified by modelId.", - "example": "550e8400-e29b-41d4-a716-446655440000" - }, - "currentTopicName": { - "type": "string", - "description": "The name of the current topic to scope query generation. If not provided, AI will automatically select the best topic for your prompt.", - "example": "order_items" - }, - "modelId": { - "type": "string", - "format": "uuid", - "description": "The UUID of the shared model to query against. Only shared models are supported.", - "example": "770e8400-e29b-41d4-a716-446655440002" - } - }, - "required": [ - "modelId" - ] - }, - "AiPickTopicResponse": { - "type": "object", - "properties": { - "topicId": { - "type": "string", - "description": "The name of the topic that best matches the prompt. Use this as the topicName parameter when calling generate-query or submitting an AI job.", - "example": "order_items" + "anyOf": [ + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "case_insensitive": { + "type": "boolean" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "kind": { + "type": "string", + "enum": [ + "CONTAINS", + "ENDS_WITH", + "STARTS_WITH", + "EQUALS", + "IS_EMPTY", + "SQL_LIKE" + ] + }, + "type": { + "type": "string", + "enum": [ + "string" + ] + }, + "values": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "kind", + "type", + "values" + ] + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "is_inclusive": { + "type": "boolean" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "kind": { + "type": "string", + "enum": [ + "LESS_THAN", + "GREATER_THAN", + "EQUALS", + "BETWEEN" + ] + }, + "type": { + "type": "string", + "enum": [ + "number" + ] + }, + "values": { + "type": "array", + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + } + ] + } + } + }, + "required": [ + "kind", + "type", + "values" + ] + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "isFiscal": { + "type": "boolean" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "kind": { + "type": "string", + "enum": [ + "IS_ON_DAY_OF_WEEK", + "IS_ON_DAY_OF_QUARTER", + "IS_IN_MONTH_OF_YEAR", + "IS_ON_DAY_OF_YEAR", + "IS_AT_HOUR_OF_DAY", + "IS_IN_QUARTER_OF_YEAR", + "IS_IN_WEEK_OF_YEAR", + "IS_ON_DAY_OF_MONTH", + "BETWEEN", + "ON_OR_AFTER", + "BEFORE", + "TIME_FOR_INTERVAL_DURATION", + "TIME_FOR_UNIT_DURATION", + "QUERY_OFFSET" + ] + }, + "left_side": { + "type": [ + "string", + "null" + ] + }, + "offset_interval_string": { + "type": [ + "string", + "null" + ] + }, + "right_side": { + "type": [ + "string", + "null" + ] + }, + "type": { + "type": "string", + "enum": [ + "date" + ] + }, + "ui_type": { + "type": [ + "string", + "null" + ], + "enum": [ + "ANY_TIME", + "BEFORE", + "BETWEEN", + "MONTH_OF_YEAR", + "PAST", + "YEAR", + "DAY", + "IS_ON_DAY_OF_WEEK", + "ON_OR_AFTER", + "IS_IN_THE_MONTH", + "IS_IN_THE_QUARTER", + "IS_IN_THE_FISCAL_QUARTER", + "IS_IN_THE_FISCAL_YEAR", + "TIME_FOR_INTERVAL_DURATION", + "TIME_FOR_UNIT_DURATION", + "CUSTOM", + null + ] + } + }, + "required": [ + "kind", + "type" + ] + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "type": { + "type": "string", + "enum": [ + "null" + ] + } + }, + "required": [ + "type" + ] + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "treat_nulls_as_false": { + "type": "boolean" + }, + "type": { + "type": "string", + "enum": [ + "boolean" + ] + } + }, + "required": [ + "type" + ] + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "disregard_limit": { + "type": "boolean" + }, + "field_name": { + "type": "string" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "query_id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "query" + ] + }, + "view_query": { + "type": "object", + "properties": { + "fields": { + "type": "array", + "items": { + "type": "string" + } + }, + "filters": { + "type": "object", + "additionalProperties": {}, + "default": {} + }, + "limit": { + "type": "number" + }, + "sorts": { + "type": "array", + "items": {}, + "default": [] + }, + "table": { + "type": "string" + } + }, + "required": [ + "fields" + ], + "additionalProperties": {} + } + }, + "required": [ + "type" + ] + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "type": { + "type": "string", + "enum": [ + "user_attribute" + ] + }, + "user_attribute_name": { + "type": "string" + } + }, + "required": [ + "type", + "user_attribute_name" + ] + }, + { + "$ref": "#/components/schemas/CompositeFilter" + } + ] + }, + "description": "Child filters — each a simple filter or another composite filter. Recursive; see the dashboard-filters reference for the full grammar." + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "type": { + "type": "string", + "enum": [ + "composite" + ] } }, "required": [ - "topicId" + "conjunction", + "filters", + "type" ] }, - "AiPickTopicBody": { - "allOf": [ - { - "$ref": "#/components/schemas/AiTopicParams" - }, - { - "type": "object", - "properties": { - "potentialTopicNames": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Optional list of topic names to limit consideration to. If not provided, all topics the user has access to in the model will be evaluated.", - "example": [ - "order_items", - "customers", - "products" - ] - }, - "prompt": { + "AiGenerateQueryResponse": { + "type": "object", + "properties": { + "baseView": { + "type": [ + "string", + "null" + ], + "description": "The base view name used for query generation when queryAllViews surfaced a non-topic view. Mutually exclusive with `topic` — exactly one is non-null when a query was generated.", + "example": null + }, + "downgradedModelTier": { + "type": "string", + "description": "Present only when the organization is over its AI downgrade threshold, signaling the query was generated on a downgraded (cheaper) model tier (e.g. 'haiku') to conserve credits. Advisory and best-effort — the call still succeeds, and clients may surface that a downgraded model was used. Absent when no downgrade applied.", + "example": "haiku" + }, + "error": { + "type": [ + "object", + "null" + ], + "properties": { + "detail": { "type": "string", - "description": "The natural language prompt to analyze. The AI will determine which topic best matches the data described in this prompt.", - "example": "How many orders were placed last month?" + "description": "Detailed error message explaining why query generation failed.", + "example": "The AI was unable to generate a query for this prompt. Try rephrasing your question to be more specific about the data you want to retrieve." }, - "userId": { + "message": { "type": "string", - "format": "uuid", - "description": "User ID to evaluate topic access as. Their permissions will be used for permission-aware topic selection. Only valid with organization-scoped API keys. Personal access tokens always act as the authenticated user.", - "example": "990e8400-e29b-41d4-a716-446655440004" + "description": "Short error summary.", + "example": "No query generated" } }, "required": [ - "prompt" - ] + "detail", + "message" + ], + "description": "Error details if query generation failed. Null on success." + }, + "query": { + "$ref": "#/components/schemas/AiSemanticQuery" + }, + "result": { + "type": "object", + "additionalProperties": {}, + "description": "Query execution results as a JSON object. Only present when runQuery is true (the default) and the query executed successfully. The structure contains the query result data." + }, + "topic": { + "type": [ + "string", + "null" + ], + "description": "The topic name used for query generation. Mutually exclusive with `baseView` — exactly one is non-null when a query was generated.", + "example": "order_items" + }, + "workbookUrl": { + "type": "string", + "format": "uri", + "description": "URL to view and edit the generated query in an Omni workbook. Only present when workbookUrl was set to true in the request.", + "example": "https://myorg.omni.co/w/abc123/1" } + }, + "required": [ + "error", + "query" ] }, - "AiSearchOmniDocsResponse": { - "type": "object", + "AiSemanticQuery": { + "type": [ + "object", + "null" + ], "properties": { - "answer": { - "type": "string", - "description": "A synthesized answer to the question, based on the Omni documentation.", - "example": "To create a dashboard filter, navigate to your dashboard and click the \"Add Filter\" button..." + "fields": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Ordered list of fully qualified field names to include in the query (e.g., \"view_name.field_name\").", + "example": [ + "products.name", + "order_items.total_revenue" + ] }, - "sources": { + "filters": { + "type": "object", + "additionalProperties": {}, + "description": "Filter conditions keyed by fully qualified field name. Filter values vary by field type." + }, + "limit": { + "type": "integer", + "description": "Maximum number of rows to return.", + "example": 500 + }, + "sorts": { "type": "array", "items": { - "type": "object", - "properties": { - "title": { - "type": "string", - "description": "The title of the source documentation page.", - "example": "Dashboard Filters" - }, - "url": { - "type": "string", - "format": "uri", - "description": "URL of the source documentation page.", - "example": "https://docs.omni.co/docs/dashboards/filters" - } - }, - "required": [ - "title", - "url" - ] + "$ref": "#/components/schemas/AiQuerySort" }, - "description": "List of documentation pages that were used to synthesize the answer." + "description": "Sort specifications applied to the query results." + }, + "table": { + "type": "string", + "description": "The base topic or view name for the query.", + "example": "order_items" } }, "required": [ - "answer", - "sources" - ] + "fields" + ], + "additionalProperties": {}, + "description": "The generated semantic query definition. Null if generation failed. This query can be passed directly to the POST /api/v1/query/run endpoint." }, - "AiSearchOmniDocsBody": { + "AiQuerySort": { "type": "object", "properties": { - "question": { + "column_name": { "type": "string", - "minLength": 1, - "maxLength": 2000, - "description": "A natural language question about Omni features, configuration, modeling, dashboards, or other topics covered in the Omni documentation.", - "example": "How do I create a dashboard filter?" + "description": "Fully qualified field name to sort by (e.g., \"view_name.field_name\").", + "example": "order_items.total_revenue" + }, + "sort_descending": { + "type": "boolean", + "description": "Whether to sort in descending order.", + "example": true } }, "required": [ - "question" + "column_name", + "sort_descending" ] }, - "AiJobSubmitResponse": { + "ApiError400": { "type": "object", "properties": { - "conversationId": { - "type": "string", - "format": "uuid", - "description": "The conversation ID for this job. Pass this as conversationId in subsequent job submissions to continue the conversation with additional context.", - "example": "660e8400-e29b-41d4-a716-446655440001" - }, - "jobId": { + "detail": { "type": "string", - "format": "uuid", - "description": "The unique identifier for the created job. Use this to poll status via GET /api/v1/ai/jobs/{jobId} or retrieve results via GET /api/v1/ai/jobs/{jobId}/result.", - "example": "550e8400-e29b-41d4-a716-446655440000" + "description": "Human-readable error message describing what went wrong.", + "example": "Bad Request: prompt: Required" }, - "omniChatUrl": { - "type": "string", - "format": "uri", - "description": "URL to view this conversation in the Omni chat interface. Opens the chat session where the job actions and results are visible.", - "example": "https://my-org.omni.co/chat/660e8400-e29b-41d4-a716-446655440001" + "status": { + "type": "integer", + "description": "HTTP status code of the error.", + "example": 400 } }, "required": [ - "conversationId", - "jobId", - "omniChatUrl" + "detail", + "status" ] }, - "ApiError409": { + "ApiError401": { "type": "object", "properties": { "detail": { "type": "string", "description": "Human-readable error message describing what went wrong.", - "example": "An active job already exists for this conversation" + "example": "Unauthorized: Missing or invalid API key" }, "status": { "type": "integer", "description": "HTTP status code of the error.", - "example": 409 + "example": 401 } }, "required": [ @@ -526,845 +682,1021 @@ "status" ] }, - "AiJobSubmitBody": { + "AiCreditShutoffError": { "type": "object", "properties": { - "branchId": { - "type": "string", - "format": "uuid", - "description": "Optional branch ID for the model. Must be a branch of the shared model specified by modelId. Use this to query against in-progress model changes.", - "example": "550e8400-e29b-41d4-a716-446655440000" - }, - "conversationId": { - "type": "string", - "format": "uuid", - "description": "Conversation ID to continue an existing conversation thread. The AI will have access to the context from previous jobs in the same conversation. If omitted, a new conversation is created. Only one active job can exist per conversation.", - "example": "660e8400-e29b-41d4-a716-446655440001" - }, - "modelId": { - "type": "string", - "format": "uuid", - "description": "The UUID of the shared model to query against. Only shared models are supported.", - "example": "770e8400-e29b-41d4-a716-446655440002" - }, - "progressWebhookEnabled": { - "type": "boolean", - "default": false, - "description": "When true, real-time progress events are POSTed to webhookUrl during execution (e.g., \"Searching for revenue fields\", \"Query returned 42 rows\"). Requires webhookUrl. Progress events are best-effort: single attempt, no retries, failures do not affect job execution.", - "example": true - }, - "prompt": { - "type": "string", - "minLength": 1, - "description": "The natural language prompt for the AI to process. The AI will analyze your question, generate appropriate queries, execute them, and return a summarized answer.", - "example": "What are the top 5 products by revenue this quarter?" - }, - "topicName": { + "code": { "type": "string", - "maxLength": 256, - "description": "Topic name to scope query generation. Topics define a set of related views and their join paths. If not provided, the AI will automatically select the best topic. Use the pick-topic endpoint to determine the right topic programmatically.", - "example": "order_items" - }, - "webhookMetadata": { - "type": "object", - "additionalProperties": {}, - "description": "Arbitrary metadata object that will be included unchanged in webhook payloads. Use this to correlate webhook notifications with your own system (e.g., tracking IDs, channel references).", - "example": { - "externalId": "task-123", - "slackChannel": "C0123456789" - } + "enum": [ + "shutoff" + ], + "description": "Stable reason code identifying an AI-credit shutoff.", + "example": "shutoff" }, - "webhookSigningSecret": { + "detail": { "type": "string", - "description": "Secret key for HMAC-SHA256 webhook payload signing. When provided, each webhook request includes X-Omni-Signature and X-Omni-Signature-Timestamp headers for verification. Required if webhookUrl is specified." + "description": "Human-readable error message describing what went wrong.", + "example": "The AI agent is currently unavailable. Contact your administrator to re-enable." }, - "webhookUrl": { - "type": "string", - "format": "uri", - "description": "URL to receive webhook POSTs. Always receives a terminal event (job.complete or job.failed) when the job finishes. When progressWebhookEnabled is true, also receives real-time progress events during execution.", - "example": "https://example.com/webhooks/omni" + "status": { + "type": "integer", + "description": "HTTP status code of the error.", + "example": 402 } }, "required": [ - "modelId", - "prompt" + "code", + "detail", + "status" ] }, - "AiJobStatusResponse": { + "ApiError403": { "type": "object", "properties": { - "branchId": { - "type": [ - "string", - "null" - ], - "format": "uuid", - "description": "Branch ID used for model context, or null if querying the main shared model." - }, - "cancelledAt": { - "type": "string", - "format": "date-time", - "description": "When the job was cancelled. Only present in CANCELLED state.", - "example": "2025-01-15T10:00:12.000Z" - }, - "cancelledBy": { - "type": "string", - "format": "uuid", - "description": "User ID of who cancelled the job. Only present in CANCELLED state.", - "example": "990e8400-e29b-41d4-a716-446655440004" - }, - "completedAt": { + "detail": { "type": "string", - "format": "date-time", - "description": "When the job finished (successfully or with error). Present in COMPLETE and FAILED states.", - "example": "2025-01-15T10:01:30.000Z" + "description": "Human-readable error message describing what went wrong.", + "example": "Forbidden: AI query generation is not enabled for this organization" }, - "conversationId": { + "status": { + "type": "integer", + "description": "HTTP status code of the error.", + "example": 403 + } + }, + "required": [ + "detail", + "status" + ] + }, + "ApiError404": { + "type": "object", + "properties": { + "detail": { "type": "string", - "format": "uuid", - "description": "The conversation this job belongs to. Use this to submit follow-up jobs in the same conversation thread.", - "example": "660e8400-e29b-41d4-a716-446655440001" + "description": "Human-readable error message describing what went wrong.", + "example": "Model 770e8400-e29b-41d4-a716-446655440002 not found" }, - "createdAt": { - "type": "string", - "format": "date-time", - "description": "When the job was submitted.", - "example": "2025-01-15T10:00:00.000Z" + "status": { + "type": "integer", + "description": "HTTP status code of the error.", + "example": 404 + } + }, + "required": [ + "detail", + "status" + ] + }, + "AiGenerateQueryBody": { + "allOf": [ + { + "$ref": "#/components/schemas/AiTopicParams" }, - "error": { + { "type": "object", "properties": { - "code": { + "prompt": { "type": "string", - "description": "Machine-readable error code.", - "example": "QUERY_EXECUTION_ERROR" + "description": "The natural language prompt describing the data you want to retrieve.", + "example": "Show me total revenue by month for the last year" }, - "detail": { - "type": "string", - "description": "Additional error detail or context.", - "example": "The query timed out after 300 seconds" + "queryAllViews": { + "type": "boolean", + "description": "If true and the model has query_all_views_and_fields enabled, AI can query views not in any topic." }, - "message": { - "type": "string", - "description": "Human-readable error message.", - "example": "Column 'revenue' not found in table 'orders'" - } - }, - "required": [ - "message" - ], - "additionalProperties": {}, - "description": "Error details explaining why the job failed. Only present in FAILED state." - }, - "executionStartedAt": { - "type": "string", - "format": "date-time", - "description": "When execution began. Present once the job transitions from QUEUED to EXECUTING. May be absent on jobs that failed or were cancelled before execution started.", - "example": "2025-01-15T10:00:05.000Z" - }, - "id": { - "type": "string", - "format": "uuid", - "description": "The unique identifier for this job.", - "example": "550e8400-e29b-41d4-a716-446655440000" - }, - "modelId": { - "type": [ - "string", - "null" - ], - "format": "uuid", - "description": "The shared model ID used for query generation.", - "example": "770e8400-e29b-41d4-a716-446655440002" - }, - "omniChatUrl": { - "type": "string", - "format": "uri", - "description": "URL to view this conversation in the Omni chat interface. Opens the chat session where the job actions and results are visible.", - "example": "https://my-org.omni.co/chat/660e8400-e29b-41d4-a716-446655440001" - }, - "organizationId": { - "type": "string", - "format": "uuid", - "description": "The organization that owns this job.", - "example": "880e8400-e29b-41d4-a716-446655440003" - }, - "progress": { - "type": [ - "object", - "null" - ], - "properties": { - "iteration": { - "type": "integer", - "description": "Current iteration number. The AI may take multiple iterations to refine queries and generate a complete answer.", - "example": 2 + "runQuery": { + "type": "boolean", + "description": "Whether to execute the generated query and return results. Defaults to true. Set to false to only generate the query definition without executing it.", + "example": true }, - "message": { + "userId": { "type": "string", - "description": "Human-readable status message describing what the AI is currently doing.", - "example": "Running query: Top products by revenue" + "format": "uuid", + "description": "User ID to execute the query as. Their permissions will be applied for row-level security. Only valid with organization-scoped API keys. Personal access tokens always act as the authenticated user.", + "example": "990e8400-e29b-41d4-a716-446655440004" }, - "updatedAt": { - "type": "string", - "format": "date-time", - "description": "When this progress update was recorded.", - "example": "2025-01-15T10:00:08.000Z" + "workbookUrl": { + "type": "boolean", + "description": "If true, creates a new workbook with the generated query and returns its URL. Useful for sharing results or further exploration.", + "example": false } }, "required": [ - "iteration", - "message", - "updatedAt" - ], - "description": "Real-time progress information. Only present in EXECUTING state. Null if no progress has been reported yet. Updated in real-time as the AI works through iterations." - }, - "prompt": { - "type": "string", - "description": "The natural language prompt that was submitted.", - "example": "What are the top 5 products by revenue?" - }, - "resultSummary": { + "prompt" + ] + } + ] + }, + "AiTopicParams": { + "type": "object", + "properties": { + "branchId": { "type": "string", - "description": "Markdown-formatted summary of the job result. Only present in COMPLETE state. For the full result with query details and data, use GET /api/v1/ai/jobs/{jobId}/result.", - "example": "### Top 5 Products by Revenue\n\n1. **Sunglasses** - $678,994\n2. **Jeans** - $475,072" + "format": "uuid", + "description": "Optional branch ID for the model. Must be a branch of the shared model specified by modelId.", + "example": "550e8400-e29b-41d4-a716-446655440000" }, - "state": { + "currentTopicName": { "type": "string", - "enum": [ - "CANCELLED", - "COMPLETE", - "DELIVERING", - "EXECUTING", - "FAILED", - "QUEUED" - ], - "description": "Current state of the job. Terminal states are COMPLETE, FAILED, and CANCELLED. Poll until the job reaches a terminal state.", - "example": "QUEUED" - }, - "topicName": { - "type": [ - "string", - "null" - ], - "description": "Topic name used to scope query generation, or null if the AI selected the topic automatically.", + "description": "The name of the current topic to scope query generation. If not provided, AI will automatically select the best topic for your prompt.", "example": "order_items" }, - "updatedAt": { - "type": "string", - "format": "date-time", - "description": "When the job record was last modified.", - "example": "2025-01-15T10:00:05.000Z" - }, - "userId": { + "modelId": { "type": "string", "format": "uuid", - "description": "The user ID who created (or is associated with) this job.", - "example": "990e8400-e29b-41d4-a716-446655440004" + "description": "The UUID of the shared model to query against. Only shared models are supported.", + "example": "770e8400-e29b-41d4-a716-446655440002" } }, "required": [ - "branchId", - "conversationId", - "createdAt", - "id", - "modelId", - "omniChatUrl", - "organizationId", - "prompt", - "state", - "topicName", - "updatedAt", - "userId" + "modelId" ] }, - "AiJobCancelResponse": { + "AiPickTopicResponse": { "type": "object", "properties": { - "jobId": { - "type": "string", - "format": "uuid", - "description": "The job ID that was requested to cancel.", - "example": "550e8400-e29b-41d4-a716-446655440000" - }, - "state": { + "topicId": { "type": "string", - "enum": [ - "CANCELLED", - "COMPLETE", - "DELIVERING", - "EXECUTING", - "FAILED", - "QUEUED" - ], - "description": "The job state after the cancellation attempt. CANCELLED if the cancellation was successful. If the job was already in a terminal state (COMPLETE, FAILED, CANCELLED), the current state is returned unchanged — the endpoint is idempotent.", - "example": "CANCELLED" + "description": "The name of the topic that best matches the prompt. Use this as the topicName parameter when calling generate-query or submitting an AI job.", + "example": "order_items" } }, "required": [ - "jobId", - "state" + "topicId" ] }, - "AiJobResultResponse": { - "type": "object", - "properties": { - "actions": { - "type": "array", + "AiPickTopicBody": { + "allOf": [ + { + "$ref": "#/components/schemas/AiTopicParams" + }, + { + "type": "object", + "properties": { + "potentialTopicNames": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Optional list of topic names to limit consideration to. If not provided, all topics the user has access to in the model will be evaluated.", + "example": [ + "order_items", + "customers", + "products" + ] + }, + "prompt": { + "type": "string", + "description": "The natural language prompt to analyze. The AI will determine which topic best matches the data described in this prompt.", + "example": "How many orders were placed last month?" + }, + "userId": { + "type": "string", + "format": "uuid", + "description": "User ID to evaluate topic access as. Their permissions will be used for permission-aware topic selection. Only valid with organization-scoped API keys. Personal access tokens always act as the authenticated user.", + "example": "990e8400-e29b-41d4-a716-446655440004" + } + }, + "required": [ + "prompt" + ] + } + ] + }, + "AiSearchOmniDocsResponse": { + "type": "object", + "properties": { + "answer": { + "type": "string", + "description": "A synthesized answer to the question, based on the Omni documentation.", + "example": "To create a dashboard filter, navigate to your dashboard and click the \"Add Filter\" button..." + }, + "sources": { + "type": "array", "items": { - "$ref": "#/components/schemas/AiJobAction" + "type": "object", + "properties": { + "title": { + "type": "string", + "description": "The title of the source documentation page.", + "example": "Dashboard Filters" + }, + "url": { + "type": "string", + "format": "uri", + "description": "URL of the source documentation page.", + "example": "https://docs.omni.co/docs/dashboards/filters" + } + }, + "required": [ + "title", + "url" + ] }, - "description": "Ordered list of actions the AI took during execution. Each action represents a step such as generating a query, executing it, or synthesizing a final answer." + "description": "List of documentation pages that were used to synthesize the answer." + } + }, + "required": [ + "answer", + "sources" + ] + }, + "AiSearchOmniDocsBody": { + "type": "object", + "properties": { + "question": { + "type": "string", + "minLength": 1, + "maxLength": 2000, + "description": "A natural language question about Omni features, configuration, modeling, dashboards, or other topics covered in the Omni documentation.", + "example": "How do I create a dashboard filter?" + } + }, + "required": [ + "question" + ] + }, + "AiJobSubmitResponse": { + "type": "object", + "properties": { + "conversationId": { + "type": "string", + "format": "uuid", + "description": "The conversation ID for this job. Pass this as conversationId in subsequent job submissions to continue the conversation with additional context.", + "example": "660e8400-e29b-41d4-a716-446655440001" }, - "message": { + "jobId": { "type": "string", - "description": "The AI's final response message in Markdown format. This is the complete answer to the original prompt, incorporating data from all executed queries.", - "example": "### Top 5 Products by Revenue\n\n1. **Sunglasses** - $678,994\n2. **Jeans** - $475,072" + "format": "uuid", + "description": "The unique identifier for the created job. Use this to poll status via GET /api/v1/ai/jobs/{jobId} or retrieve results via GET /api/v1/ai/jobs/{jobId}/result.", + "example": "550e8400-e29b-41d4-a716-446655440000" }, "omniChatUrl": { "type": "string", "format": "uri", "description": "URL to view this conversation in the Omni chat interface. Opens the chat session where the job actions and results are visible.", "example": "https://my-org.omni.co/chat/660e8400-e29b-41d4-a716-446655440001" - }, - "resultSummary": { - "type": "string", - "description": "Summary of the job result. Typically matches the final message content.", - "example": "### Top 5 Products by Revenue\n\n1. **Sunglasses** - $678,994\n2. **Jeans** - $475,072" - }, - "topic": { - "type": "string", - "description": "The topic name used for query generation.", - "example": "order_items" } }, - "additionalProperties": {} + "required": [ + "conversationId", + "jobId", + "omniChatUrl" + ] }, - "AiJobAction": { + "ApiError409": { "type": "object", "properties": { - "message": { - "type": "string", - "description": "The AI's explanation of what it is doing in this step, written in natural language.", - "example": "I'll generate a query to find the top 5 products by total revenue." - }, - "result": { - "$ref": "#/components/schemas/AiJobActionQueryResult" - }, - "timestamp": { + "detail": { "type": "string", - "description": "ISO 8601 timestamp when this action occurred.", - "example": "2025-01-15T10:00:10.000Z" + "description": "Human-readable error message describing what went wrong.", + "example": "An active job already exists for this conversation" }, - "type": { - "type": "string", - "description": "The type of action. Common types include \"generate_query\" (query generation and execution) and \"summarize\" (final answer synthesis).", - "example": "generate_query" + "status": { + "type": "integer", + "description": "HTTP status code of the error.", + "example": 409 } }, "required": [ - "message", - "timestamp", - "type" - ], - "additionalProperties": {} + "detail", + "status" + ] }, - "AiJobActionQueryResult": { + "AiJobSubmitBody": { "type": "object", "properties": { - "csvResult": { + "branchId": { "type": "string", - "description": "Query results formatted as CSV text.", - "example": "Name,Total Revenue\nRay-Ban Sunglasses,\"678,994.41\"\nLevi's 501 Jeans,\"475,072.00\"" + "format": "uuid", + "description": "Optional branch ID for the model. Must be a branch of the shared model specified by modelId. Use this to query against in-progress model changes.", + "example": "550e8400-e29b-41d4-a716-446655440000" }, - "csvResultWasTruncated": { - "type": "boolean", - "description": "Whether the CSV data was truncated due to size limits. If true, the full result set may contain additional rows not included in csvResult.", - "example": false + "conversationId": { + "type": "string", + "format": "uuid", + "description": "Conversation ID to continue an existing conversation thread. The AI will have access to the context from previous jobs in the same conversation. If omitted, a new conversation is created. Only one active job can exist per conversation.", + "example": "660e8400-e29b-41d4-a716-446655440001" }, - "hasResults": { + "modelId": { + "type": "string", + "format": "uuid", + "description": "The UUID of the shared model to query against. Only shared models are supported.", + "example": "770e8400-e29b-41d4-a716-446655440002" + }, + "progressWebhookEnabled": { "type": "boolean", - "description": "Whether the query returned any data rows.", + "default": false, + "description": "When true, real-time progress events are POSTed to webhookUrl during execution (e.g., \"Searching for revenue fields\", \"Query returned 42 rows\"). Requires webhookUrl. Progress events are best-effort: single attempt, no retries, failures do not affect job execution.", "example": true }, - "query": { - "type": "object", - "additionalProperties": {}, - "description": "The semantic query definition that was executed. This can be used with the POST /api/v1/query/run endpoint to re-run the query." + "prompt": { + "type": "string", + "minLength": 1, + "description": "The natural language prompt for the AI to process. The AI will analyze your question, generate appropriate queries, execute them, and return a summarized answer.", + "example": "What are the top 5 products by revenue this quarter?" }, - "queryName": { + "topicName": { "type": "string", - "description": "Human-readable name describing what this query retrieves.", - "example": "Top 5 Products by Revenue" + "maxLength": 256, + "description": "Topic name to scope query generation. Topics define a set of related views and their join paths. If not provided, the AI will automatically select the best topic. Use the pick-topic endpoint to determine the right topic programmatically.", + "example": "order_items" }, - "status": { + "webhookMetadata": { + "type": "object", + "additionalProperties": {}, + "description": "Arbitrary metadata object that will be included unchanged in webhook payloads. Use this to correlate webhook notifications with your own system (e.g., tracking IDs, channel references).", + "example": { + "externalId": "task-123", + "slackChannel": "C0123456789" + } + }, + "webhookSigningSecret": { "type": "string", - "enum": [ - "success", - "error" - ], - "description": "Whether the query executed successfully.", - "example": "success" + "description": "Secret key for HMAC-SHA256 webhook payload signing. When provided, each webhook request includes X-Omni-Signature and X-Omni-Signature-Timestamp headers for verification. Required if webhookUrl is specified." }, - "totalRowCount": { - "type": "integer", - "description": "Total number of rows returned by the query.", - "example": 5 - } - }, - "required": [ - "csvResult", - "csvResultWasTruncated", - "hasResults", - "query", - "queryName", - "status", - "totalRowCount" - ], - "description": "Query result data. Only present for generate_query action types." - }, - "ApiError422": { - "type": "object", - "properties": { - "error": { + "webhookUrl": { "type": "string", - "description": "Human-readable error message describing what went wrong.", - "example": "No Arrow IPC data available for visualization" + "format": "uri", + "description": "URL to receive webhook POSTs. Always receives a terminal event (job.complete or job.failed) when the job finishes. When progressWebhookEnabled is true, also receives real-time progress events during execution.", + "example": "https://example.com/webhooks/omni" } }, "required": [ - "error" + "modelId", + "prompt" ] }, - "ApiKeyListResponse": { + "AiJobStatusResponse": { "type": "object", "properties": { - "pageInfo": { - "$ref": "#/components/schemas/PageInfo" - }, - "records": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ApiKey" - } - } - }, - "required": [ - "pageInfo", - "records" - ] - }, - "PageInfo": { - "type": "object", - "properties": { - "hasNextPage": { - "type": "boolean", - "description": "Whether more results are available" - }, - "nextCursor": { + "branchId": { "type": [ "string", "null" ], - "description": "Cursor for fetching the next page" + "format": "uuid", + "description": "Branch ID used for model context, or null if querying the main shared model." }, - "pageSize": { - "type": "number", - "description": "Number of results per page" + "cancelledAt": { + "type": "string", + "format": "date-time", + "description": "When the job was cancelled. Only present in CANCELLED state.", + "example": "2025-01-15T10:00:12.000Z" + }, + "cancelledBy": { + "type": "string", + "format": "uuid", + "description": "User ID of who cancelled the job. Only present in CANCELLED state.", + "example": "990e8400-e29b-41d4-a716-446655440004" + }, + "completedAt": { + "type": "string", + "format": "date-time", + "description": "When the job finished (successfully or with error). Present in COMPLETE and FAILED states.", + "example": "2025-01-15T10:01:30.000Z" + }, + "conversationId": { + "type": "string", + "format": "uuid", + "description": "The conversation this job belongs to. Use this to submit follow-up jobs in the same conversation thread.", + "example": "660e8400-e29b-41d4-a716-446655440001" }, - "totalRecords": { - "type": "number", - "description": "Total number of records matching the query" - } - }, - "required": [ - "hasNextPage", - "nextCursor", - "pageSize", - "totalRecords" - ] - }, - "ApiKey": { - "type": "object", - "properties": { "createdAt": { "type": "string", "format": "date-time", - "description": "ISO 8601 timestamp of when the token was created", - "example": "2026-01-15T10:00:00.000Z" + "description": "When the job was submitted.", + "example": "2025-01-15T10:00:00.000Z" }, - "enabled": { - "type": "boolean", - "description": "Whether the token can currently authenticate. Organization tokens may be disabled by admins; personal and MCP tokens are always `true` (revocation deletes them).", - "example": true + "error": { + "type": "object", + "properties": { + "code": { + "type": "string", + "description": "Machine-readable error code.", + "example": "QUERY_EXECUTION_ERROR" + }, + "detail": { + "type": "string", + "description": "Additional error detail or context.", + "example": "The query timed out after 300 seconds" + }, + "message": { + "type": "string", + "description": "Human-readable error message.", + "example": "Column 'revenue' not found in table 'orders'" + } + }, + "required": [ + "message" + ], + "additionalProperties": {}, + "description": "Error details explaining why the job failed. Only present in FAILED state." + }, + "executionStartedAt": { + "type": "string", + "format": "date-time", + "description": "When execution began. Present once the job transitions from QUEUED to EXECUTING. May be absent on jobs that failed or were cancelled before execution started.", + "example": "2025-01-15T10:00:05.000Z" }, "id": { "type": "string", "format": "uuid", - "description": "Unique identifier for the token", - "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" + "description": "The unique identifier for this job.", + "example": "550e8400-e29b-41d4-a716-446655440000" }, - "membershipId": { + "modelId": { "type": [ "string", "null" ], "format": "uuid", - "description": "Membership ID of the user the token is scoped to. Null for organization-level tokens.", - "example": "b2c3d4e5-f6a7-8901-bcde-f12345678901" + "description": "The shared model ID used for query generation.", + "example": "770e8400-e29b-41d4-a716-446655440002" }, - "name": { + "omniChatUrl": { "type": "string", - "description": "Human-readable name for the token", - "example": "CI deployment key" + "format": "uri", + "description": "URL to view this conversation in the Omni chat interface. Opens the chat session where the job actions and results are visible.", + "example": "https://my-org.omni.co/chat/660e8400-e29b-41d4-a716-446655440001" }, - "type": { + "organizationId": { + "type": "string", + "format": "uuid", + "description": "The organization that owns this job.", + "example": "880e8400-e29b-41d4-a716-446655440003" + }, + "progress": { + "type": [ + "object", + "null" + ], + "properties": { + "iteration": { + "type": "integer", + "description": "Current iteration number. The AI may take multiple iterations to refine queries and generate a complete answer.", + "example": 2 + }, + "message": { + "type": "string", + "description": "Human-readable status message describing what the AI is currently doing.", + "example": "Running query: Top products by revenue" + }, + "updatedAt": { + "type": "string", + "format": "date-time", + "description": "When this progress update was recorded.", + "example": "2025-01-15T10:00:08.000Z" + } + }, + "required": [ + "iteration", + "message", + "updatedAt" + ], + "description": "Real-time progress information. Only present in EXECUTING state. Null if no progress has been reported yet. Updated in real-time as the AI works through iterations." + }, + "prompt": { + "type": "string", + "description": "The natural language prompt that was submitted.", + "example": "What are the top 5 products by revenue?" + }, + "resultSummary": { + "type": "string", + "description": "Markdown-formatted summary of the job result. Only present in COMPLETE state. For the full result with query details and data, use GET /api/v1/ai/jobs/{jobId}/result.", + "example": "### Top 5 Products by Revenue\n\n1. **Sunglasses** - $678,994\n2. **Jeans** - $475,072" + }, + "state": { "type": "string", "enum": [ - "organization", - "personal", - "mcp" + "CANCELLED", + "COMPLETE", + "DELIVERING", + "EXECUTING", + "FAILED", + "QUEUED" ], - "description": "Token type: `organization` (org-level), `personal` (user-created personal access token), or `mcp` (MCP OAuth grant).", - "example": "organization" + "description": "Current state of the job. Terminal states are COMPLETE, FAILED, and CANCELLED. Poll until the job reaches a terminal state.", + "example": "QUEUED" + }, + "topicName": { + "type": [ + "string", + "null" + ], + "description": "Topic name used to scope query generation, or null if the AI selected the topic automatically.", + "example": "order_items" + }, + "updatedAt": { + "type": "string", + "format": "date-time", + "description": "When the job record was last modified.", + "example": "2025-01-15T10:00:05.000Z" + }, + "userId": { + "type": "string", + "format": "uuid", + "description": "The user ID who created (or is associated with) this job.", + "example": "990e8400-e29b-41d4-a716-446655440004" } }, "required": [ + "branchId", + "conversationId", "createdAt", - "enabled", "id", - "membershipId", - "name", - "type" + "modelId", + "omniChatUrl", + "organizationId", + "prompt", + "state", + "topicName", + "updatedAt", + "userId" ] }, - "ApiKeyUpdateBody": { - "type": "object", - "properties": { - "enabled": { - "type": "boolean", - "description": "Set to `false` to disable the token, `true` to re-enable it. Only organization-level tokens may be disabled; personal and MCP tokens do not support this.", - "example": false - } - }, - "required": [ - "enabled" - ], - "additionalProperties": false - }, - "ApiKeyDeleteResponse": { + "AiJobCancelResponse": { "type": "object", "properties": { - "message": { + "jobId": { "type": "string", - "description": "Human-readable description of the outcome", - "example": "API token revoked" + "format": "uuid", + "description": "The job ID that was requested to cancel.", + "example": "550e8400-e29b-41d4-a716-446655440000" }, - "success": { - "type": "boolean", + "state": { + "type": "string", "enum": [ - true + "CANCELLED", + "COMPLETE", + "DELIVERING", + "EXECUTING", + "FAILED", + "QUEUED" ], - "description": "Always `true` on a successful revocation" + "description": "The job state after the cancellation attempt. CANCELLED if the cancellation was successful. If the job was already in a terminal state (COMPLETE, FAILED, CANCELLED), the current state is returned unchanged — the endpoint is idempotent.", + "example": "CANCELLED" } }, "required": [ - "message", - "success" + "jobId", + "state" ] }, - "DbtEnvironmentListResponse": { + "AiJobResultResponse": { "type": "object", "properties": { - "pageInfo": { - "$ref": "#/components/schemas/PageInfo" - }, - "records": { + "actions": { "type": "array", "items": { - "$ref": "#/components/schemas/DbtEnvironmentItem" - } + "$ref": "#/components/schemas/AiJobAction" + }, + "description": "Ordered list of actions the AI took during execution. Each action represents a step such as generating a query, executing it, or synthesizing a final answer." + }, + "message": { + "type": "string", + "description": "The AI's final response message in Markdown format. This is the complete answer to the original prompt, incorporating data from all executed queries.", + "example": "### Top 5 Products by Revenue\n\n1. **Sunglasses** - $678,994\n2. **Jeans** - $475,072" + }, + "omniChatUrl": { + "type": "string", + "format": "uri", + "description": "URL to view this conversation in the Omni chat interface. Opens the chat session where the job actions and results are visible.", + "example": "https://my-org.omni.co/chat/660e8400-e29b-41d4-a716-446655440001" + }, + "resultSummary": { + "type": "string", + "description": "Summary of the job result. Typically matches the final message content.", + "example": "### Top 5 Products by Revenue\n\n1. **Sunglasses** - $678,994\n2. **Jeans** - $475,072" + }, + "topic": { + "type": "string", + "description": "The topic name used for query generation.", + "example": "order_items" + } + }, + "additionalProperties": {} + }, + "AiJobAction": { + "type": "object", + "properties": { + "message": { + "type": "string", + "description": "The AI's explanation of what it is doing in this step, written in natural language.", + "example": "I'll generate a query to find the top 5 products by total revenue." + }, + "result": { + "$ref": "#/components/schemas/AiJobActionQueryResult" + }, + "timestamp": { + "type": "string", + "description": "ISO 8601 timestamp when this action occurred.", + "example": "2025-01-15T10:00:10.000Z" + }, + "type": { + "type": "string", + "description": "The type of action. Common types include \"generate_query\" (query generation and execution) and \"summarize\" (final answer synthesis).", + "example": "generate_query" } }, "required": [ - "pageInfo", - "records" - ] + "message", + "timestamp", + "type" + ], + "additionalProperties": {} }, - "DbtEnvironmentItem": { + "AiJobActionQueryResult": { "type": "object", "properties": { - "id": { + "csvResult": { "type": "string", - "format": "uuid", - "description": "Unique environment identifier" + "description": "Query results formatted as CSV text.", + "example": "Name,Total Revenue\nRay-Ban Sunglasses,\"678,994.41\"\nLevi's 501 Jeans,\"475,072.00\"" }, - "isDefaultEnvironment": { + "csvResultWasTruncated": { "type": "boolean", - "description": "Whether this is the default environment" + "description": "Whether the CSV data was truncated due to size limits. If true, the full result set may contain additional rows not included in csvResult.", + "example": false }, - "name": { + "hasResults": { + "type": "boolean", + "description": "Whether the query returned any data rows.", + "example": true + }, + "query": { + "type": "object", + "additionalProperties": {}, + "description": "The semantic query definition that was executed. This can be used with the POST /api/v1/query/run endpoint to re-run the query." + }, + "queryName": { "type": "string", - "description": "Environment name" + "description": "Human-readable name describing what this query retrieves.", + "example": "Top 5 Products by Revenue" }, - "ownerId": { - "type": [ - "string", - "null" + "status": { + "type": "string", + "enum": [ + "success", + "error" ], - "description": "User ID of the environment owner, or null if not a personal environment" + "description": "Whether the query executed successfully.", + "example": "success" }, - "targetDatabase": { - "type": [ - "string", - "null" - ], - "description": "Target database override" + "totalRowCount": { + "type": "integer", + "description": "Total number of rows returned by the query.", + "example": 5 + } + }, + "required": [ + "csvResult", + "csvResultWasTruncated", + "hasResults", + "query", + "queryName", + "status", + "totalRowCount" + ], + "description": "Query result data. Only present for generate_query action types." + }, + "ApiError422": { + "type": "object", + "properties": { + "error": { + "type": "string", + "description": "Human-readable error message describing what went wrong.", + "example": "No Arrow IPC data available for visualization" + } + }, + "required": [ + "error" + ] + }, + "AiBrandingResponse": { + "type": "object", + "properties": { + "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." }, - "targetName": { - "type": [ - "string", - "null" - ], - "description": "Target name override" + "headline": { + "type": "string", + "description": "Short headline shown on AI helper landing surfaces.", + "example": "What would you like to know?" }, - "targetRole": { + "logoUrl": { "type": [ "string", "null" ], - "description": "Target role override" + "format": "uri", + "description": "Absolute URL to a custom AI helper logo. `null` when the org has not configured a custom logo — clients should render their default avatar (e.g. Blobby).", + "example": "https://example.com/blobby.png" }, - "targetSchema": { + "name": { "type": "string", - "description": "Target schema" + "description": "Display name for the AI helper. Defaults to `Omni Agent` when no custom branding is set.", + "example": "Blobby" }, - "variables": { + "placeholder": { + "type": "string", + "description": "Placeholder text for the AI helper's prompt input.", + "example": "Ask a question about your data..." + } + }, + "required": [ + "body", + "headline", + "logoUrl", + "name", + "placeholder" + ] + }, + "AiConversationsListResponse": { + "type": "object", + "properties": { + "pageInfo": { + "$ref": "#/components/schemas/PageInfo" + }, + "records": { "type": "array", "items": { - "$ref": "#/components/schemas/DbtEnvironmentResponseVariable" + "$ref": "#/components/schemas/AiConversation" }, - "description": "Environment variables" + "description": "Conversations ordered by updatedAt descending." } }, "required": [ - "id", - "isDefaultEnvironment", - "name", - "ownerId", - "targetDatabase", - "targetName", - "targetRole", - "targetSchema", - "variables" + "pageInfo", + "records" ] }, - "DbtEnvironmentResponseVariable": { + "PageInfo": { "type": "object", "properties": { - "id": { - "type": "string", - "format": "uuid", - "description": "Variable ID" - }, - "isSecret": { + "hasNextPage": { "type": "boolean", - "description": "Whether the variable value is secret" - }, - "name": { - "type": "string", - "description": "Variable name" + "description": "Whether more results are available" }, - "value": { + "nextCursor": { "type": [ "string", "null" ], - "description": "Variable value (null for secret variables)" + "description": "Cursor for fetching the next page" + }, + "pageSize": { + "type": "number", + "description": "Number of results per page" + }, + "totalRecords": { + "type": "number", + "description": "Total number of records matching the query" } }, "required": [ - "id", - "isSecret", - "name", - "value" + "hasNextPage", + "nextCursor", + "pageSize", + "totalRecords" ] }, - "DbtEnvironmentCreateBody": { + "AiConversation": { "type": "object", "properties": { - "name": { + "createdAt": { "type": "string", - "minLength": 1, - "description": "Environment name", - "example": "PR_1111_Expose" - }, - "ownerId": { - "type": [ - "string", - "null" - ], - "default": null, - "description": "User ID of the environment owner. Used to mark development environments belonging to a specific user.", - "example": null + "format": "date-time", + "description": "When the conversation was started.", + "example": "2025-01-15T10:00:00.000Z" }, - "targetDatabase": { - "type": [ - "string", - "null" - ], - "default": null, - "description": "Target database override", - "example": "analytics_dev" + "id": { + "type": "string", + "format": "uuid", + "description": "Conversation ID. Pass as conversationId on subsequent /api/v1/ai/jobs submissions to continue this conversation.", + "example": "660e8400-e29b-41d4-a716-446655440001" }, - "targetName": { + "lastPrompt": { "type": [ "string", "null" ], - "default": null, - "description": "Target name override", - "example": null + "description": "The most recent user prompt in this conversation, useful for displaying a one-line summary in a list.", + "example": "What were our top products last week?" }, - "targetRole": { + "name": { "type": [ "string", "null" ], - "default": null, - "description": "Target role override", - "example": null + "description": "Conversation title. Set by the AI after the first turn; null on brand-new sessions.", + "example": "Top products last week" }, - "targetSchema": { + "updatedAt": { "type": "string", - "minLength": 1, - "description": "Target schema for this environment", - "example": "PR_1111_Expose" - }, - "variables": { - "type": "array", - "items": { - "$ref": "#/components/schemas/DbtEnvironmentVariable" - }, - "default": [], - "description": "Environment variables" + "format": "date-time", + "description": "When the conversation was last touched (most recent prompt or AI activity).", + "example": "2025-01-15T10:01:30.000Z" } }, "required": [ + "createdAt", + "id", + "lastPrompt", "name", - "targetSchema" + "updatedAt" ] }, - "DbtEnvironmentVariable": { + "AiConversationDetailResponse": { "type": "object", "properties": { - "isSecret": { - "type": "boolean", - "description": "Whether the variable value is secret" + "createdAt": { + "type": "string", + "format": "date-time" }, - "name": { + "id": { "type": "string", - "minLength": 1, - "description": "Variable name" + "format": "uuid" }, - "value": { + "messages": { + "type": "array", + "items": { + "$ref": "#/components/schemas/AiConversationMessage" + }, + "description": "Messages in chronological order. Alternating user / assistant turns." + }, + "name": { + "type": [ + "string", + "null" + ] + }, + "updatedAt": { "type": "string", - "description": "Variable value" + "format": "date-time" } }, "required": [ - "isSecret", + "createdAt", + "id", + "messages", "name", - "value" + "updatedAt" ] }, - "DbtEnvironmentUpdateBody": { + "AiConversationMessage": { "type": "object", "properties": { - "name": { + "createdAt": { "type": "string", - "minLength": 1, - "description": "Environment name", - "example": "PR_1111_Expose" + "format": "date-time", + "description": "When this turn was recorded.", + "example": "2025-01-15T10:00:00.000Z" }, - "ownerId": { + "jobId": { "type": [ "string", "null" ], - "default": null, - "description": "User ID of the environment owner. Used to mark development environments belonging to a specific user.", - "example": null + "format": "uuid", + "description": "The agentic job that produced this assistant turn. Only set for assistant messages — clients use it to fetch the rendered chart via GET /api/v1/ai/jobs/{jobId}/vis. Null when the turn predates jobs or when we could not associate one.", + "example": "550e8400-e29b-41d4-a716-446655440000" }, - "targetDatabase": { + "omniChatUrl": { "type": [ "string", "null" ], - "default": null, - "description": "Target database override", - "example": "analytics_dev" + "format": "uri", + "description": "Deep link to the assistant turn in the Omni chat UI. Null for user turns, and for assistant turns produced outside the Agentic API (where no AgenticJob row exists).", + "example": "https://my-org.omni.co/chat/660e8400-e29b-41d4-a716-446655440001" }, - "targetName": { - "type": [ - "string", - "null" + "role": { + "type": "string", + "enum": [ + "user", + "assistant" ], - "default": null, - "description": "Target name override", - "example": null + "description": "Speaker — `user` for prompts the user submitted, `assistant` for Blobby's responses.", + "example": "user" }, - "targetRole": { + "text": { + "type": "string", + "description": "Markdown content of the message. For assistant turns this is the same string returned by /api/v1/ai/jobs/{jobId}/result#message.", + "example": "What were our top products last week?" + } + }, + "required": [ + "createdAt", + "jobId", + "omniChatUrl", + "role", + "text" + ] + }, + "ApiKeyListResponse": { + "type": "object", + "properties": { + "pageInfo": { + "$ref": "#/components/schemas/PageInfo" + }, + "records": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ApiKey" + } + } + }, + "required": [ + "pageInfo", + "records" + ] + }, + "ApiKey": { + "type": "object", + "properties": { + "createdAt": { + "type": "string", + "format": "date-time", + "description": "ISO 8601 timestamp of when the token was created", + "example": "2026-01-15T10:00:00.000Z" + }, + "enabled": { + "type": "boolean", + "description": "Whether the token can currently authenticate. A disabled token cannot authenticate but remains visible until deleted.", + "example": true + }, + "id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the token", + "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" + }, + "membershipId": { "type": [ "string", "null" ], - "default": null, - "description": "Target role override", - "example": null + "format": "uuid", + "description": "Membership ID of the user the token is scoped to. Null for organization-level tokens.", + "example": "b2c3d4e5-f6a7-8901-bcde-f12345678901" }, - "targetSchema": { + "name": { "type": "string", - "minLength": 1, - "description": "Target schema for this environment", - "example": "PR_1111_Expose" + "description": "Human-readable name for the token", + "example": "CI deployment key" }, - "variables": { - "type": "array", - "items": { - "$ref": "#/components/schemas/DbtEnvironmentVariableUpdateOrNew" - }, - "default": [], - "description": "Environment variables. Variables with an id update existing ones; variables without an id create new ones." + "type": { + "type": "string", + "enum": [ + "organization", + "personal", + "mcp" + ], + "description": "Token type: `organization` (org-level), `personal` (user-created personal access token), or `mcp` (MCP OAuth grant).", + "example": "organization" } }, "required": [ + "createdAt", + "enabled", + "id", + "membershipId", "name", - "targetSchema" + "type" ] }, - "DbtEnvironmentVariableUpdateOrNew": { - "oneOf": [ - { - "$ref": "#/components/schemas/DbtEnvironmentVariableUpdate" - }, - { - "$ref": "#/components/schemas/DbtEnvironmentVariable" + "ApiKeyUpdateBody": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "description": "Set to `false` to disable the token, `true` to re-enable it.", + "example": false } - ] + }, + "required": [ + "enabled" + ], + "additionalProperties": false }, - "DbtEnvironmentDeleteResponse": { + "ApiKeyDeleteResponse": { "type": "object", "properties": { "message": { "type": "string", - "description": "Confirmation message", - "example": "dbt environment deleted successfully" + "description": "Human-readable description of the outcome", + "example": "API token revoked" }, "success": { "type": "boolean", - "description": "Whether the deletion was successful", - "example": true + "enum": [ + true + ], + "description": "Always `true` on a successful revocation" } }, "required": [ @@ -1372,7 +1704,7 @@ "success" ] }, - "ContentListResponse": { + "DbtEnvironmentListResponse": { "type": "object", "properties": { "pageInfo": { @@ -1381,1175 +1713,23440 @@ "records": { "type": "array", "items": { - "oneOf": [ - { - "allOf": [ + "$ref": "#/components/schemas/DbtEnvironmentItem" + } + } + }, + "required": [ + "pageInfo", + "records" + ] + }, + "DbtEnvironmentItem": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "Unique environment identifier" + }, + "isDefaultEnvironment": { + "type": "boolean", + "description": "Whether this is the default environment" + }, + "isDeferralEnabled": { + "type": "boolean", + "description": "Whether dbt deferral is enabled for this environment. Always false for the default (production) environment — the backend rejects enabling it there." + }, + "name": { + "type": "string", + "description": "Environment name" + }, + "ownerId": { + "type": [ + "string", + "null" + ], + "description": "User ID of the environment owner, or null if not a personal environment" + }, + "targetDatabase": { + "type": [ + "string", + "null" + ], + "description": "Target database override" + }, + "targetName": { + "type": [ + "string", + "null" + ], + "description": "Target name override" + }, + "targetRole": { + "type": [ + "string", + "null" + ], + "description": "Target role override" + }, + "targetSchema": { + "type": "string", + "description": "Target schema" + }, + "variables": { + "type": "array", + "items": { + "$ref": "#/components/schemas/DbtEnvironmentResponseVariable" + }, + "description": "Environment variables" + } + }, + "required": [ + "id", + "isDefaultEnvironment", + "isDeferralEnabled", + "name", + "ownerId", + "targetDatabase", + "targetName", + "targetRole", + "targetSchema", + "variables" + ] + }, + "DbtEnvironmentResponseVariable": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "Variable ID" + }, + "isSecret": { + "type": "boolean", + "description": "Whether the variable value is secret" + }, + "name": { + "type": "string", + "description": "Variable name" + }, + "value": { + "type": [ + "string", + "null" + ], + "description": "Variable value (null for secret variables)" + } + }, + "required": [ + "id", + "isSecret", + "name", + "value" + ] + }, + "DbtEnvironmentCreateBody": { + "type": "object", + "properties": { + "isDeferralEnabled": { + "type": "boolean", + "default": false, + "description": "Whether to enable dbt deferral for this environment. Ignored (forced to false) for the default (production) environment.", + "example": false + }, + "name": { + "type": "string", + "minLength": 1, + "description": "Environment name", + "example": "PR_1111_Expose" + }, + "ownerId": { + "type": [ + "string", + "null" + ], + "default": null, + "description": "User ID of the environment owner. Used to mark development environments belonging to a specific user.", + "example": null + }, + "targetDatabase": { + "type": [ + "string", + "null" + ], + "default": null, + "description": "Target database override", + "example": "analytics_dev" + }, + "targetName": { + "type": [ + "string", + "null" + ], + "default": null, + "description": "Target name override", + "example": null + }, + "targetRole": { + "type": [ + "string", + "null" + ], + "default": null, + "description": "Target role override", + "example": null + }, + "targetSchema": { + "type": "string", + "minLength": 1, + "description": "Target schema for this environment", + "example": "PR_1111_Expose" + }, + "variables": { + "type": "array", + "items": { + "$ref": "#/components/schemas/DbtEnvironmentVariable" + }, + "default": [], + "description": "Environment variables" + } + }, + "required": [ + "name", + "targetSchema" + ] + }, + "DbtEnvironmentVariable": { + "type": "object", + "properties": { + "isSecret": { + "type": "boolean", + "description": "Whether the variable value is secret" + }, + "name": { + "type": "string", + "minLength": 1, + "description": "Variable name" + }, + "value": { + "type": "string", + "description": "Variable value" + } + }, + "required": [ + "isSecret", + "name", + "value" + ] + }, + "DbtEnvironmentUpdateBody": { + "type": "object", + "properties": { + "isDeferralEnabled": { + "type": "boolean", + "default": false, + "description": "Whether to enable dbt deferral for this environment. Ignored (forced to false) for the default (production) environment.", + "example": false + }, + "name": { + "type": "string", + "minLength": 1, + "description": "Environment name", + "example": "PR_1111_Expose" + }, + "ownerId": { + "type": [ + "string", + "null" + ], + "default": null, + "description": "User ID of the environment owner. Used to mark development environments belonging to a specific user.", + "example": null + }, + "targetDatabase": { + "type": [ + "string", + "null" + ], + "default": null, + "description": "Target database override", + "example": "analytics_dev" + }, + "targetName": { + "type": [ + "string", + "null" + ], + "default": null, + "description": "Target name override", + "example": null + }, + "targetRole": { + "type": [ + "string", + "null" + ], + "default": null, + "description": "Target role override", + "example": null + }, + "targetSchema": { + "type": "string", + "minLength": 1, + "description": "Target schema for this environment", + "example": "PR_1111_Expose" + }, + "variables": { + "type": "array", + "items": { + "$ref": "#/components/schemas/DbtEnvironmentVariableUpdateOrNew" + }, + "default": [], + "description": "Environment variables. Variables with an id update existing ones; variables without an id create new ones." + } + }, + "required": [ + "name", + "targetSchema" + ] + }, + "DbtEnvironmentVariableUpdateOrNew": { + "oneOf": [ + { + "$ref": "#/components/schemas/DbtEnvironmentVariableUpdate" + }, + { + "$ref": "#/components/schemas/DbtEnvironmentVariable" + } + ] + }, + "DbtEnvironmentDeleteResponse": { + "type": "object", + "properties": { + "message": { + "type": "string", + "description": "Confirmation message", + "example": "dbt environment deleted successfully" + }, + "success": { + "type": "boolean", + "description": "Whether the deletion was successful", + "example": true + } + }, + "required": [ + "message", + "success" + ] + }, + "ContentListResponse": { + "type": "object", + "properties": { + "pageInfo": { + "$ref": "#/components/schemas/PageInfo" + }, + "records": { + "type": "array", + "items": { + "oneOf": [ + { + "allOf": [ + { + "$ref": "#/components/schemas/ApiDocument" + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "document" + ] + } + }, + "required": [ + "type" + ] + } + ] + }, + { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique identifier" + }, + "name": { + "type": "string", + "minLength": 1, + "maxLength": 255, + "description": "Content name" + }, + "owner": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "User ID of the owner" + }, + "name": { + "type": "string", + "description": "Name of the owner" + } + }, + "required": [ + "id", + "name" + ], + "description": "Content owner" + }, + "scope": { + "type": "string", + "enum": [ + "restricted", + "organization" + ], + "description": "Content access scope" + }, + "_count": { + "type": "object", + "properties": { + "documents": { + "type": "number", + "description": "Number of documents" + }, + "favorites": { + "type": "number", + "description": "Number of users who favorited" + } + }, + "required": [ + "documents", + "favorites" + ], + "description": "Folder counts" + }, + "labels": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Labels" + }, + "path": { + "type": "string", + "description": "Full path to the folder", + "example": "sales-reports/q1-2026" + }, + "url": { + "type": "string", + "description": "URL to view the folder in the Omni UI.", + "example": "https://org.omni.co/f/sales-reports" + }, + "type": { + "type": "string", + "enum": [ + "folder" + ] + } + }, + "required": [ + "id", + "name", + "owner", + "scope", + "path", + "url", + "type" + ] + } + ] + } + } + }, + "required": [ + "pageInfo", + "records" + ] + }, + "OwnerInternal": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Owner membership ID" + }, + "name": { + "type": "string", + "description": "Owner display name" + } + }, + "required": [ + "id", + "name" + ], + "description": "Content owner" + }, + "ContentShareScope": { + "type": "string", + "enum": [ + "restricted", + "organization" + ], + "description": "Content access scope" + }, + "InternalFolder": { + "type": [ + "object", + "null" + ], + "properties": { + "id": { + "type": "string", + "description": "Folder ID" + }, + "name": { + "type": "string", + "minLength": 1, + "maxLength": 255, + "description": "Folder name" + }, + "path": { + "type": "string", + "description": "Folder path" + }, + "scope": { + "allOf": [ + { + "$ref": "#/components/schemas/ContentShareScope" + }, + { + "description": "Folder access scope" + } + ] + } + }, + "required": [ + "id", + "name", + "path", + "scope" + ], + "description": "Parent folder" + }, + "ApiDocument": { + "type": "object", + "properties": { + "name": { + "type": "string", + "minLength": 1, + "maxLength": 255, + "description": "Content name" + }, + "owner": { + "$ref": "#/components/schemas/OwnerInternal" + }, + "scope": { + "$ref": "#/components/schemas/ContentShareScope" + }, + "_count": { + "type": "object", + "properties": { + "favorites": { + "type": "number", + "description": "Number of users who favorited" + }, + "views": { + "type": "number", + "description": "Number of views" + } + }, + "required": [ + "favorites", + "views" + ], + "description": "Document counts" + }, + "connectionId": { + "type": "string", + "description": "Connection ID" + }, + "deleted": { + "type": "boolean", + "description": "Whether document is deleted" + }, + "description": { + "type": [ + "string", + "null" + ], + "description": "Document description" + }, + "folder": { + "$ref": "#/components/schemas/InternalFolder" + }, + "hasApp": { + "type": "boolean", + "description": "Whether document has an app" + }, + "hasDashboard": { + "type": "boolean", + "description": "Whether document has a dashboard" + }, + "identifier": { + "type": "string", + "description": "Document identifier" + }, + "labels": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Applied labels" + }, + "lastViewedAt": { + "type": [ + "string", + "null" + ], + "format": "date-time", + "description": "Last time the dashboard was viewed" + }, + "updatedAt": { + "type": [ + "string", + "null" + ], + "format": "date-time", + "description": "Last updated timestamp" + }, + "url": { + "type": "string", + "description": "URL to view the document. Returns the dashboard URL if it has a dashboard, the app URL if it has an app, otherwise the workbook URL.", + "example": "https://org.omni.co/dashboards/abc123" + }, + "visits": { + "type": [ + "number", + "null" + ], + "description": "Number of dashboard visits" + } + }, + "required": [ + "name", + "owner", + "scope", + "connectionId", + "deleted", + "folder", + "hasApp", + "hasDashboard", + "identifier", + "updatedAt", + "url" + ] + }, + "DashboardsDownloadResponse": { + "type": "object", + "properties": { + "job_id": { + "type": "string", + "format": "uuid", + "description": "ID of the download job. Use this to poll for download status.", + "example": "123e4567-e89b-12d3-a456-426614174000" + }, + "message": { + "type": "string", + "description": "Status message", + "example": "Download initiated successfully" + } + }, + "required": [ + "job_id", + "message" + ] + }, + "DashboardsDownloadBody": { + "type": "object", + "properties": { + "enableFormatting": { + "type": "boolean", + "default": false, + "description": "Compatible with csv, xlsx & json formats. If true, formatting will be enabled in the output. Note: If true for json format, a queryIdentifierMapKey is required.", + "example": false + }, + "expandTablesToShowAllRows": { + "type": "boolean", + "description": "Compatible with pdf and png formats. If true, up to 1,000 rows in table visualizations will be included in the delivery. Note: This parameter cannot be used when paperFormat: fit_page.", + "example": false + }, + "filterConfig": { + "description": "An object specifying the filter conditions to apply to the task. The filter key specified must already exist in the dashboard.", + "example": { + "status": [ + "active", + "pending" + ] + } + }, + "format": { + "type": "string", + "enum": [ + "pdf", + "png", + "csv", + "xlsx", + "json" + ], + "description": "Output format for the download: pdf, png, csv, xlsx, or json", + "example": "pdf" + }, + "hideHiddenFields": { + "type": "boolean", + "default": false, + "description": "Compatible with csv & xlsx formats. If true, fields marked as hidden won't be displayed in the output.", + "example": false + }, + "hideTitle": { + "type": "boolean", + "default": false, + "description": "Compatible with pdf & png formats. If true, the content's title will be hidden in the output.", + "example": false + }, + "maxRowLimit": { + "type": "number", + "minimum": 1, + "description": "Compatible with csv, json, & xlsx formats. Used with overrideRowLimit. Specifies the maximum number of rows.", + "example": 1000 + }, + "overrideRowLimit": { + "type": "boolean", + "default": false, + "description": "Compatible with csv, json, & xlsx formats. If true, the default row limit will be overridden. Note: If true for json and xlsx formats, a queryIdentifierMapKey is required.", + "example": false + }, + "paperFormat": { + "type": "string", + "enum": [ + "a3", + "a4", + "fit_page", + "legal", + "letter", + "tabloid" + ], + "description": "Compatible with pdf formats. Defines the paper format (size) of the resulting PDF. Must be one of: a3, a4, letter, legal, fit_page, tabloid.", + "example": "letter" + }, + "paperOrientation": { + "type": "string", + "enum": [ + "portrait", + "landscape" + ], + "description": "Compatible with pdf formats. Defines the paper orientation of the resulting PDF. Must be one of: portrait, landscape.", + "example": "landscape" + }, + "queryIdentifierMapKey": { + "type": "string", + "description": "Required for single tile tasks. The ID of the query to include in a single tile task. Must reference a valid query in the dashboard.", + "example": "Jmn2r3KV" + }, + "showContentLink": { + "type": "boolean", + "default": true, + "description": "Compatible with all formats except link_only. If true, a link to the content will be shown in the output.", + "example": true + }, + "showFilters": { + "type": "boolean", + "default": true, + "description": "Compatible with all formats except link_only & csv. If true, filters will be shown in the output.", + "example": true + }, + "singleColumnLayout": { + "type": "boolean", + "description": "Compatible with pdf and png formats. If true, dashboard tiles will be arranged into a single vertical column.", + "example": false + }, + "useCache": { + "type": "boolean", + "default": false, + "description": "If true, allow scheduled queries to use cached results instead of always running fresh queries.", + "example": false + }, + "filename": { + "type": "string", + "minLength": 1, + "maxLength": 255, + "description": "Custom filename for the downloaded file (without extension)", + "example": "monthly-report" + } + }, + "required": [ + "format" + ], + "additionalProperties": false + }, + "DashboardFiltersResponse": { + "type": "object", + "properties": { + "controls": { + "description": "Control configuration object. Keys are control IDs, values contain controlType, filterId, label, etc." + }, + "filterOrder": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Ordered list of filter IDs defining display order", + "example": [ + "filter_abc123", + "filter_def456" + ] + }, + "filters": { + "description": "Filter configuration object. Keys are filter IDs, values contain fieldName, viewName, kind, defaultValue, etc." + }, + "identifier": { + "type": "string", + "description": "Dashboard identifier", + "example": "12db1a0a" + } + }, + "required": [ + "filterOrder", + "identifier" + ] + }, + "DashboardsUpdateFiltersBody": { + "type": "object", + "properties": { + "clearExistingDraft": { + "type": "boolean", + "default": false, + "description": "When true, discards any existing draft before applying updates. Required when updating a published document that already has a draft." + }, + "controls": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": {}, + "additionalProperties": {} + }, + "description": "Partial control updates. Keys are control IDs that must exist in the dashboard." + }, + "filterOrder": { + "type": "array", + "items": { + "type": "string" + }, + "description": "New order for filters. All filter IDs must exist in the dashboard." + }, + "filters": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": {}, + "additionalProperties": {} + }, + "description": "Partial filter updates. Keys are filter IDs that must exist in the dashboard." + } + } + }, + "DocumentsListResponse": { + "type": "object", + "properties": { + "pageInfo": { + "allOf": [ + { + "$ref": "#/components/schemas/PageInfo" + }, + { + "description": "Pagination information" + } + ] + }, + "records": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Document" + }, + "description": "List of documents" + } + }, + "required": [ + "pageInfo", + "records" + ] + }, + "Document": { + "type": "object", + "properties": { + "_count": { + "type": "object", + "properties": { + "favorites": { + "type": "number", + "description": "Number of users who favorited this document" + }, + "views": { + "type": "number", + "description": "Number of views" + } + }, + "required": [ + "favorites", + "views" + ], + "description": "Document counts (included when _count is in include param)" + }, + "connectionId": { + "type": "string", + "description": "Connection ID the document is associated with" + }, + "deleted": { + "type": "boolean", + "description": "Whether the document is deleted (archived)" + }, + "description": { + "type": [ + "string", + "null" + ], + "description": "Document description" + }, + "folder": { + "$ref": "#/components/schemas/DocumentFolder" + }, + "hasApp": { + "type": "boolean", + "description": "Whether the document has an associated app" + }, + "hasDashboard": { + "type": "boolean", + "description": "Whether the document has an associated dashboard" + }, + "identifier": { + "type": "string", + "description": "Document identifier", + "example": "abc123" + }, + "labels": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Labels applied to the document (included when labels is in include param)" + }, + "name": { + "type": "string", + "description": "Document name" + }, + "owner": { + "$ref": "#/components/schemas/DocumentOwner" + }, + "scope": { + "type": "string", + "enum": [ + "restricted", + "organization" + ], + "description": "Document access scope" + }, + "type": { + "type": "string", + "enum": [ + "document" + ], + "description": "Content type" + }, + "updatedAt": { + "type": [ + "string", + "null" + ], + "format": "date-time", + "description": "Last updated timestamp" + }, + "url": { + "type": "string", + "description": "URL to view the document. Returns the dashboard URL if it has a dashboard, the app URL if it has an app, otherwise the workbook URL.", + "example": "https://org.omni.co/dashboards/abc123" + } + }, + "required": [ + "connectionId", + "deleted", + "folder", + "hasDashboard", + "identifier", + "name", + "owner", + "scope", + "type", + "updatedAt", + "url" + ] + }, + "DocumentFolder": { + "type": [ + "object", + "null" + ], + "properties": { + "id": { + "type": "string", + "description": "Folder ID" + }, + "name": { + "type": "string", + "description": "Folder name" + }, + "path": { + "type": "string", + "description": "Folder path" + }, + "scope": { + "type": "string", + "enum": [ + "restricted", + "organization" + ], + "description": "Folder access scope" + } + }, + "required": [ + "id", + "name", + "path", + "scope" + ], + "description": "Folder containing the document" + }, + "DocumentOwner": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Owner membership ID" + }, + "name": { + "type": "string", + "description": "Owner display name" + } + }, + "required": [ + "id", + "name" + ], + "description": "Document owner" + }, + "DocumentsCreateResponse": { + "type": "object", + "properties": { + "dashboard": { + "type": "object", + "properties": { + "dashboardId": { + "type": "string", + "description": "Dashboard ID" + }, + "id": { + "type": "string", + "description": "Dashboard ID" + } + }, + "required": [ + "dashboardId", + "id" + ], + "additionalProperties": {}, + "description": "Created dashboard" + }, + "workbook": { + "type": "object", + "properties": { + "documentId": { + "type": "string", + "description": "Document ID (deprecated)" + }, + "id": { + "type": "string", + "description": "Workbook ID" + } + }, + "required": [ + "documentId", + "id" + ], + "additionalProperties": {}, + "description": "Created workbook" + } + }, + "required": [ + "dashboard", + "workbook" + ] + }, + "DocumentsCreateBody": { + "type": "object", + "properties": { + "branchId": { + "type": "string", + "format": "uuid", + "description": "Optional branch ID to associate the document with a model branch", + "example": "123e4567-e89b-12d3-a456-426614174001" + }, + "description": { + "type": [ + "string", + "null" + ], + "description": "Document description" + }, + "facetFilters": { + "type": "boolean", + "description": "Enable facet filters on the dashboard" + }, + "filterConfig": { + "description": "Dashboard filter configuration" + }, + "filterOrder": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Order of filters in the dashboard" + }, + "identifier": { + "$ref": "#/components/schemas/DocumentIdentifier" + }, + "metadata": { + "description": "Dashboard metadata" + }, + "metadataVersion": { + "type": "string", + "description": "Dashboard metadata version (required when metadata is provided)" + }, + "modelId": { + "type": "string", + "description": "Shared model ID to base the document on" + }, + "name": { + "type": "string", + "description": "Document name" + }, + "queryPresentations": { + "type": "array", + "items": { + "type": "object", + "properties": { + "aiConfig": { + "description": "AI configuration" + }, + "chartType": { + "type": [ + "string", + "null" + ], + "description": "Chart type" + }, + "description": { + "type": "string", + "maxLength": 500, + "description": "Query presentation description" + }, + "name": { + "type": "string", + "minLength": 1, + "maxLength": 144, + "description": "Query presentation name" + }, + "prefersChart": { + "type": "boolean", + "description": "Whether to prefer chart view" + }, + "query": { + "type": "object", + "properties": { + "fields": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Query fields" + }, + "table": { + "type": "string", + "description": "Query table/topic" + } + }, + "required": [ + "fields", + "table" + ], + "additionalProperties": {}, + "description": "Query definition" + }, + "resultConfig": { + "description": "Result configuration" + }, + "subTitle": { + "type": "string", + "maxLength": 250, + "description": "Subtitle" + }, + "topicName": { + "type": [ + "string", + "null" + ], + "maxLength": 256, + "description": "Topic name. Omit or pass null for raw-SQL tiles or any tile with no semantic topic." + }, + "visConfig": { + "$ref": "#/components/schemas/ApiVisConfig" + } + }, + "required": [ + "name", + "query" + ] + }, + "description": "Query presentations for the document" + } + }, + "required": [ + "modelId", + "name" + ] + }, + "DocumentIdentifier": { + "type": "string", + "minLength": 2, + "maxLength": 48, + "description": "Optional document identifier. If omitted, an identifier is auto-generated. Must be unique within the organization." + }, + "ApiVisConfig": { + "type": [ + "object", + "null" + ], + "properties": { + "config": { + "type": "object", + "additionalProperties": {}, + "description": "Visualization spec (chart configuration)" + }, + "fields": { + "type": [ + "array", + "null" + ], + "items": { + "type": "string", + "minLength": 1 + }, + "description": "Field names used in the visualization" + }, + "visType": { + "type": "string", + "enum": [ + "vegalite", + "omni-ai-summary-markdown", + "basic", + "omni-kpi", + "map", + "omni-markdown", + "funnel", + "sankey", + "single-record", + "svg-map", + "omni-spreadsheet", + "spreadsheet-tab", + "summary-value", + "omni-table", + "app" + ], + "description": "Visualization type (e.g. basic, omni-markdown, omni-table)" + } + }, + "additionalProperties": {}, + "description": "Visualization configuration" + }, + "DocumentsGetResponse": { + "type": "object", + "properties": { + "description": { + "type": [ + "string", + "null" + ], + "description": "Document description" + }, + "documentMetadata": { + "description": "Document metadata" + }, + "facetFilters": { + "type": "boolean", + "description": "Whether facet filters are enabled" + }, + "filterConfig": { + "description": "Dashboard filter configuration" + }, + "filterOrder": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Order of filters" + }, + "modelId": { + "type": "string", + "description": "Model ID" + }, + "name": { + "type": "string", + "description": "Document name" + }, + "queryPresentations": { + "type": "array", + "items": {}, + "description": "Query presentations" + }, + "refreshInterval": { + "type": [ + "number", + "null" + ], + "description": "Auto-refresh interval in seconds" + } + }, + "required": [ + "facetFilters", + "filterOrder", + "modelId", + "name", + "queryPresentations", + "refreshInterval" + ] + }, + "DocumentsPutResponse": { + "type": "object", + "properties": { + "description": { + "type": [ + "string", + "null" + ], + "description": "Document description" + }, + "identifier": { + "type": "string", + "description": "Document identifier" + }, + "name": { + "type": "string", + "description": "Updated document name" + } + }, + "required": [ + "identifier", + "name" + ] + }, + "DocumentsPutBody": { + "type": "object", + "properties": { + "clearExistingDraft": { + "type": "boolean", + "default": false, + "description": "Clear existing draft before updating (for published documents with drafts)" + }, + "description": { + "type": [ + "string", + "null" + ], + "description": "Document description" + }, + "documentMetadata": { + "description": "Document presentation metadata" + }, + "facetFilters": { + "type": "boolean", + "description": "Enable facet filters" + }, + "filterConfig": { + "description": "Filter configuration" + }, + "filterOrder": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Order of filters" + }, + "modelId": { + "type": "string", + "description": "Model ID" + }, + "name": { + "type": "string", + "minLength": 1, + "maxLength": 254, + "description": "Document name" + }, + "queryPresentations": { + "type": "array", + "items": { + "$ref": "#/components/schemas/DocumentsPutQueryPresentation" + }, + "minItems": 1, + "description": "Query presentations (full replacement)" + }, + "refreshInterval": { + "type": [ + "integer", + "null" + ], + "minimum": 60, + "description": "Auto-refresh interval in seconds" + } + }, + "required": [ + "facetFilters", + "filterOrder", + "modelId", + "name", + "queryPresentations", + "refreshInterval" + ] + }, + "DocumentsPutQueryPresentation": { + "type": "object", + "properties": { + "aiConfig": { + "type": "object", + "properties": { + "description": { + "type": "object", + "properties": { + "aiContext": { + "type": "string" + }, + "enabled": { + "type": "boolean" + } + } + }, + "subTitle": { + "type": "object", + "properties": { + "aiContext": { + "type": "string" + }, + "enabled": { + "type": "boolean" + } + } + } + }, + "description": "AI configuration" + }, + "chartType": { + "type": [ + "string", + "null" + ], + "enum": [ + "auto", + "area", + "areaStacked", + "areaStackedPercentage", + "bar", + "barLine", + "barGrouped", + "barStacked", + "barStackedPercentage", + "boxplot", + "code", + "column", + "columnGrouped", + "columnStacked", + "columnStackedPercentage", + "heatmap", + "kpi", + "line", + "lineColor", + "map", + "regionMap", + "markdown", + "omni-ai-summary-markdown", + "pie", + "funnel", + "sankey", + "point", + "pointColor", + "pointSize", + "pointSizeColor", + "singleRecord", + "omni-spreadsheet", + "summaryValue", + "svgMap", + "table", + null + ], + "description": "Chart type" + }, + "description": { + "type": "string", + "maxLength": 500, + "description": "Description" + }, + "name": { + "type": "string", + "minLength": 1, + "maxLength": 144, + "description": "Query presentation name" + }, + "prefersChart": { + "type": "boolean", + "description": "Whether to prefer chart view" + }, + "query": { + "description": "Query definition" + }, + "queryIdentifierMapKey": { + "type": "string", + "pattern": "^[1-9][0-9]*$", + "description": "Round-trip preservation hint. When the value matches an existing key on the document, the tile keeps its map key (and dashboard containers stay attached). Omit for new tiles. Must be a positive integer string (e.g. \"1\", \"2\", \"10\")." + }, + "resultConfig": { + "description": "Result config" + }, + "subTitle": { + "type": "string", + "maxLength": 250, + "description": "Subtitle" + }, + "topicName": { + "type": [ + "string", + "null" + ], + "maxLength": 256, + "description": "Topic name. Omit or pass null for raw-SQL tiles or any tile with no semantic topic." + }, + "visConfig": { + "$ref": "#/components/schemas/ApiVisConfig" + } + }, + "required": [ + "name" + ] + }, + "DocumentsUpdateResponse": { + "type": "object", + "properties": { + "description": { + "type": [ + "string", + "null" + ], + "description": "Document description" + }, + "identifier": { + "type": "string", + "description": "Document identifier" + }, + "name": { + "type": "string", + "description": "Updated document name" + } + }, + "required": [ + "identifier", + "name" + ] + }, + "DocumentsUpdateBody": { + "type": "object", + "properties": { + "clearExistingDraft": { + "type": "boolean", + "default": false, + "description": "Clear existing draft before updating (for published documents with drafts)" + }, + "description": { + "type": [ + "string", + "null" + ], + "description": "Document description" + }, + "identifier": { + "allOf": [ + { + "$ref": "#/components/schemas/DocumentIdentifier" + }, + { + "description": "New identifier for the document. Must be unique within the organization. The previous identifier is retained in the document identifier history and continues to redirect." + } + ] + }, + "name": { + "type": "string", + "minLength": 1, + "maxLength": 254, + "description": "New document name" + } + } + }, + "SuccessResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "description": "Whether the operation was successful", + "example": true + } + }, + "required": [ + "success" + ] + }, + "DocumentsGetQueriesResponse": { + "type": "object", + "properties": { + "queries": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Query presentation ID" + }, + "name": { + "type": "string", + "description": "Query presentation name" + }, + "query": { + "description": "Query JSON definition" + }, + "queryIdentifierMapKey": { + "type": "string", + "description": "Key in the query identifier map" + }, + "url": { + "type": "string", + "description": "URL to view this specific query/sheet in the workbook.", + "example": "https://org.omni.co/w/abc123?key=1" + } + }, + "required": [ + "id", + "name", + "queryIdentifierMapKey", + "url" + ] + }, + "description": "List of queries in the document" + } + }, + "required": [ + "queries" + ] + }, + "DocumentsMoveBody": { + "type": "object", + "properties": { + "folderPath": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Destination folder path (null for root)" + }, + "scope": { + "type": "string", + "enum": [ + "restricted", + "organization" + ], + "description": "Access scope for the document" + } + }, + "required": [ + "folderPath" + ] + }, + "DocumentsGetPermissionsResponse": { + "type": "object", + "properties": { + "permits": { + "description": "User permits for the document" + } + } + }, + "DocumentsUpdatePermissionSettingsBody": { + "type": "object", + "properties": { + "canDownload": { + "type": "boolean", + "description": "Allow downloading" + }, + "canDrill": { + "type": "boolean", + "description": "Allow drill-down" + }, + "canSchedule": { + "type": "boolean", + "description": "Allow scheduling" + }, + "canUpload": { + "type": "boolean", + "description": "Allow uploads" + }, + "canUseDashboardAi": { + "type": "boolean", + "description": "Allow using dashboard AI" + }, + "canUseTimezoneOverride": { + "type": "boolean", + "description": "Allow timezone override" + }, + "canViewWorkbook": { + "type": "boolean", + "description": "Allow viewing workbook" + }, + "organizationAccessBoost": { + "type": "boolean", + "description": "Boost organization access" + }, + "organizationRole": { + "type": "string", + "enum": [ + "viewer", + "editor", + "manager", + "no_access" + ], + "description": "Organization-wide role for the document" + }, + "requirePullRequestToPublish": { + "type": "boolean", + "description": "Require pull request to publish changes" + } + } + }, + "DocumentsAddPermitsBody": { + "type": "object", + "properties": { + "accessBoost": { + "type": "boolean", + "default": false, + "description": "Grant access boost" + }, + "role": { + "type": "string", + "enum": [ + "NO_ACCESS", + "VIEWER", + "EXPLORER", + "EDITOR", + "MANAGER" + ], + "description": "Role to grant" + }, + "userGroupIds": { + "type": "array", + "items": { + "type": "string" + }, + "default": [], + "description": "User group IDs to grant access to" + }, + "userIds": { + "type": "array", + "items": { + "type": "string", + "format": "uuid" + }, + "default": [], + "description": "User membership IDs to grant access to" + } + }, + "required": [ + "role" + ] + }, + "DocumentsUpdatePermitsBody": { + "type": "object", + "properties": { + "accessBoost": { + "type": "boolean", + "description": "Access boost setting" + }, + "role": { + "type": "string", + "enum": [ + "NO_ACCESS", + "VIEWER", + "EXPLORER", + "EDITOR", + "MANAGER" + ], + "description": "Role to set" + }, + "userGroupIds": { + "type": "array", + "items": { + "type": "string" + }, + "default": [], + "description": "User group IDs to update" + }, + "userIds": { + "type": "array", + "items": { + "type": "string", + "format": "uuid" + }, + "default": [], + "description": "User membership IDs to update" + } + } + }, + "DocumentsRevokePermitsBody": { + "type": "object", + "properties": { + "userGroupIds": { + "type": "array", + "items": { + "type": "string" + }, + "default": [], + "description": "User group IDs to revoke access from" + }, + "userIds": { + "type": "array", + "items": { + "type": "string", + "format": "uuid" + }, + "default": [], + "description": "User membership IDs to revoke access from" + } + } + }, + "DocumentsCreateDraftResponse": { + "type": "object", + "properties": { + "identifier": { + "type": "string", + "description": "Draft document identifier" + } + }, + "required": [ + "identifier" + ] + }, + "DocumentsCreateDraftBody": { + "type": "object", + "properties": { + "branchId": { + "type": "string", + "format": "uuid", + "description": "Branch ID for the draft" + } + } + }, + "DocumentsDiscardDraftResponse": { + "type": "object", + "properties": { + "message": { + "type": "string", + "description": "Success message" + } + }, + "required": [ + "message" + ] + }, + "DocumentsDiscardDraftBody": { + "type": "object", + "properties": { + "branchId": { + "type": "string", + "format": "uuid", + "description": "Branch ID for the draft" + } + } + }, + "DocumentsListDraftsResponse": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ApiDraft" + } + }, + "ApiDraft": { + "type": "object", + "properties": { + "branch": { + "$ref": "#/components/schemas/ApiDraftBranch" + }, + "createdAt": { + "type": "string", + "format": "date-time", + "description": "When the draft was created" + }, + "createdBy": { + "$ref": "#/components/schemas/ApiDraftActor" + }, + "draftOutOfDate": { + "type": "boolean", + "description": "True when the published document was published more recently than the draft was created (the draft is based on a stale baseline)" + }, + "identifier": { + "type": "string", + "description": "Draft workbook identifier — use this to address the draft" + }, + "lastEditedBy": { + "allOf": [ + { + "$ref": "#/components/schemas/ApiDraftActor" + }, + { + "description": "User who most recently edited the draft" + } + ] + }, + "publishedIdentifier": { + "type": "string", + "description": "Identifier of the published document the draft is for" + }, + "status": { + "$ref": "#/components/schemas/ApiDraftStatus" + }, + "updatedAt": { + "type": "string", + "format": "date-time", + "description": "Most recent edit time on the draft workbook" + }, + "workbookModelId": { + "type": "string", + "format": "uuid", + "description": "omni_model ID for the draft workbook" + } + }, + "required": [ + "branch", + "createdAt", + "createdBy", + "draftOutOfDate", + "identifier", + "lastEditedBy", + "publishedIdentifier", + "status", + "updatedAt", + "workbookModelId" + ] + }, + "ApiDraftBranch": { + "type": [ + "object", + "null" + ], + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "Branch (omni model) ID" + }, + "name": { + "type": "string", + "description": "Branch name" + } + }, + "required": [ + "id", + "name" + ], + "description": "Branch the draft is attached to, or null for a draft on main" + }, + "ApiDraftActor": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Display name" + } + }, + "required": [ + "name" + ], + "description": "User who created the draft" + }, + "ApiDraftStatus": { + "type": "string", + "enum": [ + "active", + "archived" + ], + "description": "Lifecycle status: \"active\" for current drafts, \"archived\" for soft-deleted drafts (retained ~7 days)" + }, + "DocumentsDuplicateResponse": { + "type": "object", + "properties": { + "dashboardId": { + "type": "string", + "description": "New dashboard ID" + }, + "identifier": { + "type": "string", + "description": "New document identifier" + }, + "name": { + "type": "string", + "description": "Document name" + }, + "workbookId": { + "type": "string", + "description": "New workbook ID" + } + }, + "required": [ + "dashboardId", + "identifier", + "name", + "workbookId" + ] + }, + "DocumentsDuplicateBody": { + "type": "object", + "properties": { + "folderPath": { + "type": [ + "string", + "null" + ], + "description": "Destination folder path (null for root)" + }, + "name": { + "type": "string", + "minLength": 1, + "maxLength": 254, + "description": "Name for the duplicated document" + }, + "scope": { + "type": "string", + "enum": [ + "restricted", + "organization" + ], + "description": "Access scope for the duplicated document" + } + }, + "required": [ + "name" + ] + }, + "DocumentsBulkUpdateLabelsResponse": { + "type": "object", + "properties": { + "labels": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Updated list of labels on the document" + } + }, + "required": [ + "labels" + ] + }, + "DocumentsBulkUpdateLabelsBody": { + "type": "object", + "properties": { + "add": { + "type": "array", + "items": { + "type": "string" + }, + "default": [], + "description": "Labels to add" + }, + "remove": { + "type": "array", + "items": { + "type": "string" + }, + "default": [], + "description": "Labels to remove" + } + } + }, + "DocumentsTransferOwnershipBody": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "format": "uuid", + "description": "Membership ID of the new owner" + } + }, + "required": [ + "userId" + ] + }, + "DocumentsAccessListResponse": { + "type": "object", + "properties": { + "pageInfo": { + "allOf": [ + { + "$ref": "#/components/schemas/PageInfo" + }, + { + "description": "Pagination information" + } + ] + }, + "principals": { + "type": "array", + "items": {}, + "description": "List of users and groups with access" + } + }, + "required": [ + "pageInfo", + "principals" + ] + }, + "DocumentsListFavoritesResponse": { + "type": "object", + "properties": { + "pageInfo": { + "allOf": [ + { + "$ref": "#/components/schemas/PageInfo" + }, + { + "description": "Pagination information" + } + ] + }, + "records": { + "type": "array", + "items": { + "$ref": "#/components/schemas/DocumentFavoriteUser" + }, + "description": "Users who favorited this document" + } + }, + "required": [ + "pageInfo", + "records" + ] + }, + "DocumentFavoriteUser": { + "type": "object", + "properties": { + "email": { + "type": [ + "string", + "null" + ], + "description": "Favoriting user's email. Null when the user has no resolvable email — e.g. an embed-SSO favoriter whose embed session did not provide one." + }, + "favoritedAt": { + "type": "string", + "description": "ISO 8601 timestamp when the user favorited the document" + }, + "name": { + "type": "string", + "description": "Favoriting user's display name" + }, + "userId": { + "type": "string", + "description": "Membership ID of the user who favorited the document (use with other v1 endpoints' userId parameter)" + } + }, + "required": [ + "email", + "favoritedAt", + "name", + "userId" + ] + }, + "DocumentsV2CreateResponse": { + "type": "object", + "properties": { + "description": { + "type": [ + "string", + "null" + ], + "description": "Document description." + }, + "identifier": { + "type": "string", + "description": "Identifier of the newly created document." + }, + "name": { + "type": "string", + "description": "Document name." + } + }, + "required": [ + "description", + "identifier", + "name" + ] + }, + "DocumentsV2CreateBody": { + "type": "object", + "properties": { + "containers": { + "$ref": "#/components/schemas/Containers" + }, + "controls": { + "$ref": "#/components/schemas/ControlsPatchExternal" + }, + "description": { + "type": [ + "string", + "null" + ], + "description": "Document description." + }, + "folderId": { + "type": [ + "string", + "null" + ], + "format": "uuid", + "description": "Folder to create the document in. When omitted, defaults to the caller’s personal \"My documents\" (requires permission to save personal content — otherwise the request is rejected)." + }, + "identifier": { + "allOf": [ + { + "$ref": "#/components/schemas/DocumentIdentifier" + }, + { + "description": "Identifier for the new document. Must be unique within the organization. Auto-generated when omitted." + } + ] + }, + "modelId": { + "type": "string", + "format": "uuid", + "description": "Base workbook model the document is built on — a SHARED model, or a SHARED_EXTENSION with `allowAsWorkbookBase = true`." + }, + "name": { + "type": "string", + "minLength": 1, + "maxLength": 254, + "description": "Document name." + }, + "queryPresentations": { + "$ref": "#/components/schemas/QueryPresentationsPatchExternal" + }, + "settings": { + "$ref": "#/components/schemas/SettingsPatchExternal" + }, + "summary": { + "type": "string", + "minLength": 1, + "maxLength": 255, + "description": "Caller-supplied note describing the create, written to the history audit trail. Defaults to \"Created document\" when omitted." + } + }, + "required": [ + "modelId", + "name" + ], + "additionalProperties": false + }, + "Containers": { + "type": "array", + "items": { + "anyOf": [ + { + "$ref": "#/components/schemas/GridContainer" + }, + { + "$ref": "#/components/schemas/PageContainer" + }, + { + "$ref": "#/components/schemas/StackContainer" + } + ] + }, + "description": "Container layout array (grid / stack / page / reference containers, recursively nested). The server validates the full structure on apply." + }, + "GridContainer": { + "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" + } + ] + }, + "before": { + "anyOf": [ + { + "$ref": "#/components/schemas/StackContainer" + }, + { + "$ref": "#/components/schemas/ReferenceContainer" + } + ] + }, + "children": { + "type": "array", + "items": { + "anyOf": [ + { + "allOf": [ + { + "$ref": "#/components/schemas/ReferenceContainer" + }, + { + "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" + ] + } + ] + }, + { + "allOf": [ + { + "$ref": "#/components/schemas/StackContainer" + }, + { + "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" + ] + } + ] + }, + { + "allOf": [ + { + "$ref": "#/components/schemas/GridContainer" + }, + { + "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" + ] + } + ] + }, + { + "allOf": [ + { + "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" + }, + "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" + ] + } + }, + "required": [ + "instanceKey", + "id", + "type" + ] + }, + { + "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)" + }, + "appearance": { + "oneOf": [ + { + "type": "object", + "properties": { + "as": { + "type": "string", + "enum": [ + "inline" + ] + } + }, + "required": [ + "as" + ] + }, + { + "type": "object", + "properties": { + "as": { + "type": "string", + "enum": [ + "tooltip" + ] + } + }, + "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)" + }, + "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" + } + } + }, + "textAlign": { + "type": "string", + "enum": [ + "start", + "center", + "end" + ], + "description": "Text alignment: \"start\", \"center\", or \"end\"" + }, + "type": { + "type": "string", + "enum": [ + "inline-text" + ] + } + }, + "required": [ + "instanceKey", + "content", + "type" + ] + }, + { + "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)" + }, + "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" + } + } + } + }, + "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": [ + "inline-page-switcher" + ] + } + }, + "required": [ + "instanceKey", + "type" + ] + }, + { + "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)" + }, + "id": { + "type": "string", + "format": "uuid", + "description": "UUID of the rich text content block" + }, + "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": [ + "text" + ] + } + }, + "required": [ + "instanceKey", + "id", + "type" + ] + }, + { + "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)" + }, + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "control" + ] + }, + "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" + } + } + } + }, + "required": [ + "instanceKey", + "id", + "type" + ] + }, + { + "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)" + }, + "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" + } + } + } + }, + "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" + } + } + } + }, + "required": [ + "instanceKey", + "id", + "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": "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)." + } + }, + "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 + ] + }, + { + "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 + ] + } + ] + } + ] + } + ] + }, + "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" + }, + "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" + ] + } + }, + "required": [ + "instanceKey", + "id", + "type" + ] + }, + { + "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)" + }, + "appearance": { + "oneOf": [ + { + "type": "object", + "properties": { + "as": { + "type": "string", + "enum": [ + "inline" + ] + } + }, + "required": [ + "as" + ] + }, + { + "type": "object", + "properties": { + "as": { + "type": "string", + "enum": [ + "tooltip" + ] + } + }, + "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)" + }, + "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" + } + } + }, + "textAlign": { + "type": "string", + "enum": [ + "start", + "center", + "end" + ], + "description": "Text alignment: \"start\", \"center\", or \"end\"" + }, + "type": { + "type": "string", + "enum": [ + "inline-text" + ] + } + }, + "required": [ + "instanceKey", + "content", + "type" + ] + }, + { + "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)" + }, + "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" + } + } + } + }, + "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": [ + "inline-page-switcher" + ] + } + }, + "required": [ + "instanceKey", + "type" + ] + }, + { + "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)" + }, + "id": { + "type": "string", + "format": "uuid", + "description": "UUID of the rich text content block" + }, + "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": [ + "text" + ] + } + }, + "required": [ + "instanceKey", + "id", + "type" + ] + }, + { + "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)" + }, + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "control" + ] + }, + "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" + } + } + } + }, + "required": [ + "instanceKey", + "id", + "type" + ] + }, + { + "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)" + }, + "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" + } + } + } + }, + "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" + } + } + } + }, + "required": [ + "instanceKey", + "id", + "type" + ] + }, + { + "type": "object", + "properties": { + "instanceKey": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "required": [ + "instanceKey", + "type" + ], + "additionalProperties": {} + }, + { + "$ref": "#/components/schemas/ReferenceContainer" + }, + { + "$ref": "#/components/schemas/GridContainer" + }, + { + "$ref": "#/components/schemas/StackContainer" + } + ] + } + }, + "containerType": { + "type": "string", + "enum": [ + "stack" + ], + "description": "Stack containers lay out children sequentially in a direction (column or row)" + }, + "direction": { + "type": "string", + "enum": [ + "column", + "row" + ], + "description": "Layout direction: \"row\" lays out horizontally, \"column\" stacks vertically (default if not specified)" + }, + "gap": { + "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": "number", + "enum": [ + 9 + ] + }, + { + "type": "number", + "enum": [ + 10 + ] + }, + { + "type": "number", + "enum": [ + 11 + ] + }, + { + "type": "number", + "enum": [ + 12 + ] + }, + { + "type": "number", + "enum": [ + 13 + ] + }, + { + "type": "number", + "enum": [ + 14 + ] + }, + { + "type": "number", + "enum": [ + 15 + ] + }, + { + "type": "number", + "enum": [ + 16 + ] + } + ], + "description": "Space between children (CSS size value)" + }, + "justify": { + "type": "string", + "enum": [ + "flex-start", + "flex-end", + "center", + "space-between" + ], + "description": "Main-axis alignment of children (e.g., start, center, end)" + }, + "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)." + } + }, + "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 + ] + }, + { + "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 + ] + } + ] + } + ] + } + ] + }, + "style": { + "type": "string", + "pattern": "^[a-z0-9-]+$" + }, + "wrap": { + "type": "string", + "enum": [ + "nowrap", + "wrap" + ], + "description": "Whether flex items should wrap to new lines (defaults to nowrap if not specified)" + } + }, + "required": [ + "instanceKey", + "children", + "containerType" + ], + "description": "Stack container — an ordered list of nested children (content, grid, stack, or reference)." + }, + "ReferenceContainer": { + "type": "object", + "properties": { + "containerType": { + "type": "string", + "enum": [ + "reference" + ] + }, + "instanceKey": { + "type": "string" + }, + "referenceKey": { + "type": "string" + } + }, + "required": [ + "containerType", + "instanceKey", + "referenceKey" + ], + "description": "Reference container — points at another container in the collection by its instanceKey." + }, + "PageContainer": { + "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" + }, + "breakpoint": { + "type": "string", + "enum": [ + "desktop", + "mobile" + ] + }, + "container": { + "anyOf": [ + { + "$ref": "#/components/schemas/GridContainer" + }, + { + "$ref": "#/components/schemas/StackContainer" + }, + { + "$ref": "#/components/schemas/ReferenceContainer" + } + ] + }, + "containerType": { + "type": "string", + "enum": [ + "page" + ] + }, + "media": { + "type": "string", + "enum": [ + "screen", + "print" + ] + } + }, + "required": [ + "instanceKey", + "container", + "containerType" + ], + "description": "Page container — a top-level page wrapping a single grid, stack, or reference container, optionally per breakpoint/media." + }, + "ControlsPatchExternal": { + "type": "object", + "properties": { + "data": { + "type": "object", + "additionalProperties": { + "$ref": "#/components/schemas/ControlPatchExternal" + }, + "description": "Controls keyed by control ID. Shallow-merged by key — omitted keys are untouched; set to `null` to delete." + }, + "order": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Display order for controls. When present, replaces the existing order." + } + } + }, + "ControlPatchExternal": { + "type": [ + "object", + "null" + ], + "properties": { + "config": { + "oneOf": [ + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "case_insensitive": { + "type": "boolean" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "kind": { + "type": "string", + "enum": [ + "CONTAINS", + "ENDS_WITH", + "STARTS_WITH", + "EQUALS", + "IS_EMPTY", + "SQL_LIKE" + ] + }, + "type": { + "type": "string", + "enum": [ + "string" + ] + }, + "values": { + "type": "array", + "items": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "kind", + "type", + "values" + ], + "additionalProperties": {} + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "is_inclusive": { + "type": "boolean" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "kind": { + "type": "string", + "enum": [ + "LESS_THAN", + "GREATER_THAN", + "EQUALS", + "BETWEEN" + ] + }, + "type": { + "type": "string", + "enum": [ + "number" + ] + }, + "values": { + "type": "array", + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + } + ] + } + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "kind", + "type", + "values" + ], + "additionalProperties": {} + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "isFiscal": { + "type": "boolean" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "kind": { + "type": "string", + "enum": [ + "IS_ON_DAY_OF_WEEK", + "IS_ON_DAY_OF_QUARTER", + "IS_IN_MONTH_OF_YEAR", + "IS_ON_DAY_OF_YEAR", + "IS_AT_HOUR_OF_DAY", + "IS_IN_QUARTER_OF_YEAR", + "IS_IN_WEEK_OF_YEAR", + "IS_ON_DAY_OF_MONTH", + "BETWEEN", + "ON_OR_AFTER", + "BEFORE", + "TIME_FOR_INTERVAL_DURATION", + "TIME_FOR_UNIT_DURATION", + "QUERY_OFFSET" + ] + }, + "left_side": { + "type": [ + "string", + "null" + ] + }, + "offset_interval_string": { + "type": [ + "string", + "null" + ] + }, + "right_side": { + "type": [ + "string", + "null" + ] + }, + "type": { + "type": "string", + "enum": [ + "date" + ] + }, + "ui_type": { + "type": [ + "string", + "null" + ], + "enum": [ + "ANY_TIME", + "BEFORE", + "BETWEEN", + "MONTH_OF_YEAR", + "PAST", + "YEAR", + "DAY", + "IS_ON_DAY_OF_WEEK", + "ON_OR_AFTER", + "IS_IN_THE_MONTH", + "IS_IN_THE_QUARTER", + "IS_IN_THE_FISCAL_QUARTER", + "IS_IN_THE_FISCAL_YEAR", + "TIME_FOR_INTERVAL_DURATION", + "TIME_FOR_UNIT_DURATION", + "CUSTOM", + null + ] + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "kind", + "type" + ], + "additionalProperties": {} + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "type": { + "type": "string", + "enum": [ + "null" + ] + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "type" + ], + "additionalProperties": {} + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "treat_nulls_as_false": { + "type": "boolean" + }, + "type": { + "type": "string", + "enum": [ + "boolean" + ] + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "type" + ], + "additionalProperties": {} + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "disregard_limit": { + "type": "boolean" + }, + "field_name": { + "type": "string" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "query_id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "query" + ] + }, + "view_query": { + "type": "object", + "properties": { + "fields": { + "type": "array", + "items": { + "type": "string" + } + }, + "filters": { + "type": "object", + "additionalProperties": {}, + "default": {} + }, + "limit": { + "type": "number" + }, + "sorts": { + "type": "array", + "items": {}, + "default": [] + }, + "table": { + "type": "string" + } + }, + "required": [ + "fields" + ], + "additionalProperties": {} + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "type" + ], + "additionalProperties": {} + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "type": { + "type": "string", + "enum": [ + "user_attribute" + ] + }, + "user_attribute_name": { + "type": "string" + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "type", + "user_attribute_name" + ], + "additionalProperties": {} + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "conjunction": { + "type": "string", + "enum": [ + "OR", + "AND" + ] + }, + "filters": { + "type": "array", + "items": { + "$ref": "#/components/schemas/CompositeFilter" + } + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "type": { + "type": "string", + "enum": [ + "composite" + ] + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "conjunction", + "filters", + "type" + ], + "additionalProperties": {} + }, + { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "label": { + "type": "string" + }, + "display": { + "type": "string", + "enum": [ + "SELECT", + "BUTTON_TOGGLE" + ] + }, + "field": { + "type": "string" + }, + "kind": { + "type": "string", + "enum": [ + "FIELD", + "TIMEFRAME" + ] + }, + "options": { + "type": "array", + "items": { + "type": "object", + "properties": { + "isDimension": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "topicLabel": { + "type": "string" + }, + "value": { + "type": "string" + }, + "viewLabel": { + "type": "string" + } + }, + "required": [ + "label", + "value" + ] + } + }, + "type": { + "type": "string", + "enum": [ + "FIELD_SELECTION" + ] + } + }, + "required": [ + "id", + "field", + "kind", + "options", + "type" + ] + }, + { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "label": { + "type": "string" + }, + "display": { + "type": "string", + "enum": [ + "SELECT", + "BUTTON_TOGGLE" + ] + }, + "options": { + "type": "array", + "items": { + "type": "object", + "properties": { + "label": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "required": [ + "label", + "value" + ] + } + }, + "selectionMap": { + "type": "object", + "additionalProperties": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "type": { + "type": "string", + "enum": [ + "MULTI_FIELD_SELECTION" + ] + }, + "value": { + "type": "string" + } + }, + "required": [ + "id", + "options", + "selectionMap", + "type" + ] + }, + { + "type": "object", + "properties": { + "computations": { + "type": "array", + "items": { + "type": "object", + "properties": { + "filterId": { + "type": "string" + }, + "isDynamicPreviousPeriod": { + "type": "boolean" + }, + "periodsAgo": { + "type": [ + "number", + "null" + ] + }, + "timeUnitName": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "periodsAgo", + "timeUnitName" + ] + } + }, + "filterFieldName": { + "type": "string" + }, + "filterId": { + "type": "string" + }, + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "PERIOD_OVER_PERIOD" + ] + } + }, + "required": [ + "computations", + "filterFieldName", + "id", + "type" + ] + }, + { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "label": { + "type": "string" + }, + "options": { + "type": "array", + "items": { + "type": "object", + "properties": { + "isDimension": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "topicLabel": { + "type": "string" + }, + "value": { + "type": "string" + }, + "viewLabel": { + "type": "string" + } + }, + "required": [ + "label", + "value" + ] + } + }, + "type": { + "type": "string", + "enum": [ + "FIELD_PICKER" + ] + }, + "values": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "id", + "options", + "type" + ] + }, + { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "label": { + "type": "string" + }, + "conjunction": { + "type": "string", + "enum": [ + "OR" + ] + }, + "filters": { + "type": "array", + "items": { + "type": "object", + "properties": { + "fieldName": { + "type": "string" + }, + "filter": { + "$ref": "#/components/schemas/JsonValue" + }, + "id": { + "type": "string" + } + }, + "required": [ + "fieldName", + "filter", + "id" + ] + } + }, + "type": { + "type": "string", + "enum": [ + "MULTI_FIELD_FILTER" + ] + } + }, + "required": [ + "id", + "conjunction", + "filters", + "type" + ] + }, + { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "label": { + "type": "string" + }, + "fieldSelection": { + "oneOf": [ + { + "type": "object", + "properties": { + "mode": { + "type": "string", + "enum": [ + "full-model" + ] + } + }, + "required": [ + "mode" + ] + }, + { + "type": "object", + "properties": { + "mode": { + "type": "string", + "enum": [ + "auto" + ] + }, + "topics": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "mode", + "topics" + ] + }, + { + "type": "object", + "properties": { + "fields": { + "type": "array", + "items": { + "type": "object", + "properties": { + "fieldName": { + "type": "string" + }, + "topicName": { + "type": "string" + } + }, + "required": [ + "fieldName" + ] + } + }, + "mode": { + "type": "string", + "enum": [ + "specific" + ] + } + }, + "required": [ + "fields", + "mode" + ] + } + ] + }, + "includeViewNameInLabels": { + "type": "boolean" + }, + "type": { + "type": "string", + "enum": [ + "DYNAMIC_FILTER" + ] + } + }, + "required": [ + "id", + "fieldSelection", + "type" + ] + }, + { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "label": { + "type": "string" + }, + "defaultValue": { + "type": "integer", + "minimum": 1 + }, + "field": { + "type": "string" + }, + "max": { + "type": "integer", + "minimum": 1 + }, + "min": { + "type": "integer", + "minimum": 1 + }, + "type": { + "type": "string", + "enum": [ + "TOP_N" + ] + }, + "value": { + "type": "integer", + "minimum": 1 + } + }, + "required": [ + "id", + "defaultValue", + "field", + "type", + "value" + ] + } + ], + "description": "Filter or interactive control config. Discriminated by `type`: filter types (string, date, number, etc.) or control types (FIELD_SELECTION, PERIOD_OVER_PERIOD, etc.). Visibility is determined by placement in the filter-bar container." + }, + "map": { + "type": "object", + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "boolean", + "enum": [ + false + ] + } + ] + }, + "description": "Per-tile field overrides keyed by tab ID. Values are a field name (override) or false (exclude tile from control)." + } + }, + "required": [ + "config" + ] + }, + "JsonValue": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "type": "object", + "additionalProperties": { + "oneOf": [ + { + "$ref": "#/components/schemas/JsonValue" + }, + { + "type": "null" + } + ] + } + }, + { + "type": "array", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/JsonValue" + }, + { + "type": "null" + } + ] + } + } + ], + "description": "Arbitrary JSON value (string, number, boolean, null, object, or array)." + }, + "QueryPresentationsPatchExternal": { + "type": "object", + "properties": { + "data": { + "type": "object", + "additionalProperties": { + "$ref": "#/components/schemas/QueryPresentationPatchExternal" + }, + "description": "Query presentations keyed by tab ID. Shallow-merged by key — omitted keys are untouched; set to `null` to delete. Capped at 48 entries per patch. When the request carries no `containers` and the document has a dashboard layout, dashboard-eligible tiles added at new keys are auto-placed on the dashboard's first page (non-renderable types such as CSV / dataset / query-view / dbt tabs are stored but not placed), and containers created by auto-placement are removed when their tile is deleted — containers placed via an explicit `containers` write are left in the layout. When `containers` is present it fully defines the layout; on a workbook-only document (no layout yet) tiles are stored without placement." + }, + "order": { + "type": "array", + "items": { + "type": "string", + "pattern": "^[1-9][0-9]*$" + }, + "description": "Tab display order. When present, replaces the existing order." + } + } + }, + "QueryPresentationPatchExternal": { + "type": [ + "object", + "null" + ], + "properties": { + "aiConfig": { + "type": [ + "object", + "null" + ], + "properties": { + "description": { + "type": "object", + "properties": { + "aiContext": { + "type": "string" + }, + "enabled": { + "type": "boolean" + } + } + }, + "subTitle": { + "type": "object", + "properties": { + "aiContext": { + "type": "string" + }, + "enabled": { + "type": "boolean" + } + } + } + }, + "description": "AI-generated metadata config (subtitle/description auto-generation settings)." + }, + "automaticVis": { + "type": [ + "boolean", + "null" + ], + "description": "When true, the system automatically selects the best visualization type." + }, + "description": { + "type": [ + "string", + "null" + ], + "maxLength": 500, + "description": "User-provided tab description." + }, + "editingModelObjectName": { + "type": [ + "string", + "null" + ], + "description": "Model object (view/topic) currently being edited via the dataset/query-view editor. Applies only to dataset / query-view tabs — omitted from reads and rejected on patches for other tab types." + }, + "editingModelObjectNameChange": { + "type": [ + "string", + "null" + ], + "description": "Pending rename of the model object being edited. Applies only to dataset / query-view tabs — omitted from reads and rejected on patches for other tab types." + }, + "filterOrder": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Ordered list of filter field names controlling display order on this tab." + }, + "isSql": { + "type": [ + "boolean", + "null" + ], + "description": "Whether this tab is in raw SQL mode." + }, + "name": { + "type": "string", + "minLength": 1, + "maxLength": 144, + "description": "User-provided tab name." + }, + "prefersChart": { + "type": "boolean", + "description": "When true, the chart view is shown by default instead of the data table." + }, + "query": { + "type": [ + "object", + "null" + ], + "properties": { + "aiGenerated": { + "type": "boolean", + "description": "True when AI generated this query’s SQL; the AI SQL is shown in the advanced SQL box." + }, + "branch_id": { + "type": "string", + "description": "Branch model ID when querying against a model branch." + }, + "calculations": { + "type": "array", + "items": { + "type": "object", + "properties": { + "allow_refs_to_unselected_fields": { + "type": "boolean", + "description": "Set by the Kotlin parser when this calc references fields not selected at the top level (AI SQL-gen produces these; UI-authored calcs do not)." + }, + "calc_name": { + "type": "string", + "description": "Internal identifier for the calculation, used as the column alias." + }, + "description": { + "type": "string", + "description": "Description of the calculation." + }, + "format": { + "type": "string", + "description": "Number/date format string (e.g. \"#,##0.00\")." + }, + "label": { + "type": "string", + "description": "Display label shown in the UI." + }, + "original_formula": { + "type": "string", + "description": "The original Excel-style formula before parsing (e.g. \"=SUM(A1:A10)\")." + }, + "outside_pivot": { + "type": "boolean", + "description": "When true, the calculation is evaluated outside the pivot grouping." + }, + "pushdown": { + "type": [ + "boolean", + "null" + ], + "description": "Per-calc override for whether to evaluate before the row limit. `null` defers to the model-level default." + }, + "sql": { + "type": "string", + "description": "Compiled SQL string produced from the formula." + }, + "sql_expression": { + "description": "Parsed SQL expression tree (serialized)." + }, + "swallow_errors": { + "type": "boolean", + "description": "When true, calculation errors are silently swallowed instead of surfaced." + } + }, + "required": [ + "calc_name" + ], + "additionalProperties": {} + }, + "description": "Table calculations attached to this query." + }, + "column_limit": { + "type": "number", + "description": "Max number of pivot columns to return." + }, + "column_totals": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "aggregation" + ] + } + }, + "required": [ + "type" + ] + }, + "description": "Column-level aggregation totals, keyed by field name." + }, + "controls": { + "type": "array", + "items": { + "oneOf": [ + { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "hidden": { + "type": "boolean" + }, + "id": { + "type": "string" + }, + "label": { + "type": "string" + }, + "display": { + "type": "string", + "enum": [ + "SELECT", + "BUTTON_TOGGLE" + ] + }, + "field": { + "type": "string" + }, + "kind": { + "type": "string", + "enum": [ + "FIELD", + "TIMEFRAME" + ] + }, + "options": { + "type": "array", + "items": { + "type": "object", + "properties": { + "isDimension": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "topicLabel": { + "type": "string" + }, + "value": { + "type": "string" + }, + "viewLabel": { + "type": "string" + } + }, + "required": [ + "label", + "value" + ] + } + }, + "type": { + "type": "string", + "enum": [ + "FIELD_SELECTION" + ] + } + }, + "required": [ + "id", + "field", + "kind", + "options", + "type" + ] + }, + { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "hidden": { + "type": "boolean" + }, + "id": { + "type": "string" + }, + "label": { + "type": "string" + }, + "display": { + "type": "string", + "enum": [ + "SELECT", + "BUTTON_TOGGLE" + ] + }, + "options": { + "type": "array", + "items": { + "type": "object", + "properties": { + "label": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "required": [ + "label", + "value" + ] + } + }, + "selectionMap": { + "type": "object", + "additionalProperties": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "type": { + "type": "string", + "enum": [ + "MULTI_FIELD_SELECTION" + ] + }, + "value": { + "type": "string" + } + }, + "required": [ + "id", + "options", + "selectionMap", + "type" + ] + }, + { + "type": "object", + "properties": { + "computations": { + "type": "array", + "items": { + "type": "object", + "properties": { + "filterId": { + "type": "string" + }, + "isDynamicPreviousPeriod": { + "type": "boolean" + }, + "periodsAgo": { + "type": [ + "number", + "null" + ] + }, + "timeUnitName": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "periodsAgo", + "timeUnitName" + ] + } + }, + "filterFieldName": { + "type": "string" + }, + "filterId": { + "type": "string" + }, + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "PERIOD_OVER_PERIOD" + ] + } + }, + "required": [ + "computations", + "filterFieldName", + "id", + "type" + ] + }, + { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "hidden": { + "type": "boolean" + }, + "id": { + "type": "string" + }, + "label": { + "type": "string" + }, + "options": { + "type": "array", + "items": { + "type": "object", + "properties": { + "isDimension": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "topicLabel": { + "type": "string" + }, + "value": { + "type": "string" + }, + "viewLabel": { + "type": "string" + } + }, + "required": [ + "label", + "value" + ] + } + }, + "type": { + "type": "string", + "enum": [ + "FIELD_PICKER" + ] + }, + "values": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "id", + "options", + "type" + ] + }, + { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "hidden": { + "type": "boolean" + }, + "id": { + "type": "string" + }, + "label": { + "type": "string" + }, + "conjunction": { + "type": "string", + "enum": [ + "OR" + ] + }, + "filters": { + "type": "array", + "items": { + "type": "object", + "properties": { + "fieldName": { + "type": "string" + }, + "filter": { + "$ref": "#/components/schemas/JsonValue" + }, + "id": { + "type": "string" + } + }, + "required": [ + "fieldName", + "filter", + "id" + ] + } + }, + "type": { + "type": "string", + "enum": [ + "MULTI_FIELD_FILTER" + ] + } + }, + "required": [ + "id", + "conjunction", + "filters", + "type" + ] + }, + { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "hidden": { + "type": "boolean" + }, + "id": { + "type": "string" + }, + "label": { + "type": "string" + }, + "fieldSelection": { + "oneOf": [ + { + "type": "object", + "properties": { + "mode": { + "type": "string", + "enum": [ + "full-model" + ] + } + }, + "required": [ + "mode" + ] + }, + { + "type": "object", + "properties": { + "mode": { + "type": "string", + "enum": [ + "auto" + ] + }, + "topics": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "mode", + "topics" + ] + }, + { + "type": "object", + "properties": { + "fields": { + "type": "array", + "items": { + "type": "object", + "properties": { + "fieldName": { + "type": "string" + }, + "topicName": { + "type": "string" + } + }, + "required": [ + "fieldName" + ] + } + }, + "mode": { + "type": "string", + "enum": [ + "specific" + ] + } + }, + "required": [ + "fields", + "mode" + ] + } + ] + }, + "includeViewNameInLabels": { + "type": "boolean" + }, + "type": { + "type": "string", + "enum": [ + "DYNAMIC_FILTER" + ] + } + }, + "required": [ + "id", + "fieldSelection", + "type" + ] + }, + { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "hidden": { + "type": "boolean" + }, + "id": { + "type": "string" + }, + "label": { + "type": "string" + }, + "defaultValue": { + "type": "integer", + "minimum": 1 + }, + "field": { + "type": "string" + }, + "max": { + "type": "integer", + "minimum": 1 + }, + "min": { + "type": "integer", + "minimum": 1 + }, + "type": { + "type": "string", + "enum": [ + "TOP_N" + ] + }, + "value": { + "type": "integer", + "minimum": 1 + } + }, + "required": [ + "id", + "defaultValue", + "field", + "type", + "value" + ] + } + ] + }, + "description": "Interactive controls (field selectors, PoP controls) attached to this query." + }, + "cube_metadata": { + "type": "object", + "properties": { + "cube_name": { + "type": "string" + }, + "hash_key": { + "type": "string" + }, + "topic_name": { + "type": "string" + } + }, + "required": [ + "cube_name", + "hash_key", + "topic_name" + ], + "additionalProperties": {}, + "description": "Cube-specific metadata (topic name, cube name, hash key) for cube-backed queries." + }, + "custom_summary_types": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Per-field custom summary functions (e.g. SUM, AVG, COUNT)." + }, + "dbtFileName": { + "type": "string", + "description": "dbt file name when this query is backed by a dbt model." + }, + "dbtMode": { + "type": "boolean", + "description": "Whether this query is in dbt mode." + }, + "default_group_by": { + "type": "boolean", + "description": "When true, all dimensions are implicitly included in GROUP BY." + }, + "dimensionIndex": { + "type": "number", + "description": "Index of the primary dimension used for result ordering." + }, + "executableSQL": { + "type": "string", + "description": "Server-compiled SQL string (read-only, set by the backend)." + }, + "fields": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Model field names selected for the query (dimensions + measures)." + }, + "fill_fields": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Fields whose missing date/time values should be filled with nulls to create continuous series." + }, + "filters": { + "type": "object", + "additionalProperties": { + "oneOf": [ + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "case_insensitive": { + "type": "boolean" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "kind": { + "type": "string", + "enum": [ + "CONTAINS", + "ENDS_WITH", + "STARTS_WITH", + "EQUALS", + "IS_EMPTY", + "SQL_LIKE" + ] + }, + "type": { + "type": "string", + "enum": [ + "string" + ] + }, + "values": { + "type": "array", + "items": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "hidden": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "kind", + "type", + "values" + ], + "additionalProperties": {} + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "is_inclusive": { + "type": "boolean" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "kind": { + "type": "string", + "enum": [ + "LESS_THAN", + "GREATER_THAN", + "EQUALS", + "BETWEEN" + ] + }, + "type": { + "type": "string", + "enum": [ + "number" + ] + }, + "values": { + "type": "array", + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + } + ] + } + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "hidden": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "kind", + "type", + "values" + ], + "additionalProperties": {} + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "isFiscal": { + "type": "boolean" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "kind": { + "type": "string", + "enum": [ + "IS_ON_DAY_OF_WEEK", + "IS_ON_DAY_OF_QUARTER", + "IS_IN_MONTH_OF_YEAR", + "IS_ON_DAY_OF_YEAR", + "IS_AT_HOUR_OF_DAY", + "IS_IN_QUARTER_OF_YEAR", + "IS_IN_WEEK_OF_YEAR", + "IS_ON_DAY_OF_MONTH", + "BETWEEN", + "ON_OR_AFTER", + "BEFORE", + "TIME_FOR_INTERVAL_DURATION", + "TIME_FOR_UNIT_DURATION", + "QUERY_OFFSET" + ] + }, + "left_side": { + "type": [ + "string", + "null" + ] + }, + "offset_interval_string": { + "type": [ + "string", + "null" + ] + }, + "right_side": { + "type": [ + "string", + "null" + ] + }, + "type": { + "type": "string", + "enum": [ + "date" + ] + }, + "ui_type": { + "type": [ + "string", + "null" + ], + "enum": [ + "ANY_TIME", + "BEFORE", + "BETWEEN", + "MONTH_OF_YEAR", + "PAST", + "YEAR", + "DAY", + "IS_ON_DAY_OF_WEEK", + "ON_OR_AFTER", + "IS_IN_THE_MONTH", + "IS_IN_THE_QUARTER", + "IS_IN_THE_FISCAL_QUARTER", + "IS_IN_THE_FISCAL_YEAR", + "TIME_FOR_INTERVAL_DURATION", + "TIME_FOR_UNIT_DURATION", + "CUSTOM", + null + ] + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "hidden": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "kind", + "type" + ], + "additionalProperties": {} + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "type": { + "type": "string", + "enum": [ + "null" + ] + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "hidden": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "type" + ], + "additionalProperties": {} + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "treat_nulls_as_false": { + "type": "boolean" + }, + "type": { + "type": "string", + "enum": [ + "boolean" + ] + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "hidden": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "type" + ], + "additionalProperties": {} + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "disregard_limit": { + "type": "boolean" + }, + "field_name": { + "type": "string" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "query_id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "query" + ] + }, + "view_query": { + "type": "object", + "properties": { + "fields": { + "type": "array", + "items": { + "type": "string" + } + }, + "filters": { + "type": "object", + "additionalProperties": {}, + "default": {} + }, + "limit": { + "type": "number" + }, + "sorts": { + "type": "array", + "items": {}, + "default": [] + }, + "table": { + "type": "string" + } + }, + "required": [ + "fields" + ], + "additionalProperties": {} + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "hidden": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "type" + ], + "additionalProperties": {} + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "type": { + "type": "string", + "enum": [ + "user_attribute" + ] + }, + "user_attribute_name": { + "type": "string" + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "hidden": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "type", + "user_attribute_name" + ], + "additionalProperties": {} + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "conjunction": { + "type": "string", + "enum": [ + "OR", + "AND" + ] + }, + "filters": { + "type": "array", + "items": { + "$ref": "#/components/schemas/CompositeFilter" + } + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "type": { + "type": "string", + "enum": [ + "composite" + ] + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "hidden": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "conjunction", + "filters", + "type" + ], + "additionalProperties": {} + } + ] + }, + "description": "Query filters keyed by filter ID." + }, + "filtersUsedInSql": { + "type": "object", + "additionalProperties": { + "oneOf": [ + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "case_insensitive": { + "type": "boolean" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "kind": { + "type": "string", + "enum": [ + "CONTAINS", + "ENDS_WITH", + "STARTS_WITH", + "EQUALS", + "IS_EMPTY", + "SQL_LIKE" + ] + }, + "type": { + "type": "string", + "enum": [ + "string" + ] + }, + "values": { + "type": "array", + "items": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "hidden": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "kind", + "type", + "values" + ], + "additionalProperties": {} + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "is_inclusive": { + "type": "boolean" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "kind": { + "type": "string", + "enum": [ + "LESS_THAN", + "GREATER_THAN", + "EQUALS", + "BETWEEN" + ] + }, + "type": { + "type": "string", + "enum": [ + "number" + ] + }, + "values": { + "type": "array", + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + } + ] + } + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "hidden": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "kind", + "type", + "values" + ], + "additionalProperties": {} + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "isFiscal": { + "type": "boolean" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "kind": { + "type": "string", + "enum": [ + "IS_ON_DAY_OF_WEEK", + "IS_ON_DAY_OF_QUARTER", + "IS_IN_MONTH_OF_YEAR", + "IS_ON_DAY_OF_YEAR", + "IS_AT_HOUR_OF_DAY", + "IS_IN_QUARTER_OF_YEAR", + "IS_IN_WEEK_OF_YEAR", + "IS_ON_DAY_OF_MONTH", + "BETWEEN", + "ON_OR_AFTER", + "BEFORE", + "TIME_FOR_INTERVAL_DURATION", + "TIME_FOR_UNIT_DURATION", + "QUERY_OFFSET" + ] + }, + "left_side": { + "type": [ + "string", + "null" + ] + }, + "offset_interval_string": { + "type": [ + "string", + "null" + ] + }, + "right_side": { + "type": [ + "string", + "null" + ] + }, + "type": { + "type": "string", + "enum": [ + "date" + ] + }, + "ui_type": { + "type": [ + "string", + "null" + ], + "enum": [ + "ANY_TIME", + "BEFORE", + "BETWEEN", + "MONTH_OF_YEAR", + "PAST", + "YEAR", + "DAY", + "IS_ON_DAY_OF_WEEK", + "ON_OR_AFTER", + "IS_IN_THE_MONTH", + "IS_IN_THE_QUARTER", + "IS_IN_THE_FISCAL_QUARTER", + "IS_IN_THE_FISCAL_YEAR", + "TIME_FOR_INTERVAL_DURATION", + "TIME_FOR_UNIT_DURATION", + "CUSTOM", + null + ] + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "hidden": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "kind", + "type" + ], + "additionalProperties": {} + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "type": { + "type": "string", + "enum": [ + "null" + ] + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "hidden": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "type" + ], + "additionalProperties": {} + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "treat_nulls_as_false": { + "type": "boolean" + }, + "type": { + "type": "string", + "enum": [ + "boolean" + ] + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "hidden": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "type" + ], + "additionalProperties": {} + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "disregard_limit": { + "type": "boolean" + }, + "field_name": { + "type": "string" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "query_id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "query" + ] + }, + "view_query": { + "type": "object", + "properties": { + "fields": { + "type": "array", + "items": { + "type": "string" + } + }, + "filters": { + "type": "object", + "additionalProperties": {}, + "default": {} + }, + "limit": { + "type": "number" + }, + "sorts": { + "type": "array", + "items": {}, + "default": [] + }, + "table": { + "type": "string" + } + }, + "required": [ + "fields" + ], + "additionalProperties": {} + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "hidden": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "type" + ], + "additionalProperties": {} + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "type": { + "type": "string", + "enum": [ + "user_attribute" + ] + }, + "user_attribute_name": { + "type": "string" + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "hidden": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "type", + "user_attribute_name" + ], + "additionalProperties": {} + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "conjunction": { + "type": "string", + "enum": [ + "OR", + "AND" + ] + }, + "filters": { + "type": "array", + "items": { + "$ref": "#/components/schemas/CompositeFilter" + } + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "type": { + "type": "string", + "enum": [ + "composite" + ] + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "hidden": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "conjunction", + "filters", + "type" + ], + "additionalProperties": {} + } + ] + }, + "description": "Filters that were embedded directly in raw SQL (read-only)." + }, + "join_paths_from_topic_name": { + "type": "string", + "description": "Topic name that determines join path precedence for parsed SQL queries." + }, + "join_via_map": { + "type": "object", + "additionalProperties": { + "type": "array", + "items": { + "type": "string" + } + }, + "description": "Virtual topic join path overrides, keyed by view name to ordered join path." + }, + "limit": { + "type": "number", + "description": "Row limit for the query." + }, + "manualSort": { + "type": "boolean", + "description": "When true, the user has explicitly set a custom sort order." + }, + "metadata": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "format": { + "type": "string" + }, + "label": { + "type": "string" + }, + "order": { + "type": "number" + } + }, + "additionalProperties": {} + }, + "description": "Per-field display metadata (format, label, order)." + }, + "offset": { + "type": "number", + "description": "Row offset for pagination." + }, + "parsed": { + "type": "boolean", + "description": "Whether this raw SQL query has been parsed into a semantic query." + }, + "periodOverPeriodTransposed": { + "type": "boolean", + "description": "Whether the period-over-period comparison columns are transposed." + }, + "period_over_period_computations": { + "type": "array", + "items": { + "type": "object", + "properties": { + "date_filter_field_name": { + "type": "string", + "description": "The date dimension field this comparison is anchored to." + }, + "date_filter_id": { + "type": "string", + "description": "ID of the date filter being offset (if backed by a dashboard filter)." + }, + "is_dynamic_previous_period": { + "type": "boolean", + "description": "When true, the previous period is calculated dynamically relative to the current filter range." + }, + "periods_ago": { + "type": [ + "number", + "null" + ], + "description": "How many periods back to compare (e.g. 1 = previous period). Null if not set." + }, + "time_unit_name": { + "type": [ + "string", + "null" + ], + "description": "Time grain for the offset (e.g. \"month\", \"year\"). Null if not set." + } + }, + "required": [ + "date_filter_field_name", + "periods_ago", + "time_unit_name" + ], + "additionalProperties": {} + }, + "description": "Period-over-period comparison configurations." + }, + "pivots": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Field names to pivot on (columns become values)." + }, + "rewriteSql": { + "type": "boolean", + "description": "When true, the backend should rewrite/optimize the SQL." + }, + "row_totals": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "aggregation" + ] + } + }, + "required": [ + "type" + ] + }, + "description": "Row-level aggregation totals, keyed by field name." + }, + "sorts": { + "type": "array", + "items": { + "type": "object", + "properties": { + "column_name": { + "type": "string", + "description": "The model field name to sort by." + }, + "is_column_sort": { + "type": "boolean", + "description": "When true, this sort targets a pivoted column rather than a row dimension." + }, + "pivot_value_map": { + "type": "object", + "additionalProperties": { + "type": [ + "string", + "null" + ] + }, + "description": "Maps pivot field names to specific pivot values, scoping the sort to a single pivot column." + }, + "sort_descending": { + "type": "boolean", + "description": "When true, sort order is descending." + }, + "subtotal_sort": { + "type": "string", + "description": "Field name whose subtotal row should be used as the sort key." + } + }, + "required": [ + "column_name", + "sort_descending" + ], + "additionalProperties": {} + }, + "description": "Sort clauses applied to the query result set." + }, + "sqlSortsEnabled": { + "type": "boolean", + "description": "Whether user-created sorts are enabled on a raw SQL query." + }, + "staticQueryReferences": { + "type": "object", + "additionalProperties": {}, + "description": "Pre-computed query references for AI chat context. Inner shape is `OmniQuery & { model_id: string }`; left as `unknown` to avoid a recursive zod schema. Validated structurally by consumers when they execute the referenced sub-queries." + }, + "table": { + "type": "string", + "description": "Base view (table) name in the model." + }, + "transposed_measures": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Measure field names that have been transposed into rows." + }, + "userEditedSQL": { + "type": "string", + "description": "User-authored raw SQL (empty string when not in SQL mode)." + }, + "version": { + "type": "number", + "description": "Schema version for migration support." + } + }, + "required": [ + "calculations", + "column_totals", + "fields", + "fill_fields", + "filters", + "pivots", + "row_totals", + "sorts", + "table", + "userEditedSQL" + ], + "additionalProperties": {}, + "description": "The semantic query for this tab, minus the server-owned workbook model anchors (modelId / model_extension_id). Omitted on a no-op replay; the server anchors new/changed tiles to the draft." + }, + "resultConfig": { + "type": "object", + "additionalProperties": {}, + "description": "Result display configuration (column widths, frozen columns, conditional formatting, number formatting, etc.)." + }, + "subTitle": { + "type": [ + "string", + "null" + ], + "maxLength": 250, + "description": "User-provided tab subtitle." + }, + "topicName": { + "type": [ + "string", + "null" + ], + "description": "The topic (explore) this query is built on." + }, + "type": { + "type": "string", + "enum": [ + "blank", + "csv", + "query", + "dataset", + "spreadsheet", + "sql", + "dbt", + "query-view", + "linked", + "app" + ], + "description": "The query presentation type (e.g. SEMANTIC, SQL, LINKED, SPREADSHEET)." + }, + "visConfig": { + "type": [ + "object", + "null" + ], + "properties": { + "chartType": { + "type": [ + "string", + "null" + ], + "enum": [ + "auto", + "area", + "areaStacked", + "areaStackedPercentage", + "bar", + "barLine", + "barGrouped", + "barStacked", + "barStackedPercentage", + "boxplot", + "code", + "column", + "columnGrouped", + "columnStacked", + "columnStackedPercentage", + "heatmap", + "kpi", + "line", + "lineColor", + "map", + "regionMap", + "markdown", + "omni-ai-summary-markdown", + "pie", + "funnel", + "sankey", + "point", + "pointColor", + "pointSize", + "pointSizeColor", + "singleRecord", + "omni-spreadsheet", + "summaryValue", + "svgMap", + "table", + null + ], + "description": "High-level chart type (e.g. \"bar\", \"line\", \"area\")." + }, + "fields": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Field names used in the visualization axes/series." + }, + "version": { + "type": "number", + "description": "Schema version for vis config migration." + }, + "visConfig": { + "type": "object", + "properties": { + "visType": { + "type": [ + "string", + "null" + ], + "enum": [ + "vegalite", + "omni-ai-summary-markdown", + "basic", + "omni-kpi", + "map", + "omni-markdown", + "funnel", + "sankey", + "single-record", + "svg-map", + "omni-spreadsheet", + "spreadsheet-tab", + "summary-value", + "omni-table", + "app", + null + ], + "description": "The visualization type (e.g. \"basic\", \"omni-table\")." + } + }, + "additionalProperties": {}, + "description": "Inner visualization config — structure varies by visType." + } + }, + "additionalProperties": {}, + "description": "Visualization configuration for the tile." + }, + "sourceQueryPresentationKey": { + "type": [ + "string", + "null" + ], + "pattern": "^[1-9][0-9]*$", + "description": "For LINKED-type tabs, the record key — the same identifier used as a `queryPresentations.data` key — of the source tile whose query this tab reuses. Null for all other tab types. This is a tile record key, NOT a positional index into `order`." + } + }, + "required": [ + "type" + ], + "additionalProperties": false + }, + "SettingsPatchExternal": { + "type": "object", + "properties": { + "crossfilterEnabled": { + "type": "boolean", + "description": "When true, clicking a value in one tile filters all other tiles on the dashboard." + }, + "customText": { + "type": [ + "object", + "null" + ], + "properties": { + "queryError": { + "type": "string", + "description": "Custom text shown when a query errors, replacing the default error text." + }, + "queryNoResults": { + "type": "string", + "description": "Custom text shown when a query returns no results, replacing the default empty state." + } + }, + "description": "Custom text replacing default UI strings on the dashboard, e.g. when queries error or return no results." + }, + "facetFilters": { + "type": "boolean", + "description": "When true, dashboard filters are applied per-facet when faceting is active." + }, + "refreshInterval": { + "type": [ + "number", + "null" + ], + "description": "Auto-refresh interval in seconds. Null disables auto-refresh." + }, + "runQueriesOn": { + "type": [ + "string", + "null" + ], + "enum": [ + "current-page", + "all-pages", + null + ], + "description": "Controls whether dashboard queries execute on the visible page or across all pages." + } + }, + "description": "Document settings. Shallow-merged with the existing settings." + }, + "DocumentsV2ReadResponse": { + "type": "object", + "properties": { + "containers": { + "$ref": "#/components/schemas/Containers" + }, + "controls": { + "$ref": "#/components/schemas/ControlsReadExternal" + }, + "description": { + "type": [ + "string", + "null" + ], + "description": "Document description." + }, + "name": { + "type": "string", + "maxLength": 254, + "description": "Document name." + }, + "queryPresentations": { + "$ref": "#/components/schemas/QueryPresentationsReadExternal" + }, + "settings": { + "$ref": "#/components/schemas/SettingsReadExternal" + } + }, + "required": [ + "description", + "name", + "queryPresentations" + ] + }, + "ControlsReadExternal": { + "type": "object", + "properties": { + "data": { + "type": "object", + "additionalProperties": { + "$ref": "#/components/schemas/ControlReadExternal" + }, + "description": "Controls keyed by control ID." + }, + "order": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Display order for controls." + } + }, + "required": [ + "data", + "order" + ] + }, + "ControlReadExternal": { + "type": "object", + "properties": { + "config": { + "oneOf": [ + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "case_insensitive": { + "type": "boolean" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "kind": { + "type": "string", + "enum": [ + "CONTAINS", + "ENDS_WITH", + "STARTS_WITH", + "EQUALS", + "IS_EMPTY", + "SQL_LIKE" + ] + }, + "type": { + "type": "string", + "enum": [ + "string" + ] + }, + "values": { + "type": "array", + "items": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "kind", + "type", + "values" + ], + "additionalProperties": {} + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "is_inclusive": { + "type": "boolean" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "kind": { + "type": "string", + "enum": [ + "LESS_THAN", + "GREATER_THAN", + "EQUALS", + "BETWEEN" + ] + }, + "type": { + "type": "string", + "enum": [ + "number" + ] + }, + "values": { + "type": "array", + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + } + ] + } + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "kind", + "type", + "values" + ], + "additionalProperties": {} + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "isFiscal": { + "type": "boolean" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "kind": { + "type": "string", + "enum": [ + "IS_ON_DAY_OF_WEEK", + "IS_ON_DAY_OF_QUARTER", + "IS_IN_MONTH_OF_YEAR", + "IS_ON_DAY_OF_YEAR", + "IS_AT_HOUR_OF_DAY", + "IS_IN_QUARTER_OF_YEAR", + "IS_IN_WEEK_OF_YEAR", + "IS_ON_DAY_OF_MONTH", + "BETWEEN", + "ON_OR_AFTER", + "BEFORE", + "TIME_FOR_INTERVAL_DURATION", + "TIME_FOR_UNIT_DURATION", + "QUERY_OFFSET" + ] + }, + "left_side": { + "type": [ + "string", + "null" + ] + }, + "offset_interval_string": { + "type": [ + "string", + "null" + ] + }, + "right_side": { + "type": [ + "string", + "null" + ] + }, + "type": { + "type": "string", + "enum": [ + "date" + ] + }, + "ui_type": { + "type": [ + "string", + "null" + ], + "enum": [ + "ANY_TIME", + "BEFORE", + "BETWEEN", + "MONTH_OF_YEAR", + "PAST", + "YEAR", + "DAY", + "IS_ON_DAY_OF_WEEK", + "ON_OR_AFTER", + "IS_IN_THE_MONTH", + "IS_IN_THE_QUARTER", + "IS_IN_THE_FISCAL_QUARTER", + "IS_IN_THE_FISCAL_YEAR", + "TIME_FOR_INTERVAL_DURATION", + "TIME_FOR_UNIT_DURATION", + "CUSTOM", + null + ] + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "kind", + "type" + ], + "additionalProperties": {} + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "type": { + "type": "string", + "enum": [ + "null" + ] + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "type" + ], + "additionalProperties": {} + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "treat_nulls_as_false": { + "type": "boolean" + }, + "type": { + "type": "string", + "enum": [ + "boolean" + ] + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "type" + ], + "additionalProperties": {} + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "disregard_limit": { + "type": "boolean" + }, + "field_name": { + "type": "string" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "query_id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "query" + ] + }, + "view_query": { + "type": "object", + "properties": { + "fields": { + "type": "array", + "items": { + "type": "string" + } + }, + "filters": { + "type": "object", + "additionalProperties": {}, + "default": {} + }, + "limit": { + "type": "number" + }, + "sorts": { + "type": "array", + "items": {}, + "default": [] + }, + "table": { + "type": "string" + } + }, + "required": [ + "fields" + ], + "additionalProperties": {} + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "type" + ], + "additionalProperties": {} + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "type": { + "type": "string", + "enum": [ + "user_attribute" + ] + }, + "user_attribute_name": { + "type": "string" + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "type", + "user_attribute_name" + ], + "additionalProperties": {} + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "conjunction": { + "type": "string", + "enum": [ + "OR", + "AND" + ] + }, + "filters": { + "type": "array", + "items": { + "$ref": "#/components/schemas/CompositeFilter" + } + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "type": { + "type": "string", + "enum": [ + "composite" + ] + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "conjunction", + "filters", + "type" + ], + "additionalProperties": {} + }, + { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "label": { + "type": "string" + }, + "display": { + "type": "string", + "enum": [ + "SELECT", + "BUTTON_TOGGLE" + ] + }, + "field": { + "type": "string" + }, + "kind": { + "type": "string", + "enum": [ + "FIELD", + "TIMEFRAME" + ] + }, + "options": { + "type": "array", + "items": { + "type": "object", + "properties": { + "isDimension": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "topicLabel": { + "type": "string" + }, + "value": { + "type": "string" + }, + "viewLabel": { + "type": "string" + } + }, + "required": [ + "label", + "value" + ] + } + }, + "type": { + "type": "string", + "enum": [ + "FIELD_SELECTION" + ] + } + }, + "required": [ + "id", + "field", + "kind", + "options", + "type" + ] + }, + { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "label": { + "type": "string" + }, + "display": { + "type": "string", + "enum": [ + "SELECT", + "BUTTON_TOGGLE" + ] + }, + "options": { + "type": "array", + "items": { + "type": "object", + "properties": { + "label": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "required": [ + "label", + "value" + ] + } + }, + "selectionMap": { + "type": "object", + "additionalProperties": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "type": { + "type": "string", + "enum": [ + "MULTI_FIELD_SELECTION" + ] + }, + "value": { + "type": "string" + } + }, + "required": [ + "id", + "options", + "selectionMap", + "type" + ] + }, + { + "type": "object", + "properties": { + "computations": { + "type": "array", + "items": { + "type": "object", + "properties": { + "filterId": { + "type": "string" + }, + "isDynamicPreviousPeriod": { + "type": "boolean" + }, + "periodsAgo": { + "type": [ + "number", + "null" + ] + }, + "timeUnitName": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "periodsAgo", + "timeUnitName" + ] + } + }, + "filterFieldName": { + "type": "string" + }, + "filterId": { + "type": "string" + }, + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "PERIOD_OVER_PERIOD" + ] + } + }, + "required": [ + "computations", + "filterFieldName", + "id", + "type" + ] + }, + { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "label": { + "type": "string" + }, + "options": { + "type": "array", + "items": { + "type": "object", + "properties": { + "isDimension": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "topicLabel": { + "type": "string" + }, + "value": { + "type": "string" + }, + "viewLabel": { + "type": "string" + } + }, + "required": [ + "label", + "value" + ] + } + }, + "type": { + "type": "string", + "enum": [ + "FIELD_PICKER" + ] + }, + "values": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "id", + "options", + "type" + ] + }, + { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "label": { + "type": "string" + }, + "conjunction": { + "type": "string", + "enum": [ + "OR" + ] + }, + "filters": { + "type": "array", + "items": { + "type": "object", + "properties": { + "fieldName": { + "type": "string" + }, + "filter": { + "$ref": "#/components/schemas/JsonValue" + }, + "id": { + "type": "string" + } + }, + "required": [ + "fieldName", + "filter", + "id" + ] + } + }, + "type": { + "type": "string", + "enum": [ + "MULTI_FIELD_FILTER" + ] + } + }, + "required": [ + "id", + "conjunction", + "filters", + "type" + ] + }, + { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "label": { + "type": "string" + }, + "fieldSelection": { + "oneOf": [ + { + "type": "object", + "properties": { + "mode": { + "type": "string", + "enum": [ + "full-model" + ] + } + }, + "required": [ + "mode" + ] + }, + { + "type": "object", + "properties": { + "mode": { + "type": "string", + "enum": [ + "auto" + ] + }, + "topics": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "mode", + "topics" + ] + }, + { + "type": "object", + "properties": { + "fields": { + "type": "array", + "items": { + "type": "object", + "properties": { + "fieldName": { + "type": "string" + }, + "topicName": { + "type": "string" + } + }, + "required": [ + "fieldName" + ] + } + }, + "mode": { + "type": "string", + "enum": [ + "specific" + ] + } + }, + "required": [ + "fields", + "mode" + ] + } + ] + }, + "includeViewNameInLabels": { + "type": "boolean" + }, + "type": { + "type": "string", + "enum": [ + "DYNAMIC_FILTER" + ] + } + }, + "required": [ + "id", + "fieldSelection", + "type" + ] + }, + { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "label": { + "type": "string" + }, + "defaultValue": { + "type": "integer", + "minimum": 1 + }, + "field": { + "type": "string" + }, + "max": { + "type": "integer", + "minimum": 1 + }, + "min": { + "type": "integer", + "minimum": 1 + }, + "type": { + "type": "string", + "enum": [ + "TOP_N" + ] + }, + "value": { + "type": "integer", + "minimum": 1 + } + }, + "required": [ + "id", + "defaultValue", + "field", + "type", + "value" + ] + } + ], + "description": "Filter or interactive control config. Discriminated by `type`: filter types (string, date, number, etc.) or control types (FIELD_SELECTION, PERIOD_OVER_PERIOD, etc.). Visibility is determined by placement in the filter-bar container." + }, + "map": { + "type": "object", + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "boolean", + "enum": [ + false + ] + } + ] + }, + "description": "Per-tile field overrides keyed by tab ID. Values are a field name (override) or false (exclude tile from control)." + } + }, + "required": [ + "config" + ] + }, + "QueryPresentationsReadExternal": { + "type": "object", + "properties": { + "data": { + "type": "object", + "additionalProperties": { + "$ref": "#/components/schemas/QueryPresentationReadExternal" + }, + "description": "Query presentations keyed by tab ID." + }, + "order": { + "type": "array", + "items": { + "type": "string", + "pattern": "^[1-9][0-9]*$" + }, + "description": "Tab display order." + } + }, + "required": [ + "data", + "order" + ] + }, + "QueryPresentationReadExternal": { + "type": "object", + "properties": { + "aiConfig": { + "type": [ + "object", + "null" + ], + "properties": { + "description": { + "type": "object", + "properties": { + "aiContext": { + "type": "string" + }, + "enabled": { + "type": "boolean" + } + } + }, + "subTitle": { + "type": "object", + "properties": { + "aiContext": { + "type": "string" + }, + "enabled": { + "type": "boolean" + } + } + } + }, + "description": "AI-generated metadata config (subtitle/description auto-generation settings)." + }, + "automaticVis": { + "type": [ + "boolean", + "null" + ], + "description": "When true, the system automatically selects the best visualization type." + }, + "description": { + "type": [ + "string", + "null" + ], + "maxLength": 500, + "description": "User-provided tab description." + }, + "editingModelObjectName": { + "type": [ + "string", + "null" + ], + "description": "Model object (view/topic) currently being edited via the dataset/query-view editor. Applies only to dataset / query-view tabs — omitted from reads and rejected on patches for other tab types." + }, + "editingModelObjectNameChange": { + "type": [ + "string", + "null" + ], + "description": "Pending rename of the model object being edited. Applies only to dataset / query-view tabs — omitted from reads and rejected on patches for other tab types." + }, + "filterOrder": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Ordered list of filter field names controlling display order on this tab." + }, + "isSql": { + "type": [ + "boolean", + "null" + ], + "description": "Whether this tab is in raw SQL mode." + }, + "name": { + "type": "string", + "minLength": 1, + "maxLength": 144, + "description": "User-provided tab name." + }, + "prefersChart": { + "type": "boolean", + "description": "When true, the chart view is shown by default instead of the data table." + }, + "query": { + "type": [ + "object", + "null" + ], + "properties": { + "aiGenerated": { + "type": "boolean", + "description": "True when AI generated this query’s SQL; the AI SQL is shown in the advanced SQL box." + }, + "branch_id": { + "type": "string", + "description": "Branch model ID when querying against a model branch." + }, + "calculations": { + "type": "array", + "items": { + "type": "object", + "properties": { + "allow_refs_to_unselected_fields": { + "type": "boolean", + "description": "Set by the Kotlin parser when this calc references fields not selected at the top level (AI SQL-gen produces these; UI-authored calcs do not)." + }, + "calc_name": { + "type": "string", + "description": "Internal identifier for the calculation, used as the column alias." + }, + "description": { + "type": "string", + "description": "Description of the calculation." + }, + "format": { + "type": "string", + "description": "Number/date format string (e.g. \"#,##0.00\")." + }, + "label": { + "type": "string", + "description": "Display label shown in the UI." + }, + "original_formula": { + "type": "string", + "description": "The original Excel-style formula before parsing (e.g. \"=SUM(A1:A10)\")." + }, + "outside_pivot": { + "type": "boolean", + "description": "When true, the calculation is evaluated outside the pivot grouping." + }, + "pushdown": { + "type": [ + "boolean", + "null" + ], + "description": "Per-calc override for whether to evaluate before the row limit. `null` defers to the model-level default." + }, + "sql": { + "type": "string", + "description": "Compiled SQL string produced from the formula." + }, + "sql_expression": { + "description": "Parsed SQL expression tree (serialized)." + }, + "swallow_errors": { + "type": "boolean", + "description": "When true, calculation errors are silently swallowed instead of surfaced." + } + }, + "required": [ + "calc_name" + ], + "additionalProperties": {} + }, + "description": "Table calculations attached to this query." + }, + "column_limit": { + "type": "number", + "description": "Max number of pivot columns to return." + }, + "column_totals": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "aggregation" + ] + } + }, + "required": [ + "type" + ] + }, + "description": "Column-level aggregation totals, keyed by field name." + }, + "controls": { + "type": "array", + "items": { + "oneOf": [ + { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "hidden": { + "type": "boolean" + }, + "id": { + "type": "string" + }, + "label": { + "type": "string" + }, + "display": { + "type": "string", + "enum": [ + "SELECT", + "BUTTON_TOGGLE" + ] + }, + "field": { + "type": "string" + }, + "kind": { + "type": "string", + "enum": [ + "FIELD", + "TIMEFRAME" + ] + }, + "options": { + "type": "array", + "items": { + "type": "object", + "properties": { + "isDimension": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "topicLabel": { + "type": "string" + }, + "value": { + "type": "string" + }, + "viewLabel": { + "type": "string" + } + }, + "required": [ + "label", + "value" + ] + } + }, + "type": { + "type": "string", + "enum": [ + "FIELD_SELECTION" + ] + } + }, + "required": [ + "id", + "field", + "kind", + "options", + "type" + ] + }, + { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "hidden": { + "type": "boolean" + }, + "id": { + "type": "string" + }, + "label": { + "type": "string" + }, + "display": { + "type": "string", + "enum": [ + "SELECT", + "BUTTON_TOGGLE" + ] + }, + "options": { + "type": "array", + "items": { + "type": "object", + "properties": { + "label": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "required": [ + "label", + "value" + ] + } + }, + "selectionMap": { + "type": "object", + "additionalProperties": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "type": { + "type": "string", + "enum": [ + "MULTI_FIELD_SELECTION" + ] + }, + "value": { + "type": "string" + } + }, + "required": [ + "id", + "options", + "selectionMap", + "type" + ] + }, + { + "type": "object", + "properties": { + "computations": { + "type": "array", + "items": { + "type": "object", + "properties": { + "filterId": { + "type": "string" + }, + "isDynamicPreviousPeriod": { + "type": "boolean" + }, + "periodsAgo": { + "type": [ + "number", + "null" + ] + }, + "timeUnitName": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "periodsAgo", + "timeUnitName" + ] + } + }, + "filterFieldName": { + "type": "string" + }, + "filterId": { + "type": "string" + }, + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "PERIOD_OVER_PERIOD" + ] + } + }, + "required": [ + "computations", + "filterFieldName", + "id", + "type" + ] + }, + { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "hidden": { + "type": "boolean" + }, + "id": { + "type": "string" + }, + "label": { + "type": "string" + }, + "options": { + "type": "array", + "items": { + "type": "object", + "properties": { + "isDimension": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "topicLabel": { + "type": "string" + }, + "value": { + "type": "string" + }, + "viewLabel": { + "type": "string" + } + }, + "required": [ + "label", + "value" + ] + } + }, + "type": { + "type": "string", + "enum": [ + "FIELD_PICKER" + ] + }, + "values": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "id", + "options", + "type" + ] + }, + { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "hidden": { + "type": "boolean" + }, + "id": { + "type": "string" + }, + "label": { + "type": "string" + }, + "conjunction": { + "type": "string", + "enum": [ + "OR" + ] + }, + "filters": { + "type": "array", + "items": { + "type": "object", + "properties": { + "fieldName": { + "type": "string" + }, + "filter": { + "$ref": "#/components/schemas/JsonValue" + }, + "id": { + "type": "string" + } + }, + "required": [ + "fieldName", + "filter", + "id" + ] + } + }, + "type": { + "type": "string", + "enum": [ + "MULTI_FIELD_FILTER" + ] + } + }, + "required": [ + "id", + "conjunction", + "filters", + "type" + ] + }, + { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "hidden": { + "type": "boolean" + }, + "id": { + "type": "string" + }, + "label": { + "type": "string" + }, + "fieldSelection": { + "oneOf": [ + { + "type": "object", + "properties": { + "mode": { + "type": "string", + "enum": [ + "full-model" + ] + } + }, + "required": [ + "mode" + ] + }, + { + "type": "object", + "properties": { + "mode": { + "type": "string", + "enum": [ + "auto" + ] + }, + "topics": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "mode", + "topics" + ] + }, + { + "type": "object", + "properties": { + "fields": { + "type": "array", + "items": { + "type": "object", + "properties": { + "fieldName": { + "type": "string" + }, + "topicName": { + "type": "string" + } + }, + "required": [ + "fieldName" + ] + } + }, + "mode": { + "type": "string", + "enum": [ + "specific" + ] + } + }, + "required": [ + "fields", + "mode" + ] + } + ] + }, + "includeViewNameInLabels": { + "type": "boolean" + }, + "type": { + "type": "string", + "enum": [ + "DYNAMIC_FILTER" + ] + } + }, + "required": [ + "id", + "fieldSelection", + "type" + ] + }, + { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "hidden": { + "type": "boolean" + }, + "id": { + "type": "string" + }, + "label": { + "type": "string" + }, + "defaultValue": { + "type": "integer", + "minimum": 1 + }, + "field": { + "type": "string" + }, + "max": { + "type": "integer", + "minimum": 1 + }, + "min": { + "type": "integer", + "minimum": 1 + }, + "type": { + "type": "string", + "enum": [ + "TOP_N" + ] + }, + "value": { + "type": "integer", + "minimum": 1 + } + }, + "required": [ + "id", + "defaultValue", + "field", + "type", + "value" + ] + } + ] + }, + "description": "Interactive controls (field selectors, PoP controls) attached to this query." + }, + "cube_metadata": { + "type": "object", + "properties": { + "cube_name": { + "type": "string" + }, + "hash_key": { + "type": "string" + }, + "topic_name": { + "type": "string" + } + }, + "required": [ + "cube_name", + "hash_key", + "topic_name" + ], + "additionalProperties": {}, + "description": "Cube-specific metadata (topic name, cube name, hash key) for cube-backed queries." + }, + "custom_summary_types": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Per-field custom summary functions (e.g. SUM, AVG, COUNT)." + }, + "dbtFileName": { + "type": "string", + "description": "dbt file name when this query is backed by a dbt model." + }, + "dbtMode": { + "type": "boolean", + "description": "Whether this query is in dbt mode." + }, + "default_group_by": { + "type": "boolean", + "description": "When true, all dimensions are implicitly included in GROUP BY." + }, + "dimensionIndex": { + "type": "number", + "description": "Index of the primary dimension used for result ordering." + }, + "executableSQL": { + "type": "string", + "description": "Server-compiled SQL string (read-only, set by the backend)." + }, + "fields": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Model field names selected for the query (dimensions + measures)." + }, + "fill_fields": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Fields whose missing date/time values should be filled with nulls to create continuous series." + }, + "filters": { + "type": "object", + "additionalProperties": { + "oneOf": [ + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "case_insensitive": { + "type": "boolean" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "kind": { + "type": "string", + "enum": [ + "CONTAINS", + "ENDS_WITH", + "STARTS_WITH", + "EQUALS", + "IS_EMPTY", + "SQL_LIKE" + ] + }, + "type": { + "type": "string", + "enum": [ + "string" + ] + }, + "values": { + "type": "array", + "items": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "hidden": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "kind", + "type", + "values" + ], + "additionalProperties": {} + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "is_inclusive": { + "type": "boolean" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "kind": { + "type": "string", + "enum": [ + "LESS_THAN", + "GREATER_THAN", + "EQUALS", + "BETWEEN" + ] + }, + "type": { + "type": "string", + "enum": [ + "number" + ] + }, + "values": { + "type": "array", + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + } + ] + } + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "hidden": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "kind", + "type", + "values" + ], + "additionalProperties": {} + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "isFiscal": { + "type": "boolean" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "kind": { + "type": "string", + "enum": [ + "IS_ON_DAY_OF_WEEK", + "IS_ON_DAY_OF_QUARTER", + "IS_IN_MONTH_OF_YEAR", + "IS_ON_DAY_OF_YEAR", + "IS_AT_HOUR_OF_DAY", + "IS_IN_QUARTER_OF_YEAR", + "IS_IN_WEEK_OF_YEAR", + "IS_ON_DAY_OF_MONTH", + "BETWEEN", + "ON_OR_AFTER", + "BEFORE", + "TIME_FOR_INTERVAL_DURATION", + "TIME_FOR_UNIT_DURATION", + "QUERY_OFFSET" + ] + }, + "left_side": { + "type": [ + "string", + "null" + ] + }, + "offset_interval_string": { + "type": [ + "string", + "null" + ] + }, + "right_side": { + "type": [ + "string", + "null" + ] + }, + "type": { + "type": "string", + "enum": [ + "date" + ] + }, + "ui_type": { + "type": [ + "string", + "null" + ], + "enum": [ + "ANY_TIME", + "BEFORE", + "BETWEEN", + "MONTH_OF_YEAR", + "PAST", + "YEAR", + "DAY", + "IS_ON_DAY_OF_WEEK", + "ON_OR_AFTER", + "IS_IN_THE_MONTH", + "IS_IN_THE_QUARTER", + "IS_IN_THE_FISCAL_QUARTER", + "IS_IN_THE_FISCAL_YEAR", + "TIME_FOR_INTERVAL_DURATION", + "TIME_FOR_UNIT_DURATION", + "CUSTOM", + null + ] + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "hidden": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "kind", + "type" + ], + "additionalProperties": {} + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "type": { + "type": "string", + "enum": [ + "null" + ] + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "hidden": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "type" + ], + "additionalProperties": {} + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "treat_nulls_as_false": { + "type": "boolean" + }, + "type": { + "type": "string", + "enum": [ + "boolean" + ] + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "hidden": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "type" + ], + "additionalProperties": {} + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "disregard_limit": { + "type": "boolean" + }, + "field_name": { + "type": "string" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "query_id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "query" + ] + }, + "view_query": { + "type": "object", + "properties": { + "fields": { + "type": "array", + "items": { + "type": "string" + } + }, + "filters": { + "type": "object", + "additionalProperties": {}, + "default": {} + }, + "limit": { + "type": "number" + }, + "sorts": { + "type": "array", + "items": {}, + "default": [] + }, + "table": { + "type": "string" + } + }, + "required": [ + "fields" + ], + "additionalProperties": {} + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "hidden": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "type" + ], + "additionalProperties": {} + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "type": { + "type": "string", + "enum": [ + "user_attribute" + ] + }, + "user_attribute_name": { + "type": "string" + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "hidden": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "type", + "user_attribute_name" + ], + "additionalProperties": {} + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "conjunction": { + "type": "string", + "enum": [ + "OR", + "AND" + ] + }, + "filters": { + "type": "array", + "items": { + "$ref": "#/components/schemas/CompositeFilter" + } + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "type": { + "type": "string", + "enum": [ + "composite" + ] + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "hidden": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "conjunction", + "filters", + "type" + ], + "additionalProperties": {} + } + ] + }, + "description": "Query filters keyed by filter ID." + }, + "filtersUsedInSql": { + "type": "object", + "additionalProperties": { + "oneOf": [ + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "case_insensitive": { + "type": "boolean" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "kind": { + "type": "string", + "enum": [ + "CONTAINS", + "ENDS_WITH", + "STARTS_WITH", + "EQUALS", + "IS_EMPTY", + "SQL_LIKE" + ] + }, + "type": { + "type": "string", + "enum": [ + "string" + ] + }, + "values": { + "type": "array", + "items": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "hidden": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "kind", + "type", + "values" + ], + "additionalProperties": {} + }, { - "$ref": "#/components/schemas/ApiDocument" + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "is_inclusive": { + "type": "boolean" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "kind": { + "type": "string", + "enum": [ + "LESS_THAN", + "GREATER_THAN", + "EQUALS", + "BETWEEN" + ] + }, + "type": { + "type": "string", + "enum": [ + "number" + ] + }, + "values": { + "type": "array", + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + } + ] + } + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "hidden": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "kind", + "type", + "values" + ], + "additionalProperties": {} }, { "type": "object", "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "isFiscal": { + "type": "boolean" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "kind": { + "type": "string", + "enum": [ + "IS_ON_DAY_OF_WEEK", + "IS_ON_DAY_OF_QUARTER", + "IS_IN_MONTH_OF_YEAR", + "IS_ON_DAY_OF_YEAR", + "IS_AT_HOUR_OF_DAY", + "IS_IN_QUARTER_OF_YEAR", + "IS_IN_WEEK_OF_YEAR", + "IS_ON_DAY_OF_MONTH", + "BETWEEN", + "ON_OR_AFTER", + "BEFORE", + "TIME_FOR_INTERVAL_DURATION", + "TIME_FOR_UNIT_DURATION", + "QUERY_OFFSET" + ] + }, + "left_side": { + "type": [ + "string", + "null" + ] + }, + "offset_interval_string": { + "type": [ + "string", + "null" + ] + }, + "right_side": { + "type": [ + "string", + "null" + ] + }, "type": { "type": "string", "enum": [ - "document" + "date" + ] + }, + "ui_type": { + "type": [ + "string", + "null" + ], + "enum": [ + "ANY_TIME", + "BEFORE", + "BETWEEN", + "MONTH_OF_YEAR", + "PAST", + "YEAR", + "DAY", + "IS_ON_DAY_OF_WEEK", + "ON_OR_AFTER", + "IS_IN_THE_MONTH", + "IS_IN_THE_QUARTER", + "IS_IN_THE_FISCAL_QUARTER", + "IS_IN_THE_FISCAL_YEAR", + "TIME_FOR_INTERVAL_DURATION", + "TIME_FOR_UNIT_DURATION", + "CUSTOM", + null + ] + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "hidden": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "kind", + "type" + ], + "additionalProperties": {} + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "type": { + "type": "string", + "enum": [ + "null" + ] + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "hidden": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "type" + ], + "additionalProperties": {} + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "treat_nulls_as_false": { + "type": "boolean" + }, + "type": { + "type": "string", + "enum": [ + "boolean" + ] + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "hidden": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "type" + ], + "additionalProperties": {} + }, + { + "type": "object", + "properties": { + "cancel_query_filter": { + "type": "boolean" + }, + "ignore_if_unjoinable": { + "type": "boolean" + }, + "disregard_limit": { + "type": "boolean" + }, + "field_name": { + "type": "string" + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "query_id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "query" + ] + }, + "view_query": { + "type": "object", + "properties": { + "fields": { + "type": "array", + "items": { + "type": "string" + } + }, + "filters": { + "type": "object", + "additionalProperties": {}, + "default": {} + }, + "limit": { + "type": "number" + }, + "sorts": { + "type": "array", + "items": {}, + "default": [] + }, + "table": { + "type": "string" + } + }, + "required": [ + "fields" + ], + "additionalProperties": {} + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } ] + }, + "hidden": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } } }, "required": [ "type" - ] - } - ] - }, - { - "type": "object", - "properties": { - "id": { - "type": "string", - "description": "Unique identifier" - }, - "name": { - "type": "string", - "minLength": 1, - "maxLength": 255, - "description": "Content name" + ], + "additionalProperties": {} }, - "owner": { + { "type": "object", "properties": { - "id": { - "type": "string", - "description": "User ID of the owner" + "cancel_query_filter": { + "type": "boolean" }, - "name": { + "ignore_if_unjoinable": { + "type": "boolean" + }, + "type": { "type": "string", - "description": "Name of the owner" + "enum": [ + "user_attribute" + ] + }, + "user_attribute_name": { + "type": "string" + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "hidden": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } } }, "required": [ - "id", - "name" - ], - "description": "Content owner" - }, - "scope": { - "type": "string", - "enum": [ - "restricted", - "organization" + "type", + "user_attribute_name" ], - "description": "Content access scope" + "additionalProperties": {} }, - "_count": { + { "type": "object", "properties": { - "documents": { - "type": "number", - "description": "Number of documents" + "cancel_query_filter": { + "type": "boolean" }, - "favorites": { - "type": "number", - "description": "Number of users who favorited" + "ignore_if_unjoinable": { + "type": "boolean" + }, + "conjunction": { + "type": "string", + "enum": [ + "OR", + "AND" + ] + }, + "filters": { + "type": "array", + "items": { + "$ref": "#/components/schemas/CompositeFilter" + } + }, + "is_negative": { + "type": [ + "boolean", + "null" + ] + }, + "type": { + "type": "string", + "enum": [ + "composite" + ] + }, + "appliedLabels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "base_view": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "filterControlType": { + "anyOf": [ + { + "type": "string", + "enum": [ + "multiValueEquals", + "singleValueEquals" + ] + }, + { + "type": "string", + "enum": [ + "singleDay", + "timeframe" + ] + } + ] + }, + "hidden": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "topic": { + "type": "string" + }, + "watchedContainerIds": { + "type": "array", + "items": { + "type": "string" + } } }, "required": [ - "documents", - "favorites" + "conjunction", + "filters", + "type" ], - "description": "Folder counts" + "additionalProperties": {} + } + ] + }, + "description": "Filters that were embedded directly in raw SQL (read-only)." + }, + "join_paths_from_topic_name": { + "type": "string", + "description": "Topic name that determines join path precedence for parsed SQL queries." + }, + "join_via_map": { + "type": "object", + "additionalProperties": { + "type": "array", + "items": { + "type": "string" + } + }, + "description": "Virtual topic join path overrides, keyed by view name to ordered join path." + }, + "limit": { + "type": "number", + "description": "Row limit for the query." + }, + "manualSort": { + "type": "boolean", + "description": "When true, the user has explicitly set a custom sort order." + }, + "metadata": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "format": { + "type": "string" }, - "labels": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Labels" + "label": { + "type": "string" }, - "path": { + "order": { + "type": "number" + } + }, + "additionalProperties": {} + }, + "description": "Per-field display metadata (format, label, order)." + }, + "offset": { + "type": "number", + "description": "Row offset for pagination." + }, + "parsed": { + "type": "boolean", + "description": "Whether this raw SQL query has been parsed into a semantic query." + }, + "periodOverPeriodTransposed": { + "type": "boolean", + "description": "Whether the period-over-period comparison columns are transposed." + }, + "period_over_period_computations": { + "type": "array", + "items": { + "type": "object", + "properties": { + "date_filter_field_name": { "type": "string", - "description": "Full path to the folder", - "example": "sales-reports/q1-2026" + "description": "The date dimension field this comparison is anchored to." }, - "url": { + "date_filter_id": { "type": "string", - "description": "URL to view the folder in the Omni UI.", - "example": "https://org.omni.co/f/sales-reports" + "description": "ID of the date filter being offset (if backed by a dashboard filter)." + }, + "is_dynamic_previous_period": { + "type": "boolean", + "description": "When true, the previous period is calculated dynamically relative to the current filter range." + }, + "periods_ago": { + "type": [ + "number", + "null" + ], + "description": "How many periods back to compare (e.g. 1 = previous period). Null if not set." }, + "time_unit_name": { + "type": [ + "string", + "null" + ], + "description": "Time grain for the offset (e.g. \"month\", \"year\"). Null if not set." + } + }, + "required": [ + "date_filter_field_name", + "periods_ago", + "time_unit_name" + ], + "additionalProperties": {} + }, + "description": "Period-over-period comparison configurations." + }, + "pivots": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Field names to pivot on (columns become values)." + }, + "rewriteSql": { + "type": "boolean", + "description": "When true, the backend should rewrite/optimize the SQL." + }, + "row_totals": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { "type": { "type": "string", "enum": [ - "folder" + "aggregation" ] } }, "required": [ - "id", - "name", - "owner", - "scope", - "path", - "url", - "type" - ] - } - ] - } - } - }, - "required": [ - "pageInfo", - "records" - ] - }, - "OwnerInternal": { - "type": "object", - "properties": { - "id": { - "type": "string", - "description": "Owner membership ID" + "type" + ] + }, + "description": "Row-level aggregation totals, keyed by field name." + }, + "sorts": { + "type": "array", + "items": { + "type": "object", + "properties": { + "column_name": { + "type": "string", + "description": "The model field name to sort by." + }, + "is_column_sort": { + "type": "boolean", + "description": "When true, this sort targets a pivoted column rather than a row dimension." + }, + "pivot_value_map": { + "type": "object", + "additionalProperties": { + "type": [ + "string", + "null" + ] + }, + "description": "Maps pivot field names to specific pivot values, scoping the sort to a single pivot column." + }, + "sort_descending": { + "type": "boolean", + "description": "When true, sort order is descending." + }, + "subtotal_sort": { + "type": "string", + "description": "Field name whose subtotal row should be used as the sort key." + } + }, + "required": [ + "column_name", + "sort_descending" + ], + "additionalProperties": {} + }, + "description": "Sort clauses applied to the query result set." + }, + "sqlSortsEnabled": { + "type": "boolean", + "description": "Whether user-created sorts are enabled on a raw SQL query." + }, + "staticQueryReferences": { + "type": "object", + "additionalProperties": {}, + "description": "Pre-computed query references for AI chat context. Inner shape is `OmniQuery & { model_id: string }`; left as `unknown` to avoid a recursive zod schema. Validated structurally by consumers when they execute the referenced sub-queries." + }, + "table": { + "type": "string", + "description": "Base view (table) name in the model." + }, + "transposed_measures": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Measure field names that have been transposed into rows." + }, + "userEditedSQL": { + "type": "string", + "description": "User-authored raw SQL (empty string when not in SQL mode)." + }, + "version": { + "type": "number", + "description": "Schema version for migration support." + } + }, + "required": [ + "calculations", + "column_totals", + "fields", + "fill_fields", + "filters", + "pivots", + "row_totals", + "sorts", + "table", + "userEditedSQL" + ], + "additionalProperties": {}, + "description": "The semantic query for this tab, minus the server-owned workbook model anchors (modelId / model_extension_id). For LINKED-type tabs this field is read-only." }, - "name": { - "type": "string", - "description": "Owner display name" - } - }, - "required": [ - "id", - "name" - ], - "description": "Content owner" - }, - "ContentShareScope": { - "type": "string", - "enum": [ - "restricted", - "organization" - ], - "description": "Content access scope" - }, - "InternalFolder": { - "type": [ - "object", - "null" - ], - "properties": { - "id": { - "type": "string", - "description": "Folder ID" + "resultConfig": { + "type": "object", + "additionalProperties": {}, + "description": "Result display configuration (column widths, frozen columns, conditional formatting, number formatting, etc.)." }, - "name": { - "type": "string", - "minLength": 1, - "maxLength": 255, - "description": "Folder name" + "subTitle": { + "type": [ + "string", + "null" + ], + "maxLength": 250, + "description": "User-provided tab subtitle." }, - "path": { + "topicName": { + "type": [ + "string", + "null" + ], + "description": "The topic (explore) this query is built on." + }, + "type": { "type": "string", - "description": "Folder path" + "enum": [ + "blank", + "csv", + "query", + "dataset", + "spreadsheet", + "sql", + "dbt", + "query-view", + "linked", + "app" + ], + "description": "The query presentation type (e.g. SEMANTIC, SQL, LINKED, SPREADSHEET)." }, - "scope": { - "allOf": [ - { - "$ref": "#/components/schemas/ContentShareScope" + "visConfig": { + "type": [ + "object", + "null" + ], + "properties": { + "chartType": { + "type": [ + "string", + "null" + ], + "enum": [ + "auto", + "area", + "areaStacked", + "areaStackedPercentage", + "bar", + "barLine", + "barGrouped", + "barStacked", + "barStackedPercentage", + "boxplot", + "code", + "column", + "columnGrouped", + "columnStacked", + "columnStackedPercentage", + "heatmap", + "kpi", + "line", + "lineColor", + "map", + "regionMap", + "markdown", + "omni-ai-summary-markdown", + "pie", + "funnel", + "sankey", + "point", + "pointColor", + "pointSize", + "pointSizeColor", + "singleRecord", + "omni-spreadsheet", + "summaryValue", + "svgMap", + "table", + null + ], + "description": "High-level chart type (e.g. \"bar\", \"line\", \"area\")." }, - { - "description": "Folder access scope" + "fields": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Field names used in the visualization axes/series." + }, + "version": { + "type": "number", + "description": "Schema version for vis config migration." + }, + "visConfig": { + "type": "object", + "properties": { + "visType": { + "type": [ + "string", + "null" + ], + "enum": [ + "vegalite", + "omni-ai-summary-markdown", + "basic", + "omni-kpi", + "map", + "omni-markdown", + "funnel", + "sankey", + "single-record", + "svg-map", + "omni-spreadsheet", + "spreadsheet-tab", + "summary-value", + "omni-table", + "app", + null + ], + "description": "The visualization type (e.g. \"basic\", \"omni-table\")." + } + }, + "additionalProperties": {}, + "description": "Inner visualization config — structure varies by visType." } - ] + }, + "additionalProperties": {}, + "description": "Visualization configuration for the tile." + }, + "sourceQueryPresentationKey": { + "type": [ + "string", + "null" + ], + "pattern": "^[1-9][0-9]*$", + "description": "For LINKED-type tabs, the record key — the same identifier used as a `queryPresentations.data` key — of the source tile whose query this tab reuses. Null for all other tab types. This is a tile record key, NOT a positional index into `order`." } }, "required": [ - "id", + "aiConfig", + "automaticVis", + "description", + "filterOrder", + "isSql", "name", - "path", - "scope" - ], - "description": "Parent folder" + "prefersChart", + "query", + "resultConfig", + "subTitle", + "topicName", + "type", + "visConfig", + "sourceQueryPresentationKey" + ] }, - "ApiDocument": { + "SettingsReadExternal": { "type": "object", "properties": { - "name": { - "type": "string", - "minLength": 1, - "maxLength": 255, - "description": "Content name" - }, - "owner": { - "$ref": "#/components/schemas/OwnerInternal" - }, - "scope": { - "$ref": "#/components/schemas/ContentShareScope" + "crossfilterEnabled": { + "type": "boolean", + "description": "When true, clicking a value in one tile filters all other tiles on the dashboard." }, - "_count": { - "type": "object", + "customText": { + "type": [ + "object", + "null" + ], "properties": { - "favorites": { - "type": "number", - "description": "Number of users who favorited" + "queryError": { + "type": "string", + "description": "Custom text shown when a query errors, replacing the default error text." }, - "views": { - "type": "number", - "description": "Number of views" + "queryNoResults": { + "type": "string", + "description": "Custom text shown when a query returns no results, replacing the default empty state." } }, - "required": [ - "favorites", - "views" - ], - "description": "Document counts" - }, - "connectionId": { - "type": "string", - "description": "Connection ID" + "description": "Custom text replacing default UI strings on the dashboard, e.g. when queries error or return no results." }, - "deleted": { + "facetFilters": { "type": "boolean", - "description": "Whether document is deleted" + "description": "When true, dashboard filters are applied per-facet when faceting is active." + }, + "refreshInterval": { + "type": [ + "number", + "null" + ], + "description": "Auto-refresh interval in seconds. Null disables auto-refresh." }, + "runQueriesOn": { + "type": [ + "string", + "null" + ], + "enum": [ + "current-page", + "all-pages", + null + ], + "description": "Controls whether dashboard queries execute on the visible page or across all pages." + } + }, + "required": [ + "crossfilterEnabled", + "customText", + "facetFilters", + "refreshInterval", + "runQueriesOn" + ] + }, + "DocumentsV2PatchDraftResponse": { + "type": "object", + "properties": { "description": { "type": [ "string", "null" ], - "description": "Document description" - }, - "folder": { - "$ref": "#/components/schemas/InternalFolder" + "description": "Document description." }, - "hasDashboard": { - "type": "boolean", - "description": "Whether document has a dashboard" + "draftIdentifier": { + "type": "string", + "description": "Identifier of the draft the patch was applied to." }, "identifier": { "type": "string", - "description": "Document identifier" + "description": "Published document identifier the draft targets." + }, + "name": { + "type": "string", + "description": "Document name." + } + }, + "required": [ + "description", + "draftIdentifier", + "identifier", + "name" + ] + }, + "DocumentsV2CreateDraftBody": { + "allOf": [ + { + "$ref": "#/components/schemas/DocumentsV2PatchDraftBody" + }, + { + "type": "object", + "properties": { + "branchId": { + "type": "string", + "format": "uuid", + "description": "Branch the draft is created on. Omit for a draft on the main (unpublished) workspace." + } + }, + "additionalProperties": false + } + ] + }, + "DocumentsV2PatchDraftBody": { + "type": "object", + "properties": { + "containers": { + "allOf": [ + { + "$ref": "#/components/schemas/Containers" + }, + { + "description": "Container layout. When present, fully replaces the existing layout and disables automatic tile placement for the request." + } + ] }, - "labels": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Applied labels" + "controls": { + "$ref": "#/components/schemas/ControlsPatchExternal" }, - "lastViewedAt": { + "description": { "type": [ "string", "null" - ], - "format": "date-time", - "description": "Last time the dashboard was viewed" + ] }, - "updatedAt": { + "name": { + "type": "string", + "minLength": 1, + "maxLength": 254, + "description": "Document name." + }, + "queryPresentations": { + "$ref": "#/components/schemas/QueryPresentationsPatchExternal" + }, + "settings": { + "$ref": "#/components/schemas/SettingsPatchExternal" + }, + "summary": { + "type": "string", + "minLength": 1, + "maxLength": 255, + "description": "Caller-supplied description of what this patch changes, written to the history audit trail. When absent, the server generates one from the touched sections." + } + }, + "additionalProperties": false + }, + "DocumentsV2PublishDraftResponse": { + "type": "object", + "properties": { + "description": { "type": [ "string", "null" ], - "format": "date-time", - "description": "Last updated timestamp" + "description": "Document description." }, - "url": { + "identifier": { "type": "string", - "description": "URL to view the document. Returns dashboard URL if document has a dashboard, otherwise workbook URL.", - "example": "https://org.omni.co/dashboards/abc123" + "description": "Published document identifier." }, - "visits": { - "type": [ - "number", - "null" - ], - "description": "Number of dashboard visits" + "name": { + "type": "string", + "description": "Document name." } }, "required": [ - "name", - "owner", - "scope", - "connectionId", - "deleted", - "folder", - "hasDashboard", + "description", "identifier", - "updatedAt", - "url" + "name" ] }, - "DashboardsDownloadResponse": { + "EmbedSsoGenerateSessionResponse": { "type": "object", "properties": { - "job_id": { - "type": "string", - "format": "uuid", - "description": "ID of the download job. Use this to poll for download status.", - "example": "123e4567-e89b-12d3-a456-426614174000" - }, - "message": { + "sessionId": { "type": "string", - "description": "Status message", - "example": "Download initiated successfully" + "description": "Session ID to use for embedding Omni content" } }, "required": [ - "job_id", - "message" + "sessionId" ] }, - "DashboardsDownloadBody": { + "EmbedSsoGenerateSessionBody": { "type": "object", "properties": { - "enableFormatting": { - "type": "boolean", - "default": false, - "description": "Compatible with csv, xlsx & json formats. If true, formatting will be enabled in the output. Note: If true for json format, a queryIdentifierMapKey is required.", - "example": false - }, - "expandTablesToShowAllRows": { - "type": "boolean", - "description": "Compatible with pdf and png formats. If true, up to 1,000 rows in table visualizations will be included in the delivery. Note: This parameter cannot be used when paperFormat: fit_page.", - "example": false + "externalId": { + "type": "string", + "description": "External identifier for the user (from your system)", + "example": "user-123" }, - "filterConfig": { - "description": "An object specifying the filter conditions to apply to the task. The filter key specified must already exist in the dashboard.", - "example": { - "status": [ - "active", - "pending" - ] - } + "groups": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Optional list of group names to assign to the user", + "example": [ + "engineering", + "sales" + ] }, - "format": { + "name": { "type": "string", - "enum": [ - "pdf", - "png", - "csv", - "xlsx", - "json" - ], - "description": "Output format for the download: pdf, png, csv, xlsx, or json", - "example": "pdf" + "description": "Display name for the user", + "example": "John Doe" }, - "hideHiddenFields": { - "type": "boolean", - "default": false, - "description": "Compatible with csv & xlsx formats. If true, fields marked as hidden won't be displayed in the output.", - "example": false + "userAttributes": { + "type": "object", + "additionalProperties": {}, + "description": "Optional user attributes for row-level security" + } + }, + "required": [ + "externalId", + "name" + ] + }, + "EvalPromptSetsListResponse": { + "type": "object", + "properties": { + "prompt_sets": { + "type": "array", + "items": { + "$ref": "#/components/schemas/EvalPromptSetListItem" + }, + "description": "Prompt sets matching the query, sorted alphabetically by name." + } + }, + "required": [ + "prompt_sets" + ] + }, + "EvalPromptSetListItem": { + "type": "object", + "properties": { + "created_at": { + "type": [ + "string", + "null" + ], + "description": "ISO 8601 timestamp when the prompt set was created.", + "example": "2025-01-15T10:00:00.000Z" }, - "hideTitle": { - "type": "boolean", - "default": false, - "description": "Compatible with pdf & png formats. If true, the content's title will be hidden in the output.", - "example": false + "description": { + "type": [ + "string", + "null" + ], + "description": "Optional human-readable description of the prompt set.", + "example": "Regression suite for the orders topic" }, - "maxRowLimit": { - "type": "number", - "minimum": 1, - "description": "Compatible with csv, json, & xlsx formats. Used with overrideRowLimit. Specifies the maximum number of rows.", - "example": 1000 + "id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the prompt set.", + "example": "550e8400-e29b-41d4-a716-446655440000" }, - "overrideRowLimit": { + "is_archived": { "type": "boolean", - "default": false, - "description": "Compatible with csv, json, & xlsx formats. If true, the default row limit will be overridden. Note: If true for json and xlsx formats, a queryIdentifierMapKey is required.", + "description": "Whether the prompt set has been archived.", "example": false }, - "paperFormat": { + "model_id": { "type": "string", - "enum": [ - "a3", - "a4", - "fit_page", - "legal", - "letter", - "tabloid" - ], - "description": "Compatible with pdf formats. Defines the paper format (size) of the resulting PDF. Must be one of: a3, a4, letter, legal, fit_page, tabloid.", - "example": "letter" + "format": "uuid", + "description": "The shared model this prompt set is bound to.", + "example": "880e8400-e29b-41d4-a716-446655440003" }, - "paperOrientation": { + "name": { "type": "string", - "enum": [ - "portrait", - "landscape" - ], - "description": "Compatible with pdf formats. Defines the paper orientation of the resulting PDF. Must be one of: portrait, landscape.", - "example": "landscape" + "description": "Human-readable name for the prompt set.", + "example": "Orders regression" }, - "queryIdentifierMapKey": { + "slug": { "type": "string", - "description": "Required for single tile tasks. The ID of the query to include in a single tile task. Must reference a valid query in the dashboard.", - "example": "Jmn2r3KV" - }, - "showContentLink": { - "type": "boolean", - "default": true, - "description": "Compatible with all formats except link_only. If true, a link to the content will be shown in the output.", - "example": true + "description": "URL-safe identifier for the prompt set. Unique per `model_id`.", + "example": "orders-regression" }, - "showFilters": { - "type": "boolean", - "default": true, - "description": "Compatible with all formats except link_only & csv. If true, filters will be shown in the output.", - "example": true - }, - "singleColumnLayout": { - "type": "boolean", - "description": "Compatible with pdf and png formats. If true, dashboard tiles will be arranged into a single vertical column.", - "example": false + "updated_at": { + "type": [ + "string", + "null" + ], + "description": "ISO 8601 timestamp when the prompt set was last updated.", + "example": "2025-01-15T10:00:00.000Z" }, - "useCache": { - "type": "boolean", - "default": false, - "description": "If true, allow scheduled queries to use cached results instead of always running fresh queries.", - "example": false + "latest_run_at": { + "type": [ + "string", + "null" + ], + "description": "ISO 8601 timestamp of the most recent run on this prompt set, if any.", + "example": "2025-01-15T10:05:00.000Z" }, - "filename": { + "prompt_count": { + "type": "integer", + "description": "Number of prompts in the set.", + "example": 12 + } + }, + "required": [ + "created_at", + "description", + "id", + "is_archived", + "model_id", + "name", + "slug", + "updated_at", + "latest_run_at", + "prompt_count" + ] + }, + "EvalApiError400": { + "type": "object", + "properties": { + "detail": { "type": "string", - "minLength": 1, - "maxLength": 255, - "description": "Custom filename for the downloaded file (without extension)", - "example": "monthly-report" + "description": "Human-readable error message describing what went wrong.", + "example": "Bad Request: name: Required" + }, + "status": { + "type": "integer", + "description": "HTTP status code of the error.", + "example": 400 } }, "required": [ - "format" - ], - "additionalProperties": false + "detail", + "status" + ] }, - "DashboardFiltersResponse": { + "EvalApiError401": { "type": "object", "properties": { - "controls": { - "description": "Control configuration object. Keys are control IDs, values contain controlType, filterId, label, etc." - }, - "filterOrder": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Ordered list of filter IDs defining display order", - "example": [ - "filter_abc123", - "filter_def456" - ] - }, - "filters": { - "description": "Filter configuration object. Keys are filter IDs, values contain fieldName, viewName, kind, defaultValue, etc." - }, - "identifier": { + "detail": { "type": "string", - "description": "Dashboard identifier", - "example": "12db1a0a" + "description": "Human-readable error message describing what went wrong.", + "example": "Unauthorized: Missing or invalid API key" + }, + "status": { + "type": "integer", + "description": "HTTP status code of the error.", + "example": 401 } }, "required": [ - "filterOrder", - "identifier" + "detail", + "status" ] }, - "DashboardsUpdateFiltersBody": { + "EvalApiError403": { "type": "object", "properties": { - "clearExistingDraft": { - "type": "boolean", - "default": false, - "description": "When true, discards any existing draft before applying updates. Required when updating a published document that already has a draft." - }, - "controls": { - "type": "object", - "additionalProperties": { - "type": "object", - "properties": {}, - "additionalProperties": {} - }, - "description": "Partial control updates. Keys are control IDs that must exist in the dashboard." - }, - "filterOrder": { - "type": "array", - "items": { - "type": "string" - }, - "description": "New order for filters. All filter IDs must exist in the dashboard." + "detail": { + "type": "string", + "description": "Human-readable error message describing what went wrong.", + "example": "AI eval requires at least Querier access on the model" }, - "filters": { - "type": "object", - "additionalProperties": { - "type": "object", - "properties": {}, - "additionalProperties": {} - }, - "description": "Partial filter updates. Keys are filter IDs that must exist in the dashboard." + "status": { + "type": "integer", + "description": "HTTP status code of the error.", + "example": 403 } - } + }, + "required": [ + "detail", + "status" + ] }, - "DocumentsListResponse": { + "EvalApiError404": { "type": "object", "properties": { - "pageInfo": { - "allOf": [ - { - "$ref": "#/components/schemas/PageInfo" - }, - { - "description": "Pagination information" - } - ] + "detail": { + "type": "string", + "description": "Human-readable error message describing what went wrong.", + "example": "Prompt set not found" }, - "records": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Document" - }, - "description": "List of documents" + "status": { + "type": "integer", + "description": "HTTP status code of the error.", + "example": 404 } }, "required": [ - "pageInfo", - "records" + "detail", + "status" ] }, - "Document": { + "EvalPromptSetsCreateResponse": { "type": "object", "properties": { - "_count": { - "type": "object", - "properties": { - "favorites": { - "type": "number", - "description": "Number of users who favorited this document" - }, - "views": { - "type": "number", - "description": "Number of views" - } - }, - "required": [ - "favorites", - "views" + "prompt_set": { + "$ref": "#/components/schemas/EvalPromptSet" + } + }, + "required": [ + "prompt_set" + ] + }, + "EvalPromptSet": { + "type": "object", + "properties": { + "created_at": { + "type": [ + "string", + "null" ], - "description": "Document counts (included when _count is in include param)" - }, - "connectionId": { - "type": "string", - "description": "Connection ID the document is associated with" - }, - "deleted": { - "type": "boolean", - "description": "Whether the document is deleted (archived)" + "description": "ISO 8601 timestamp when the prompt set was created.", + "example": "2025-01-15T10:00:00.000Z" }, "description": { "type": [ "string", "null" ], - "description": "Document description" + "description": "Optional human-readable description of the prompt set.", + "example": "Regression suite for the orders topic" }, - "folder": { - "$ref": "#/components/schemas/DocumentFolder" + "id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the prompt set.", + "example": "550e8400-e29b-41d4-a716-446655440000" }, - "hasDashboard": { + "is_archived": { "type": "boolean", - "description": "Whether the document has an associated dashboard" + "description": "Whether the prompt set has been archived.", + "example": false }, - "identifier": { + "model_id": { "type": "string", - "description": "Document identifier", - "example": "abc123" + "format": "uuid", + "description": "The shared model this prompt set is bound to.", + "example": "880e8400-e29b-41d4-a716-446655440003" }, - "labels": { + "name": { + "type": "string", + "description": "Human-readable name for the prompt set.", + "example": "Orders regression" + }, + "prompts": { "type": "array", "items": { - "type": "string" + "$ref": "#/components/schemas/EvalPrompt" }, - "description": "Labels applied to the document (included when labels is in include param)" + "description": "Prompts that make up the set." }, - "name": { + "slug": { "type": "string", - "description": "Document name" + "description": "URL-safe identifier for the prompt set. Unique per `model_id`.", + "example": "orders-regression" }, - "owner": { - "$ref": "#/components/schemas/DocumentOwner" - }, - "scope": { - "type": "string", - "enum": [ - "restricted", - "organization" + "updated_at": { + "type": [ + "string", + "null" ], - "description": "Document access scope" - }, - "type": { - "type": "string", - "enum": [ - "document" + "description": "ISO 8601 timestamp when the prompt set was last updated.", + "example": "2025-01-15T10:00:00.000Z" + } + }, + "required": [ + "created_at", + "description", + "id", + "is_archived", + "model_id", + "name", + "prompts", + "slug", + "updated_at" + ] + }, + "EvalPrompt": { + "type": "object", + "properties": { + "created_at": { + "type": [ + "string", + "null" ], - "description": "Content type" + "description": "ISO 8601 timestamp when the prompt was created.", + "example": "2025-01-15T10:00:00.000Z" }, - "updatedAt": { + "expectation": { "type": [ "string", "null" ], - "format": "date-time", - "description": "Last updated timestamp" + "description": "The expectation the analysis judge scores the analysis against, or null when none was set.", + "example": "The top product by revenue should be Aniseed Syrup." }, - "url": { + "id": { "type": "string", - "description": "URL to view the document. Returns dashboard URL if document has a dashboard, otherwise workbook URL.", - "example": "https://org.omni.co/dashboards/abc123" + "format": "uuid", + "description": "Unique identifier for the prompt.", + "example": "770e8400-e29b-41d4-a716-446655440002" + }, + "prompt_text": { + "type": "string", + "description": "The natural language prompt text the AI is evaluated on.", + "example": "What are the top 5 products by revenue?" + }, + "updated_at": { + "type": [ + "string", + "null" + ], + "description": "ISO 8601 timestamp when the prompt was last updated.", + "example": "2025-01-15T10:00:00.000Z" } }, "required": [ - "connectionId", - "deleted", - "folder", - "hasDashboard", - "identifier", - "name", - "owner", - "scope", - "type", - "updatedAt", - "url" + "created_at", + "expectation", + "id", + "prompt_text", + "updated_at" ] }, - "DocumentFolder": { - "type": [ - "object", - "null" - ], + "EvalPromptSetsCreateBody": { + "type": "object", "properties": { - "id": { + "description": { + "type": [ + "string", + "null" + ], + "maxLength": 1024, + "description": "Optional human-readable description of the prompt set. Max 1024 characters.", + "example": "Regression suite for the orders topic" + }, + "model_id": { "type": "string", - "description": "Folder ID" + "format": "uuid", + "description": "The shared model this prompt set is bound to.", + "example": "880e8400-e29b-41d4-a716-446655440003" }, "name": { "type": "string", - "description": "Folder name" + "minLength": 1, + "maxLength": 255, + "description": "Human-readable name for the prompt set. 255 characters or fewer.", + "example": "Orders regression" }, - "path": { - "type": "string", - "description": "Folder path" + "prompts": { + "type": "array", + "items": { + "type": "object", + "properties": { + "expectation": { + "type": [ + "string", + "null" + ], + "maxLength": 16000, + "description": "Optional expectation the analysis judge scores the analysis against. Max 16000 characters.", + "example": "The top product by revenue should be Aniseed Syrup." + }, + "prompt_text": { + "type": "string", + "minLength": 1, + "maxLength": 8000, + "description": "The natural language prompt text. Max 8000 characters.", + "example": "What are the top 5 products by revenue?" + } + }, + "required": [ + "prompt_text" + ] + }, + "maxItems": 25, + "default": [], + "description": "Initial prompts for the set. Defaults to an empty list. At most 25 prompts." }, - "scope": { + "slug": { "type": "string", - "enum": [ - "restricted", - "organization" - ], - "description": "Folder access scope" + "maxLength": 255, + "pattern": "^[a-z][a-z0-9-]*$", + "description": "URL-safe identifier for the prompt set. Must be unique per `model_id` and match `^[a-z][a-z0-9-]*$`. Max 255 characters.", + "example": "orders-regression" } }, "required": [ - "id", + "model_id", "name", - "path", - "scope" - ], - "description": "Folder containing the document" + "slug" + ] }, - "DocumentOwner": { + "EvalPromptSetsGetResponse": { "type": "object", "properties": { - "id": { - "type": "string", - "description": "Owner membership ID" - }, - "name": { - "type": "string", - "description": "Owner display name" + "prompt_set": { + "$ref": "#/components/schemas/EvalPromptSet" } }, "required": [ - "id", - "name" - ], - "description": "Document owner" + "prompt_set" + ] }, - "DocumentsCreateResponse": { + "EvalPromptSetsUpdateResponse": { "type": "object", "properties": { - "dashboard": { - "type": "object", - "properties": { - "dashboardId": { - "type": "string", - "description": "Dashboard ID" - }, - "id": { - "type": "string", - "description": "Dashboard ID" - } - }, - "required": [ - "dashboardId", - "id" - ], - "additionalProperties": {}, - "description": "Created dashboard" - }, - "workbook": { - "type": "object", - "properties": { - "documentId": { - "type": "string", - "description": "Document ID (deprecated)" - }, - "id": { - "type": "string", - "description": "Workbook ID" - } - }, - "required": [ - "documentId", - "id" - ], - "additionalProperties": {}, - "description": "Created workbook" + "prompt_set": { + "$ref": "#/components/schemas/EvalPromptSet" } }, "required": [ - "dashboard", - "workbook" + "prompt_set" ] }, - "DocumentsCreateBody": { + "EvalApiError422": { "type": "object", "properties": { - "branchId": { + "detail": { "type": "string", - "format": "uuid", - "description": "Optional branch ID to associate the document with a model branch", - "example": "123e4567-e89b-12d3-a456-426614174001" + "description": "Human-readable error message describing what went wrong.", + "example": "A prompt being updated does not belong to this prompt set" }, + "status": { + "type": "integer", + "description": "HTTP status code of the error.", + "example": 422 + } + }, + "required": [ + "detail", + "status" + ] + }, + "EvalPromptSetsUpdateBody": { + "type": "object", + "properties": { "description": { "type": [ "string", "null" ], - "description": "Document description" - }, - "facetFilters": { - "type": "boolean", - "description": "Enable facet filters on the dashboard" - }, - "filterConfig": { - "description": "Dashboard filter configuration" - }, - "filterOrder": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Order of filters in the dashboard" - }, - "identifier": { - "$ref": "#/components/schemas/DocumentIdentifier" - }, - "metadata": { - "description": "Dashboard metadata" - }, - "metadataVersion": { - "type": "string", - "description": "Dashboard metadata version (required when metadata is provided)" - }, - "modelId": { - "type": "string", - "description": "Shared model ID to base the document on" + "maxLength": 1024, + "description": "New description for the prompt set. Pass `null` to clear. Max 1024 characters." }, "name": { "type": "string", - "description": "Document name" + "minLength": 1, + "maxLength": 255, + "description": "New human-readable name for the prompt set. 255 characters or fewer." }, - "queryPresentations": { + "prompts": { "type": "array", "items": { "type": "object", "properties": { - "aiConfig": { - "description": "AI configuration" - }, - "chartType": { + "expectation": { "type": [ "string", "null" ], - "description": "Chart type" - }, - "description": { - "type": "string", - "description": "Query presentation description" - }, - "name": { - "type": "string", - "description": "Query presentation name" - }, - "prefersChart": { - "type": "boolean", - "description": "Whether to prefer chart view" - }, - "query": { - "type": "object", - "properties": { - "fields": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Query fields" - }, - "table": { - "type": "string", - "description": "Query table/topic" - } - }, - "required": [ - "fields", - "table" - ], - "additionalProperties": {}, - "description": "Query definition" - }, - "resultConfig": { - "description": "Result configuration" + "maxLength": 16000, + "description": "Optional expectation the analysis judge scores the analysis against. Pass `null` to clear. Max 16000 characters.", + "example": "The top product by revenue should be Aniseed Syrup." }, - "subTitle": { + "id": { "type": "string", - "description": "Subtitle" + "format": "uuid", + "description": "Existing prompt id. When provided, updates that prompt; when omitted, a new prompt is created. Prompts not included in this list are removed." }, - "topicName": { + "prompt_text": { "type": "string", - "description": "Topic name" - }, - "visConfig": { - "$ref": "#/components/schemas/ApiVisConfig" + "minLength": 1, + "maxLength": 8000, + "description": "Updated or new prompt text. Max 8000 characters.", + "example": "What are the top 10 products by revenue this quarter?" } }, "required": [ - "name", - "query" + "prompt_text" ] }, - "description": "Query presentations for the document" + "maxItems": 25, + "description": "Full desired set of prompts after the update. Prompts omitted from this list are deleted; new prompts (no `id`) are appended in body order. Existing prompts retain their original position — reordering is not supported on this endpoint. At most 25 prompts total." + } + } + }, + "EvalPromptSetsDeleteResponse": { + "type": "object", + "properties": { + "cancelled_job_count": { + "type": "integer", + "description": "Number of in-flight agentic jobs associated with this prompt set that were cancelled as part of the archive.", + "example": 0 + }, + "is_archived": { + "type": "boolean", + "enum": [ + true + ], + "description": "Always `true` on success — archives the prompt set." } }, "required": [ - "modelId", - "name" + "cancelled_job_count", + "is_archived" ] }, - "DocumentIdentifier": { - "type": "string", - "minLength": 2, - "maxLength": 48, - "description": "Optional document identifier. If omitted, an identifier is auto-generated. Must be unique within the organization." + "EvalApiError500": { + "type": "object", + "properties": { + "detail": { + "type": "string", + "description": "Human-readable error message describing what went wrong.", + "example": "Archive committed but a run-cancellation failed; retry to complete" + }, + "status": { + "type": "integer", + "description": "HTTP status code of the error.", + "example": 500 + } + }, + "required": [ + "detail", + "status" + ] }, - "ApiVisConfig": { + "EvalPromptSetsUnarchiveResponse": { "type": "object", "properties": { - "config": { - "type": "object", - "additionalProperties": {}, - "description": "Visualization spec (chart configuration)" + "prompt_set": { + "$ref": "#/components/schemas/EvalPromptSet" + } + }, + "required": [ + "prompt_set" + ] + }, + "EvalRunsListResponse": { + "type": "object", + "properties": { + "runs": { + "type": "array", + "items": { + "$ref": "#/components/schemas/EvalRunListItem" + }, + "description": "Runs for the prompt set, newest first, filtered to those whose model the caller can access." + } + }, + "required": [ + "runs" + ] + }, + "EvalRunListItem": { + "type": "object", + "properties": { + "branch_id": { + "type": [ + "string", + "null" + ], + "format": "uuid", + "description": "Optional branch ID the run was executed against. Null when run against the main shared model.", + "example": null }, - "fields": { + "branch_name": { "type": [ - "array", + "string", "null" ], - "items": { - "type": "string", - "minLength": 1 - }, - "description": "Field names used in the visualization" + "description": "Display name for the branch, if `branch_id` is set.", + "example": null }, - "visType": { - "type": "string", - "enum": [ - "vegalite", - "omni-ai-summary-markdown", - "basic", - "omni-kpi", - "map", - "omni-markdown", - "funnel", - "sankey", - "single-record", - "svg-map", - "omni-spreadsheet", - "spreadsheet-tab", - "summary-value", - "omni-table", - "app" + "completed_at": { + "type": [ + "string", + "null" ], - "description": "Visualization type (e.g. basic, omni-markdown, omni-table)" - } - }, - "additionalProperties": {}, - "description": "Visualization configuration" - }, - "DocumentsGetResponse": { - "type": "object", - "properties": { + "description": "ISO 8601 timestamp when the run reached a terminal state.", + "example": null + }, + "created_at": { + "type": [ + "string", + "null" + ], + "description": "ISO 8601 timestamp when the run was created.", + "example": "2025-01-15T10:00:00.000Z" + }, "description": { "type": [ "string", "null" ], - "description": "Document description" + "description": "Optional human-readable description for the run.", + "example": null }, - "documentMetadata": { - "description": "Document metadata" + "id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the run.", + "example": "660e8400-e29b-41d4-a716-446655440001" }, - "facetFilters": { + "is_archived": { "type": "boolean", - "description": "Whether facet filters are enabled" - }, - "filterConfig": { - "description": "Dashboard filter configuration" - }, - "filterOrder": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Order of filters" + "description": "Whether the run has been archived.", + "example": false }, - "modelId": { + "model_id": { "type": "string", - "description": "Model ID" + "format": "uuid", + "description": "The shared model this run was executed against.", + "example": "880e8400-e29b-41d4-a716-446655440003" }, - "name": { + "prompt_set_id": { "type": "string", - "description": "Document name" + "format": "uuid", + "description": "The prompt set this run was created from.", + "example": "550e8400-e29b-41d4-a716-446655440000" }, - "queryPresentations": { - "type": "array", - "items": {}, - "description": "Query presentations" + "run_number": { + "type": "integer", + "description": "Sequential, per-prompt-set run number.", + "example": 3 }, - "refreshInterval": { - "type": [ - "number", - "null" + "stats": { + "$ref": "#/components/schemas/EvalRunStats" + }, + "status": { + "type": "string", + "enum": [ + "RUNNING", + "COMPLETE", + "CANCELLED" ], - "description": "Auto-refresh interval in seconds" + "description": "Run-level lifecycle. Flips to a terminal state (COMPLETE or CANCELLED) exactly once.", + "example": "RUNNING" } }, "required": [ - "facetFilters", - "filterOrder", - "modelId", - "name", - "queryPresentations", - "refreshInterval" + "branch_id", + "branch_name", + "completed_at", + "created_at", + "description", + "id", + "is_archived", + "model_id", + "prompt_set_id", + "run_number", + "stats", + "status" ] }, - "DocumentsPutResponse": { + "EvalRunStats": { "type": "object", "properties": { - "description": { - "type": [ - "string", - "null" - ], - "description": "Document description" + "terminal": { + "type": "integer", + "description": "Number of per-prompt jobs that have reached a terminal state (COMPLETE, FAILED, or CANCELLED).", + "example": 8 }, - "identifier": { - "type": "string", - "description": "Document identifier" + "total": { + "type": "integer", + "description": "Total number of per-prompt jobs in the run.", + "example": 12 + } + }, + "required": [ + "terminal", + "total" + ] + }, + "EvalRunsCreateResponse": { + "type": "object", + "properties": { + "job_count": { + "type": "integer", + "description": "Number of per-prompt agentic jobs created for this run (one per prompt that fanned out successfully). Enqueue onto the work queue happens after creation and is best-effort, so this count reflects jobs created, not necessarily those successfully enqueued.", + "example": 12 }, - "name": { - "type": "string", - "description": "Updated document name" + "run": { + "$ref": "#/components/schemas/EvalRunDetail" } }, "required": [ - "identifier", - "name" + "job_count", + "run" ] }, - "DocumentsPutBody": { + "EvalRunDetail": { "type": "object", "properties": { - "clearExistingDraft": { - "type": "boolean", - "default": false, - "description": "Clear existing draft before updating (for published documents with drafts)" + "branch_id": { + "type": [ + "string", + "null" + ], + "format": "uuid", + "description": "Optional branch ID the run was executed against. Null when run against the main shared model.", + "example": null + }, + "branch_name": { + "type": [ + "string", + "null" + ], + "description": "Display name for the branch, if `branch_id` is set.", + "example": null + }, + "completed_at": { + "type": [ + "string", + "null" + ], + "description": "ISO 8601 timestamp when the run reached a terminal state.", + "example": null + }, + "created_at": { + "type": [ + "string", + "null" + ], + "description": "ISO 8601 timestamp when the run was created.", + "example": "2025-01-15T10:00:00.000Z" }, "description": { "type": [ "string", "null" ], - "description": "Document description" + "description": "Optional human-readable description for the run.", + "example": null }, - "documentMetadata": { - "description": "Document presentation metadata" + "id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the run.", + "example": "660e8400-e29b-41d4-a716-446655440001" }, - "facetFilters": { + "is_archived": { "type": "boolean", - "description": "Enable facet filters" + "description": "Whether the run has been archived.", + "example": false }, - "filterConfig": { - "description": "Filter configuration" + "model_id": { + "type": "string", + "format": "uuid", + "description": "The shared model this run was executed against.", + "example": "880e8400-e29b-41d4-a716-446655440003" }, - "filterOrder": { + "prompt_set_id": { + "type": "string", + "format": "uuid", + "description": "The prompt set this run was created from.", + "example": "550e8400-e29b-41d4-a716-446655440000" + }, + "results": { "type": "array", "items": { - "type": "string" + "$ref": "#/components/schemas/EvalRunResult" }, - "description": "Order of filters" + "description": "Per-prompt results for this run, ordered by their creation order in the prompt set." }, - "modelId": { + "run_number": { + "type": "integer", + "description": "Sequential, per-prompt-set run number.", + "example": 3 + }, + "status": { "type": "string", - "description": "Model ID" + "enum": [ + "RUNNING", + "COMPLETE", + "CANCELLED" + ], + "description": "Run-level lifecycle. Flips to a terminal state (COMPLETE or CANCELLED) exactly once.", + "example": "RUNNING" + } + }, + "required": [ + "branch_id", + "branch_name", + "completed_at", + "created_at", + "description", + "id", + "is_archived", + "model_id", + "prompt_set_id", + "results", + "run_number", + "status" + ], + "description": "The newly created run with its initial results." + }, + "EvalRunResult": { + "type": "object", + "properties": { + "agentic_job": { + "$ref": "#/components/schemas/EvalRunResultAgenticJob" }, - "name": { + "cost": { + "type": [ + "number", + "null" + ], + "description": "Total LLM cost (USD) for this prompt, if available.", + "example": 0.0021 + }, + "error_reason": { + "type": [ + "string", + "null" + ], + "description": "Failure reason string for prompts whose underlying job failed.", + "example": null + }, + "expectation": { + "type": [ + "string", + "null" + ], + "description": "The prompt's expectation as of run creation (snapshotted, so later prompt edits don't change past runs), or null when none was set. The analysis judge scores the analysis against it.", + "example": "The top product by revenue should be Aniseed Syrup." + }, + "id": { "type": "string", - "minLength": 1, - "maxLength": 254, - "description": "Document name" + "format": "uuid", + "description": "Unique identifier for the run result row.", + "example": "aa0e8400-e29b-41d4-a716-446655440005" }, - "queryPresentations": { - "type": "array", - "items": { - "$ref": "#/components/schemas/DocumentsPutQueryPresentation" - }, - "minItems": 1, - "description": "Query presentations (full replacement)" + "prompt": { + "type": "string", + "description": "The prompt text that was evaluated.", + "example": "What are the top 5 products by revenue?" }, - "refreshInterval": { + "score": { + "type": [ + "number", + "null" + ], + "description": "Numeric judge score for this prompt result, if scoring ran.", + "example": 0.9 + }, + "scoring_cost": { + "type": [ + "number", + "null" + ], + "description": "Total LLM cost (USD) for scoring this prompt result.", + "example": 0.0004 + }, + "timing_ms": { "type": [ "integer", "null" ], - "minimum": 60, - "description": "Auto-refresh interval in seconds" + "description": "Wall-clock duration of the underlying job in milliseconds.", + "example": 4321 } }, "required": [ - "facetFilters", - "filterOrder", - "modelId", - "name", - "queryPresentations", - "refreshInterval" + "agentic_job", + "cost", + "error_reason", + "expectation", + "id", + "prompt", + "score", + "scoring_cost", + "timing_ms" ] }, - "DocumentsPutQueryPresentation": { + "EvalRunResultAgenticJob": { "type": "object", "properties": { - "aiConfig": { - "type": "object", - "properties": { - "description": { - "type": "object", - "properties": { - "aiContext": { - "type": "string" - }, - "enabled": { - "type": "boolean" - } - } - }, - "subTitle": { - "type": "object", - "properties": { - "aiContext": { - "type": "string" - }, - "enabled": { - "type": "boolean" - } - } - } - }, - "description": "AI configuration" - }, - "chartType": { + "conversation_id": { "type": [ "string", "null" ], - "enum": [ - "auto", - "area", - "areaStacked", - "areaStackedPercentage", - "bar", - "barLine", - "barGrouped", - "barStacked", - "barStackedPercentage", - "boxplot", - "code", - "column", - "columnGrouped", - "columnStacked", - "columnStackedPercentage", - "heatmap", - "kpi", - "line", - "lineColor", - "map", - "regionMap", - "markdown", - "omni-ai-summary-markdown", - "pie", - "funnel", - "sankey", - "point", - "pointColor", - "pointSize", - "pointSizeColor", - "singleRecord", - "omni-spreadsheet", - "summaryValue", - "svgMap", - "table", - null - ], - "description": "Chart type" + "format": "uuid", + "description": "Conversation the agentic job belongs to.", + "example": "770e8400-e29b-41d4-a716-446655440002" }, - "description": { + "id": { "type": "string", - "description": "Description" + "format": "uuid", + "description": "Agentic job identifier.", + "example": "990e8400-e29b-41d4-a716-446655440004" }, - "name": { + "state": { "type": "string", - "description": "Query presentation name" - }, - "prefersChart": { - "type": "boolean", - "description": "Whether to prefer chart view" - }, - "query": { - "description": "Query definition" - }, - "resultConfig": { - "description": "Result config" - }, - "subTitle": { + "enum": [ + "CANCELLED", + "COMPLETE", + "DELIVERING", + "EXECUTING", + "FAILED", + "QUEUED" + ], + "description": "Current state of the agentic job that ran this prompt.", + "example": "COMPLETE" + } + }, + "required": [ + "conversation_id", + "id", + "state" + ] + }, + "EvalApiError429": { + "type": "object", + "properties": { + "detail": { "type": "string", - "description": "Subtitle" + "description": "Human-readable error message describing what went wrong.", + "example": "Too many active runs; wait for an in-flight run to finish" }, - "topicName": { + "status": { + "type": "integer", + "description": "HTTP status code of the error.", + "example": 429 + } + }, + "required": [ + "detail", + "status" + ] + }, + "EvalApiError503": { + "type": "object", + "properties": { + "detail": { "type": "string", - "description": "Topic name" + "description": "Human-readable error message describing what went wrong.", + "example": "AI eval is paused for this organization" }, - "visConfig": { - "$ref": "#/components/schemas/ApiVisConfig" + "status": { + "type": "integer", + "description": "HTTP status code of the error.", + "example": 503 } }, "required": [ - "name" + "detail", + "status" ] }, - "DocumentsUpdateResponse": { + "EvalRunsCreateBody": { "type": "object", "properties": { "description": { @@ -2557,4053 +25154,4320 @@ "string", "null" ], - "description": "Document description" + "maxLength": 1024, + "description": "Optional human-readable description for the run. Pass `null` to clear (or omit). Max 1024 characters.", + "example": "Re-running after switching to gpt-4o for query generation" }, - "identifier": { + "prompt_set_id": { "type": "string", - "description": "Document identifier" + "format": "uuid", + "description": "The prompt set to execute.", + "example": "550e8400-e29b-41d4-a716-446655440000" }, - "name": { - "type": "string", - "description": "Updated document name" + "run_config": { + "type": "object", + "properties": { + "branch_id": { + "type": "string", + "format": "uuid", + "description": "Optional branch ID to run against. Must be a branch of the prompt set's model.", + "example": "440e8400-e29b-41d4-a716-446655440006" + } + }, + "description": "Per-run configuration. Optional — omit if no overrides." } }, "required": [ - "identifier", - "name" + "prompt_set_id" ] }, - "DocumentsUpdateBody": { + "EvalRunsGetResponse": { "type": "object", "properties": { - "clearExistingDraft": { + "run": { + "$ref": "#/components/schemas/EvalRunDetail" + } + }, + "required": [ + "run" + ] + }, + "EvalRunsDeleteResponse": { + "type": "object", + "properties": { + "is_archived": { "type": "boolean", - "default": false, - "description": "Clear existing draft before updating (for published documents with drafts)" - }, - "description": { - "type": [ - "string", - "null" + "enum": [ + true ], - "description": "Document description" + "description": "Always `true` on success — the run has been archived." + } + }, + "required": [ + "is_archived" + ] + }, + "EvalRunsCancelResponse": { + "type": "object", + "properties": { + "cancelled": { + "type": "integer", + "description": "Number of per-prompt agentic jobs that were cancelled by this request.", + "example": 4 }, - "identifier": { + "run": { "allOf": [ { - "$ref": "#/components/schemas/DocumentIdentifier" + "$ref": "#/components/schemas/EvalRunDetail" }, { - "description": "New identifier for the document. Must be unique within the organization. The previous identifier is retained in the document identifier history and continues to redirect." + "description": "The cancelled run. `status: CANCELLED` and `is_archived: true` after this call." } ] }, - "name": { - "type": "string", - "minLength": 1, - "maxLength": 254, - "description": "New document name" + "total": { + "type": "integer", + "description": "Total number of per-prompt jobs in the run.", + "example": 12 } - } + }, + "required": [ + "cancelled", + "run", + "total" + ] }, - "SuccessResponse": { + "EvalRunsUnarchiveResponse": { "type": "object", "properties": { - "success": { + "is_archived": { "type": "boolean", - "description": "Whether the operation was successful", - "example": true + "enum": [ + false + ], + "description": "Always `false` on success — the run has been unarchived." } }, "required": [ - "success" + "is_archived" ] }, - "DocumentsGetQueriesResponse": { + "FoldersListResponse": { "type": "object", "properties": { - "queries": { + "pageInfo": { + "allOf": [ + { + "$ref": "#/components/schemas/PageInfo" + }, + { + "description": "Pagination information" + } + ] + }, + "records": { "type": "array", "items": { "type": "object", "properties": { + "_count": { + "type": "object", + "properties": { + "documents": { + "type": "number", + "description": "Number of documents in the folder" + }, + "favorites": { + "type": "number", + "description": "Number of users who have favorited this folder" + } + }, + "required": [ + "documents", + "favorites" + ], + "description": "Count statistics for the folder" + }, "id": { "type": "string", - "description": "Query presentation ID" + "format": "uuid", + "description": "Unique folder identifier" + }, + "labels": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Labels associated with the folder" }, "name": { "type": "string", - "description": "Query presentation name" + "description": "Name of the folder", + "example": "My Reports" }, - "query": { - "description": "Query JSON definition" + "ownerId": { + "type": "string", + "format": "uuid", + "description": "User ID of the folder owner" }, - "queryIdentifierMapKey": { + "path": { "type": "string", - "description": "Key in the query identifier map" + "description": "Full path to the folder", + "example": "/shared/reports/my-reports" }, "url": { "type": "string", - "description": "URL to view this specific query/sheet in the workbook.", - "example": "https://org.omni.co/w/abc123?key=1" + "description": "URL to view the folder in the Omni UI.", + "example": "https://org.omni.co/f/my-reports" } }, "required": [ "id", "name", - "queryIdentifierMapKey", + "ownerId", + "path", "url" ] }, - "description": "List of queries in the document" + "description": "List of folders" } }, "required": [ - "queries" + "pageInfo", + "records" ] }, - "DocumentsMoveBody": { + "FoldersCreateResponse": { "type": "object", "properties": { - "folderPath": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "Destination folder path (null for root)" - }, - "scope": { + "id": { "type": "string", - "enum": [ - "restricted", - "organization" - ], - "description": "Access scope for the document" - } - }, - "required": [ - "folderPath" - ] - }, - "DocumentsGetPermissionsResponse": { - "type": "object", - "properties": { - "permits": { - "description": "User permits for the document" - } - } - }, - "DocumentsUpdatePermissionSettingsBody": { - "type": "object", - "properties": { - "canDownload": { - "type": "boolean", - "description": "Allow downloading" - }, - "canDrill": { - "type": "boolean", - "description": "Allow drill-down" - }, - "canSchedule": { - "type": "boolean", - "description": "Allow scheduling" - }, - "canUpload": { - "type": "boolean", - "description": "Allow uploads" - }, - "canUseDashboardAi": { - "type": "boolean", - "description": "Allow using dashboard AI" - }, - "canViewWorkbook": { - "type": "boolean", - "description": "Allow viewing workbook" + "format": "uuid", + "description": "ID of the created folder" }, - "organizationAccessBoost": { - "type": "boolean", - "description": "Boost organization access" + "name": { + "type": "string", + "description": "Name of the created folder" }, - "organizationRole": { + "ownerId": { "type": "string", - "enum": [ - "viewer", - "editor", - "manager", - "no_access" - ], - "description": "Organization-wide role for the document" + "format": "uuid", + "description": "User ID of the folder owner" }, - "requirePullRequestToPublish": { - "type": "boolean", - "description": "Require pull request to publish changes" - } - } - }, - "DocumentsAddPermitsBody": { - "type": "object", - "properties": { - "accessBoost": { - "type": "boolean", - "default": false, - "description": "Grant access boost" + "path": { + "type": "string", + "description": "Full path to the folder" }, - "role": { + "scope": { "type": "string", "enum": [ - "NO_ACCESS", - "VIEWER", - "EXPLORER", - "EDITOR", - "MANAGER" + "organization", + "restricted" ], - "description": "Role to grant" - }, - "userGroupIds": { - "type": "array", - "items": { - "type": "string" - }, - "default": [], - "description": "User group IDs to grant access to" - }, - "userIds": { - "type": "array", - "items": { - "type": "string", - "format": "uuid" - }, - "default": [], - "description": "User membership IDs to grant access to" + "description": "Share scope of the folder" } }, "required": [ - "role" + "id", + "name", + "ownerId", + "path", + "scope" ] }, - "DocumentsUpdatePermitsBody": { + "FoldersCreateBody": { "type": "object", "properties": { - "accessBoost": { - "type": "boolean", - "description": "Access boost setting" + "name": { + "type": "string", + "minLength": 1, + "description": "Name of the folder to create", + "example": "My New Folder" }, - "role": { + "parentFolderId": { + "type": "string", + "format": "uuid", + "description": "Parent folder ID (omit to create at root level)" + }, + "scope": { "type": "string", "enum": [ - "NO_ACCESS", - "VIEWER", - "EXPLORER", - "EDITOR", - "MANAGER" + "organization", + "restricted" ], - "description": "Role to set" - }, - "userGroupIds": { - "type": "array", - "items": { - "type": "string" - }, - "default": [], - "description": "User group IDs to update" - }, - "userIds": { - "type": "array", - "items": { - "type": "string", - "format": "uuid" - }, - "default": [], - "description": "User membership IDs to update" - } - } - }, - "DocumentsRevokePermitsBody": { - "type": "object", - "properties": { - "userGroupIds": { - "type": "array", - "items": { - "type": "string" - }, - "default": [], - "description": "User group IDs to revoke access from" + "description": "Share scope for the folder" }, - "userIds": { - "type": "array", - "items": { - "type": "string", - "format": "uuid" - }, - "default": [], - "description": "User membership IDs to revoke access from" - } - } - }, - "DocumentsCreateDraftResponse": { - "type": "object", - "properties": { - "identifier": { + "userId": { "type": "string", - "description": "Draft document identifier" + "format": "uuid", + "description": "User ID to create the folder as (for org-scoped API keys only)" } }, "required": [ - "identifier" + "name" ] }, - "DocumentsCreateDraftBody": { - "type": "object", - "properties": { - "branchId": { - "type": "string", - "format": "uuid", - "description": "Branch ID for the draft" - } - } - }, - "DocumentsDiscardDraftResponse": { + "FoldersDeleteResponse": { "type": "object", "properties": { - "message": { - "type": "string", - "description": "Success message" + "success": { + "type": "boolean", + "description": "Whether the folder was deleted successfully" } }, "required": [ - "message" + "success" ] }, - "DocumentsDiscardDraftBody": { - "type": "object", - "properties": { - "branchId": { - "type": "string", - "format": "uuid", - "description": "Branch ID for the draft" - } - } - }, - "DocumentsDuplicateResponse": { + "FoldersUpdateResponse": { "type": "object", "properties": { - "dashboardId": { - "type": "string", - "description": "New dashboard ID" - }, - "identifier": { + "id": { "type": "string", - "description": "New document identifier" + "format": "uuid", + "description": "Folder ID" }, "name": { "type": "string", - "description": "Document name" + "description": "Updated folder name" }, - "workbookId": { + "path": { "type": "string", - "description": "New workbook ID" + "description": "Updated URL path segment for the folder (the folder's own segment only)" } }, "required": [ - "dashboardId", - "identifier", + "id", "name", - "workbookId" + "path" ] }, - "DocumentsDuplicateBody": { + "FoldersUpdateBody": { "type": "object", "properties": { - "folderPath": { - "type": [ - "string", - "null" - ], - "description": "Destination folder path (null for root)" - }, "name": { "type": "string", "minLength": 1, - "maxLength": 254, - "description": "Name for the duplicated document" + "description": "New display name for the folder", + "example": "Q1 Reports" }, - "scope": { + "path": { "type": "string", - "enum": [ - "restricted", - "organization" - ], - "description": "Access scope for the duplicated document" + "minLength": 1, + "pattern": "^[a-zA-Z0-9-]+$", + "description": "New URL path segment for the folder (alphanumeric and dashes only). This is only the folder's own segment, not the full hierarchical path.", + "example": "q1-reports" + }, + "resolvePathConflict": { + "type": "boolean", + "default": false, + "description": "When true, automatically resolves path collisions with existing folders by appending a numeric suffix (e.g., my-path-1). When false (default), returns 409 Conflict if the path is already taken. Does not apply to reserved paths, which are always rejected with 400." } - }, - "required": [ - "name" - ] + } }, - "DocumentsBulkUpdateLabelsResponse": { + "FoldersGetPermissionsResponse": { "type": "object", "properties": { - "labels": { + "permits": { "type": "array", "items": { - "type": "string" + "type": "object", + "properties": { + "accessBoost": { + "type": "boolean", + "description": "Whether access boost is enabled for this permit" + }, + "role": { + "type": "string", + "description": "Content role (e.g., VIEWER, EDITOR, MANAGER)", + "example": "VIEWER" + }, + "userGroupId": { + "type": "string", + "description": "User group ID if this is a group permit" + }, + "userId": { + "type": "string", + "format": "uuid", + "description": "User ID if this is a user permit" + } + }, + "required": [ + "role" + ] }, - "description": "Updated list of labels on the document" + "description": "List of permission permits for the folder" } }, "required": [ - "labels" + "permits" ] }, - "DocumentsBulkUpdateLabelsBody": { + "FoldersAddPermissionsResponse": { "type": "object", "properties": { - "add": { + "success": { + "type": "boolean", + "description": "Whether the permissions were added successfully" + } + }, + "required": [ + "success" + ] + }, + "FoldersAddPermissionsBody": { + "type": "object", + "properties": { + "accessBoost": { + "type": "boolean", + "default": false, + "description": "Whether to grant access boost" + }, + "role": { + "type": "string", + "enum": [ + "NO_ACCESS", + "VIEWER", + "EXPLORER", + "EDITOR", + "MANAGER" + ], + "description": "Content role to assign (VIEWER, EDITOR, or MANAGER)", + "example": "VIEWER" + }, + "userGroupIds": { "type": "array", "items": { "type": "string" }, "default": [], - "description": "Labels to add" + "description": "User group IDs to grant permission to" }, - "remove": { + "userIds": { "type": "array", "items": { - "type": "string" + "type": "string", + "format": "uuid" }, "default": [], - "description": "Labels to remove" + "description": "User IDs to grant permission to" } - } + }, + "required": [ + "role" + ], + "additionalProperties": false }, - "DocumentsTransferOwnershipBody": { + "FoldersUpdatePermissionsResponse": { "type": "object", "properties": { - "userId": { - "type": "string", - "format": "uuid", - "description": "Membership ID of the new owner" + "success": { + "type": "boolean", + "description": "Whether the permissions were updated successfully" } }, "required": [ - "userId" + "success" ] }, - "DocumentsAccessListResponse": { + "FoldersUpdatePermissionsBody": { "type": "object", "properties": { - "pageInfo": { - "allOf": [ - { - "$ref": "#/components/schemas/PageInfo" - }, - { - "description": "Pagination information" - } - ] + "accessBoost": { + "type": "boolean", + "description": "Whether to grant access boost" }, - "principals": { + "role": { + "type": "string", + "enum": [ + "NO_ACCESS", + "VIEWER", + "EXPLORER", + "EDITOR", + "MANAGER" + ], + "description": "New content role to assign" + }, + "userGroupIds": { "type": "array", - "items": {}, - "description": "List of users and groups with access" + "items": { + "type": "string" + }, + "default": [], + "description": "User group IDs to update permissions for" + }, + "userIds": { + "type": "array", + "items": { + "type": "string", + "format": "uuid" + }, + "default": [], + "description": "User IDs to update permissions for" } }, - "required": [ - "pageInfo", - "principals" - ] + "additionalProperties": false }, - "EmbedSsoGenerateSessionResponse": { + "FoldersRevokePermissionsResponse": { "type": "object", "properties": { - "sessionId": { - "type": "string", - "description": "Session ID to use for embedding Omni content" + "success": { + "type": "boolean", + "description": "Whether the permissions were revoked successfully" } }, "required": [ - "sessionId" + "success" ] }, - "EmbedSsoGenerateSessionBody": { + "FoldersRevokePermissionsBody": { "type": "object", "properties": { - "externalId": { - "type": "string", - "description": "External identifier for the user (from your system)", - "example": "user-123" - }, - "groups": { + "userGroupIds": { "type": "array", "items": { "type": "string" }, - "description": "Optional list of group names to assign to the user", - "example": [ - "engineering", - "sales" - ] - }, - "name": { - "type": "string", - "description": "Display name for the user", - "example": "John Doe" + "default": [], + "description": "User group IDs to revoke permissions from" }, - "userAttributes": { - "type": "object", - "additionalProperties": {}, - "description": "Optional user attributes for row-level security" + "userIds": { + "type": "array", + "items": { + "type": "string", + "format": "uuid" + }, + "default": [], + "description": "User IDs to revoke permissions from" } }, - "required": [ - "externalId", - "name" - ] + "additionalProperties": false }, - "FoldersListResponse": { + "LabelsListResponse": { "type": "object", - "properties": { - "pageInfo": { - "allOf": [ - { - "$ref": "#/components/schemas/PageInfo" - }, - { - "description": "Pagination information" - } - ] - }, - "records": { + "properties": { + "labels": { "type": "array", "items": { "type": "object", "properties": { - "_count": { - "type": "object", - "properties": { - "documents": { - "type": "number", - "description": "Number of documents in the folder" - }, - "favorites": { - "type": "number", - "description": "Number of users who have favorited this folder" - } - }, - "required": [ - "documents", - "favorites" + "color": { + "type": [ + "string", + "null" ], - "description": "Count statistics for the folder" + "maxLength": 9, + "description": "Hex color for the label (e.g. #0366d6)", + "example": "#0366d6" }, - "id": { - "type": "string", - "format": "uuid", - "description": "Unique folder identifier" + "description": { + "type": [ + "string", + "null" + ], + "maxLength": 500, + "description": "Label description", + "example": "Important items that need attention" }, - "labels": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Labels associated with the folder" + "homepage": { + "type": "boolean", + "description": "Whether label is shown on homepage" }, "name": { "type": "string", - "description": "Name of the folder", - "example": "My Reports" - }, - "ownerId": { - "type": "string", - "format": "uuid", - "description": "User ID of the folder owner" + "description": "Label name", + "example": "verified" }, - "path": { - "type": "string", - "description": "Full path to the folder", - "example": "/shared/reports/my-reports" + "usage_count": { + "type": "number", + "description": "Number of documents with this label" }, - "url": { - "type": "string", - "description": "URL to view the folder in the Omni UI.", - "example": "https://org.omni.co/f/my-reports" + "verified": { + "type": "boolean", + "description": "Whether label is verified" } }, "required": [ - "id", + "color", + "description", + "homepage", "name", - "ownerId", - "path", - "url" + "usage_count", + "verified" ] }, - "description": "List of folders" + "description": "List of labels" } }, "required": [ - "pageInfo", - "records" + "labels" ] }, - "FoldersCreateResponse": { + "LabelsCreateResponse": { "type": "object", "properties": { - "id": { - "type": "string", - "format": "uuid", - "description": "ID of the created folder" + "color": { + "type": [ + "string", + "null" + ], + "maxLength": 9, + "description": "Hex color for the label (e.g. #0366d6)", + "example": "#0366d6" }, - "name": { - "type": "string", - "description": "Name of the created folder" + "description": { + "type": [ + "string", + "null" + ], + "maxLength": 500, + "description": "Label description", + "example": "Important items that need attention" }, - "ownerId": { - "type": "string", - "format": "uuid", - "description": "User ID of the folder owner" + "homepage": { + "type": "boolean", + "description": "Whether label is shown on homepage" }, - "path": { + "name": { "type": "string", - "description": "Full path to the folder" + "description": "Label name", + "example": "verified" }, - "scope": { - "type": "string", - "enum": [ - "organization", - "restricted" - ], - "description": "Share scope of the folder" + "usage_count": { + "type": "number", + "description": "Number of documents with this label" + }, + "verified": { + "type": "boolean", + "description": "Whether label is verified" } }, "required": [ - "id", + "color", + "description", + "homepage", "name", - "ownerId", - "path", - "scope" + "usage_count", + "verified" ] }, - "FoldersCreateBody": { + "LabelsCreateBody": { "type": "object", "properties": { + "color": { + "type": [ + "string", + "null" + ], + "maxLength": 9, + "default": null, + "description": "Hex color for the label (e.g. #0366d6)", + "example": "#0366d6" + }, + "description": { + "type": [ + "string", + "null" + ], + "maxLength": 500, + "default": null, + "description": "Label description", + "example": "Important items that need attention" + }, + "homepage": { + "type": "boolean", + "default": false, + "description": "Show label on homepage. Requires admin permissions." + }, "name": { "type": "string", - "minLength": 1, - "description": "Name of the folder to create", - "example": "My New Folder" + "minLength": 2, + "maxLength": 25, + "description": "Label name", + "example": "important" }, - "parentFolderId": { - "type": "string", - "format": "uuid", - "description": "Parent folder ID (omit to create at root level)" + "verified": { + "type": "boolean", + "default": false, + "description": "Mark as verified label. Requires admin permissions." + } + }, + "required": [ + "name" + ] + }, + "LabelsGetResponse": { + "type": "object", + "properties": { + "color": { + "type": [ + "string", + "null" + ], + "maxLength": 9, + "description": "Hex color for the label (e.g. #0366d6)", + "example": "#0366d6" }, - "scope": { - "type": "string", - "enum": [ - "organization", - "restricted" + "description": { + "type": [ + "string", + "null" ], - "description": "Share scope for the folder" + "maxLength": 500, + "description": "Label description", + "example": "Important items that need attention" }, - "userId": { + "homepage": { + "type": "boolean", + "description": "Whether label is shown on homepage" + }, + "name": { "type": "string", - "format": "uuid", - "description": "User ID to create the folder as (for org-scoped API keys only)" + "description": "Label name", + "example": "verified" + }, + "usage_count": { + "type": "number", + "description": "Number of documents with this label" + }, + "verified": { + "type": "boolean", + "description": "Whether label is verified" } }, "required": [ - "name" + "color", + "description", + "homepage", + "name", + "usage_count", + "verified" ] }, - "FoldersDeleteResponse": { + "LabelsUpdateResponse": { "type": "object", "properties": { - "success": { + "color": { + "type": [ + "string", + "null" + ], + "maxLength": 9, + "description": "Hex color for the label (e.g. #0366d6)", + "example": "#0366d6" + }, + "description": { + "type": [ + "string", + "null" + ], + "maxLength": 500, + "description": "Label description", + "example": "Important items that need attention" + }, + "homepage": { "type": "boolean", - "description": "Whether the folder was deleted successfully" - } - }, - "required": [ - "success" - ] - }, - "FoldersUpdateResponse": { - "type": "object", - "properties": { - "id": { - "type": "string", - "format": "uuid", - "description": "Folder ID" + "description": "Whether label is shown on homepage" }, "name": { "type": "string", - "description": "Updated folder name" + "description": "Label name", + "example": "verified" }, - "path": { - "type": "string", - "description": "Updated URL path segment for the folder (the folder's own segment only)" + "usage_count": { + "type": "number", + "description": "Number of documents with this label" + }, + "verified": { + "type": "boolean", + "description": "Whether label is verified" } }, "required": [ - "id", + "color", + "description", + "homepage", "name", - "path" + "usage_count", + "verified" ] }, - "FoldersUpdateBody": { + "LabelsUpdateBody": { "type": "object", "properties": { - "name": { - "type": "string", - "minLength": 1, - "description": "New display name for the folder", - "example": "Q1 Reports" + "color": { + "type": [ + "string", + "null" + ], + "maxLength": 9, + "description": "Hex color for the label (e.g. #0366d6)", + "example": "#0366d6" }, - "path": { + "description": { + "type": [ + "string", + "null" + ], + "maxLength": 500, + "description": "Label description", + "example": "Important items that need attention" + }, + "homepage": { + "type": "boolean", + "description": "Show label on homepage. Requires admin permissions to modify." + }, + "name": { "type": "string", - "minLength": 1, - "pattern": "^[a-zA-Z0-9-]+$", - "description": "New URL path segment for the folder (alphanumeric and dashes only). This is only the folder's own segment, not the full hierarchical path.", - "example": "q1-reports" + "minLength": 2, + "maxLength": 25, + "description": "Label name", + "example": "important" }, - "resolvePathConflict": { + "verified": { "type": "boolean", - "default": false, - "description": "When true, automatically resolves path collisions with existing folders by appending a numeric suffix (e.g., my-path-1). When false (default), returns 409 Conflict if the path is already taken. Does not apply to reserved paths, which are always rejected with 400." + "description": "Mark as verified label. Requires admin permissions to modify." } } }, - "FoldersGetPermissionsResponse": { + "ModelsListResponse": { "type": "object", "properties": { - "permits": { + "pageInfo": { + "allOf": [ + { + "$ref": "#/components/schemas/PageInfo" + }, + { + "description": "Pagination information" + } + ] + }, + "records": { "type": "array", "items": { "type": "object", "properties": { - "accessBoost": { - "type": "boolean", - "description": "Whether access boost is enabled for this permit" + "baseModelId": { + "type": [ + "string", + "null" + ], + "description": "Base model ID for branch/extension models" }, - "role": { + "branches": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Branch ID" + }, + "name": { + "type": "string", + "description": "Branch name" + } + }, + "required": [ + "id", + "name" + ] + }, + "description": "Active branches (if include=activeBranches)" + }, + "connectionId": { + "type": [ + "string", + "null" + ], + "description": "Connection ID" + }, + "createdAt": { "type": "string", - "description": "Content role (e.g., VIEWER, EDITOR, MANAGER)", - "example": "VIEWER" + "description": "Creation timestamp" }, - "userGroupId": { + "deletedAt": { + "type": [ + "string", + "null" + ], + "description": "Deletion timestamp" + }, + "id": { "type": "string", - "description": "User group ID if this is a group permit" + "description": "Model ID" }, - "userId": { + "modelKind": { + "type": [ + "string", + "null" + ], + "description": "Model kind" + }, + "name": { + "type": [ + "string", + "null" + ], + "description": "Model name" + }, + "updatedAt": { "type": "string", - "format": "uuid", - "description": "User ID if this is a user permit" + "description": "Last update timestamp" } }, "required": [ - "role" + "baseModelId", + "connectionId", + "createdAt", + "deletedAt", + "id", + "modelKind", + "name", + "updatedAt" ] }, - "description": "List of permission permits for the folder" + "description": "List of model records" + } + }, + "required": [ + "pageInfo", + "records" + ] + }, + "CreateModelSchemaBase": { + "type": "object", + "properties": { + "accessGrants": { + "type": "array", + "items": { + "type": "object", + "properties": { + "accessBoostable": { + "type": "boolean" + }, + "allowedValues": { + "type": "array", + "items": { + "type": "string" + } + }, + "codeComments": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "ignored": { + "type": "boolean" + }, + "name": { + "type": "string" + }, + "userAttribute": { + "type": "string" + } + }, + "required": [ + "accessBoostable", + "name" + ] + }, + "description": "Access grants for the model" + }, + "allowAsWorkbookBase": { + "type": "boolean", + "description": "Allow this model as a workbook base" + }, + "baseModelId": { + "type": "string", + "description": "Base model ID for extension or branch models" + }, + "connectionId": { + "type": "string", + "description": "Connection ID for the model" + }, + "modelKind": { + "anyOf": [ + { + "type": "string", + "enum": [ + "SCHEMA" + ] + }, + { + "type": "string", + "enum": [ + "SHARED" + ] + }, + { + "type": "string", + "enum": [ + "SHARED_EXTENSION" + ] + }, + { + "type": "string", + "enum": [ + "BRANCH" + ] + } + ], + "default": "SCHEMA", + "description": "Kind of model to create" + }, + "modelName": { + "type": "string", + "description": "Name for the model" + }, + "usesIsolatedBranches": { + "type": "boolean", + "description": "For SHARED_EXTENSION models, controls if branches are shown on extension model page instead of parent shared model" } }, "required": [ - "permits" + "connectionId" ] }, - "FoldersAddPermissionsResponse": { + "ModelsUpdateResponse": { "type": "object", "properties": { + "model": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "Model ID" + }, + "name": { + "type": "string", + "description": "Updated model name" + } + }, + "required": [ + "id", + "name" + ], + "description": "Updated model details" + }, "success": { "type": "boolean", - "description": "Whether the permissions were added successfully" + "description": "Whether the operation succeeded" } }, "required": [ + "model", "success" ] }, - "FoldersAddPermissionsBody": { + "ModelsUpdateBody": { "type": "object", "properties": { - "accessBoost": { - "type": "boolean", - "default": false, - "description": "Whether to grant access boost" - }, - "role": { + "name": { "type": "string", - "enum": [ - "NO_ACCESS", - "VIEWER", - "EXPLORER", - "EDITOR", - "MANAGER" - ], - "description": "Content role to assign (VIEWER, EDITOR, or MANAGER)", - "example": "VIEWER" - }, - "userGroupIds": { - "type": "array", - "items": { - "type": "string" - }, - "default": [], - "description": "User group IDs to grant permission to" - }, - "userIds": { - "type": "array", - "items": { - "type": "string", - "format": "uuid" - }, - "default": [], - "description": "User IDs to grant permission to" - } - }, - "required": [ - "role" - ], - "additionalProperties": false - }, - "FoldersUpdatePermissionsResponse": { - "type": "object", - "properties": { - "success": { - "type": "boolean", - "description": "Whether the permissions were updated successfully" + "minLength": 1, + "description": "New name for the model", + "example": "My Renamed Model" } }, "required": [ - "success" + "name" ] }, - "FoldersUpdatePermissionsBody": { + "JobsGetStatusResponse": { "type": "object", "properties": { - "accessBoost": { - "type": "boolean", - "description": "Whether to grant access boost" + "job_id": { + "type": "string", + "description": "The job ID", + "example": "550e8400-e29b-41d4-a716-446655440000" }, - "role": { + "job_type": { + "type": "string", + "description": "The type of job (e.g., REFRESH_SCHEMA)", + "example": "REFRESH_SCHEMA" + }, + "status": { "type": "string", "enum": [ - "NO_ACCESS", - "VIEWER", - "EXPLORER", - "EDITOR", - "MANAGER" + "IN_PROGRESS", + "COMPLETED", + "FAILED" ], - "description": "New content role to assign" - }, - "userGroupIds": { - "type": "array", - "items": { - "type": "string" - }, - "default": [], - "description": "User group IDs to update permissions for" - }, - "userIds": { - "type": "array", - "items": { - "type": "string", - "format": "uuid" - }, - "default": [], - "description": "User IDs to update permissions for" - } - }, - "additionalProperties": false - }, - "FoldersRevokePermissionsResponse": { - "type": "object", - "properties": { - "success": { - "type": "boolean", - "description": "Whether the permissions were revoked successfully" + "description": "Current status of the job", + "example": "COMPLETED" } }, "required": [ - "success" + "job_id", + "job_type", + "status" ] }, - "FoldersRevokePermissionsBody": { + "ModelsGetSchemasResponse": { "type": "object", "properties": { - "userGroupIds": { + "schemas": { "type": "array", "items": { "type": "string" }, - "default": [], - "description": "User group IDs to revoke permissions from" - }, - "userIds": { - "type": "array", - "items": { - "type": "string", - "format": "uuid" - }, - "default": [], - "description": "User IDs to revoke permissions from" + "description": "Sorted list of all available schema names (catalog-scoped if applicable, e.g. warehouse.reporting)" } }, - "additionalProperties": false + "required": [ + "schemas" + ] }, - "LabelsListResponse": { + "ModelsGetViewResponse": { "type": "object", "properties": { - "labels": { + "success": { + "type": "boolean", + "description": "Whether the operation succeeded" + }, + "views": { "type": "array", "items": { "type": "object", "properties": { - "color": { - "type": [ - "string", - "null" - ], - "maxLength": 9, - "description": "Hex color for the label (e.g. #0366d6)", - "example": "#0366d6" - }, "description": { - "type": [ - "string", - "null" - ], - "maxLength": 500, - "description": "Label description", - "example": "Important items that need attention" + "type": "string", + "description": "View description" }, - "homepage": { + "fields": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Field name" + }, + "type": { + "type": "string", + "enum": [ + "dimension", + "measure", + "filter" + ], + "description": "Field type" + } + }, + "required": [ + "name", + "type" + ] + }, + "description": "Fields in the view" + }, + "hidden": { "type": "boolean", - "description": "Whether label is shown on homepage" + "description": "Whether the view is hidden" }, - "name": { + "label": { "type": "string", - "description": "Label name", - "example": "verified" - }, - "usage_count": { - "type": "number", - "description": "Number of documents with this label" + "description": "View label" }, - "verified": { - "type": "boolean", - "description": "Whether label is verified" + "name": { + "type": "string", + "description": "View name" } }, - "required": [ - "color", - "description", - "homepage", - "name", - "usage_count", - "verified" + "required": [ + "fields", + "name" ] }, - "description": "List of labels" + "description": "List of views" } }, "required": [ - "labels" + "success", + "views" ] }, - "LabelsCreateResponse": { + "ModelsUpdateViewBody": { "type": "object", "properties": { - "color": { - "type": [ - "string", - "null" - ], - "maxLength": 9, - "description": "Hex color for the label (e.g. #0366d6)", - "example": "#0366d6" + "aiContext": { + "type": "string", + "description": "AI context for the view" }, "description": { - "type": [ - "string", - "null" - ], - "maxLength": 500, - "description": "Label description", - "example": "Important items that need attention" + "type": "string", + "description": "View description" }, - "homepage": { + "format": { + "type": "string", + "description": "View format" + }, + "hidden": { "type": "boolean", - "description": "Whether label is shown on homepage" + "description": "Whether the view is hidden" }, - "name": { + "label": { "type": "string", - "description": "Label name", - "example": "verified" - }, - "usage_count": { - "type": "number", - "description": "Number of documents with this label" + "description": "View label" }, - "verified": { - "type": "boolean", - "description": "Whether label is verified" + "tags": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Tags for the view" } - }, - "required": [ - "color", - "description", - "homepage", - "name", - "usage_count", - "verified" - ] + } }, - "LabelsCreateBody": { + "ModelsUpdateFieldBody": { "type": "object", "properties": { - "color": { - "type": [ - "string", - "null" - ], - "maxLength": 9, - "default": null, - "description": "Hex color for the label (e.g. #0366d6)", - "example": "#0366d6" - }, - "description": { - "type": [ - "string", - "null" - ], - "maxLength": 500, - "default": null, - "description": "Label description", - "example": "Important items that need attention" + "aiContext": { + "type": "string", + "description": "AI context for the field" }, - "homepage": { - "type": "boolean", - "default": false, - "description": "Show label on homepage. Requires admin permissions." + "allValues": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Deprecated: use sampleValues instead" }, - "name": { - "type": "string", - "minLength": 2, - "maxLength": 25, - "description": "Label name", - "example": "important" + "binBoundaries": { + "type": "array", + "items": { + "type": "number" + }, + "description": "Bin boundaries for binned fields" }, - "verified": { - "type": "boolean", - "default": false, - "description": "Mark as verified label. Requires admin permissions." - } - }, - "required": [ - "name" - ] - }, - "LabelsGetResponse": { - "type": "object", - "properties": { - "color": { - "type": [ - "string", - "null" - ], - "maxLength": 9, - "description": "Hex color for the label (e.g. #0366d6)", - "example": "#0366d6" + "binLabels": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Labels for bins" }, "description": { - "type": [ - "string", - "null" - ], - "maxLength": 500, - "description": "Label description", - "example": "Important items that need attention" + "type": "string", + "description": "Field description" }, - "homepage": { - "type": "boolean", - "description": "Whether label is shown on homepage" + "drillFields": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Drill-down fields" }, - "name": { + "elseValue": { "type": "string", - "description": "Label name", - "example": "verified" - }, - "usage_count": { - "type": "number", - "description": "Number of documents with this label" + "description": "Else value for grouped fields" }, - "verified": { - "type": "boolean", - "description": "Whether label is verified" - } - }, - "required": [ - "color", - "description", - "homepage", - "name", - "usage_count", - "verified" - ] - }, - "LabelsUpdateResponse": { - "type": "object", - "properties": { - "color": { - "type": [ - "string", - "null" - ], - "maxLength": 9, - "description": "Hex color for the label (e.g. #0366d6)", - "example": "#0366d6" + "filters": { + "type": "object", + "additionalProperties": {}, + "description": "Filters for the field" }, - "description": { - "type": [ - "string", - "null" - ], - "maxLength": 500, - "description": "Label description", - "example": "Important items that need attention" + "format": { + "type": "string", + "description": "Field format" }, - "homepage": { - "type": "boolean", - "description": "Whether label is shown on homepage" + "groupFilters": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": {} + }, + "description": "Group filters" }, - "name": { + "groupLabel": { "type": "string", - "description": "Label name", - "example": "verified" + "description": "Group label" }, - "usage_count": { - "type": "number", - "description": "Number of documents with this label" + "groupNames": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Group names" }, - "verified": { - "type": "boolean", - "description": "Whether label is verified" - } - }, - "required": [ - "color", - "description", - "homepage", - "name", - "usage_count", - "verified" - ] - }, - "LabelsUpdateBody": { - "type": "object", - "properties": { - "color": { - "type": [ - "string", - "null" - ], - "maxLength": 9, - "description": "Hex color for the label (e.g. #0366d6)", - "example": "#0366d6" + "hidden": { + "type": "boolean", + "description": "Whether the field is hidden" }, - "description": { - "type": [ - "string", - "null" - ], - "maxLength": 500, - "description": "Label description", - "example": "Important items that need attention" + "ignored": { + "type": "boolean", + "description": "Whether the field is ignored" }, - "homepage": { + "isCalc": { "type": "boolean", - "description": "Show label on homepage. Requires admin permissions to modify." + "description": "Whether this is a calculation field" }, - "name": { + "label": { "type": "string", - "minLength": 2, - "maxLength": 25, - "description": "Label name", - "example": "important" + "description": "Field label" }, - "verified": { - "type": "boolean", - "description": "Mark as verified label. Requires admin permissions to modify." + "newFieldName": { + "type": "string", + "description": "New field name (for rename)" + }, + "newViewName": { + "type": "string", + "description": "New view name (for move)" + }, + "sampleValues": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Sample values for the field" + }, + "sql": { + "type": "string", + "description": "SQL expression for the field" + }, + "synonyms": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Synonyms for the field" + }, + "tags": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Tags for the field" + }, + "topicContext": { + "type": "string", + "description": "Topic context for the field" } } }, - "ModelsListResponse": { + "ModelsListTopicsResponse": { "type": "object", "properties": { - "pageInfo": { - "allOf": [ - { - "$ref": "#/components/schemas/PageInfo" - }, - { - "description": "Pagination information" - } - ] + "success": { + "type": "boolean", + "description": "Whether the operation succeeded" }, - "records": { + "topics": { "type": "array", "items": { "type": "object", "properties": { - "baseModelId": { - "type": [ - "string", - "null" - ], - "description": "Base model ID for branch/extension models" - }, - "branches": { - "type": "array", - "items": { - "type": "object", - "properties": { - "id": { - "type": "string", - "description": "Branch ID" - }, - "name": { - "type": "string", - "description": "Branch name" - } - }, - "required": [ - "id", - "name" - ] - }, - "description": "Active branches (if include=activeBranches)" - }, - "connectionId": { - "type": [ - "string", - "null" - ], - "description": "Connection ID" - }, - "createdAt": { + "base_view_name": { "type": "string", - "description": "Creation timestamp" - }, - "deletedAt": { - "type": [ - "string", - "null" - ], - "description": "Deletion timestamp" + "description": "Base view name for the topic" }, - "id": { + "description": { "type": "string", - "description": "Model ID" - }, - "modelKind": { - "type": [ - "string", - "null" - ], - "description": "Model kind" - }, - "name": { - "type": [ - "string", - "null" - ], - "description": "Model name" + "description": "Topic description" }, - "updatedAt": { + "group_label": { "type": "string", - "description": "Last update timestamp" - } - }, - "required": [ - "baseModelId", - "connectionId", - "createdAt", - "deletedAt", - "id", - "modelKind", - "name", - "updatedAt" - ] - }, - "description": "List of model records" - } - }, - "required": [ - "pageInfo", - "records" - ] - }, - "CreateModelSchemaBase": { - "type": "object", - "properties": { - "accessGrants": { - "type": "array", - "items": { - "type": "object", - "properties": { - "accessBoostable": { - "type": "boolean" - }, - "allowedValues": { - "type": "array", - "items": { - "type": "string" - } + "description": "Group label" }, - "codeComments": { - "type": "object", - "additionalProperties": { - "type": "string" - } + "hidden": { + "type": "boolean", + "description": "Whether the topic is hidden" }, - "ignored": { - "type": "boolean" + "label": { + "type": "string", + "description": "Topic label" }, "name": { - "type": "string" - }, - "userAttribute": { - "type": "string" + "type": "string", + "description": "Topic name" } }, "required": [ - "accessBoostable", + "base_view_name", "name" ] }, - "description": "Access grants for the model" - }, - "allowAsWorkbookBase": { - "type": "boolean", - "description": "Allow this model as a workbook base" - }, - "baseModelId": { - "type": "string", - "description": "Base model ID for extension or branch models" - }, - "connectionId": { - "type": "string", - "description": "Connection ID for the model" - }, - "modelKind": { - "anyOf": [ - { - "type": "string", - "enum": [ - "SCHEMA" - ] - }, - { - "type": "string", - "enum": [ - "SHARED" - ] - }, - { - "type": "string", - "enum": [ - "SHARED_EXTENSION" - ] - }, - { - "type": "string", - "enum": [ - "BRANCH" - ] - } - ], - "default": "SCHEMA", - "description": "Kind of model to create" - }, - "modelName": { - "type": "string", - "description": "Name for the model" - }, - "usesIsolatedBranches": { - "type": "boolean", - "description": "For SHARED_EXTENSION models, controls if branches are shown on extension model page instead of parent shared model" + "description": "List of topics" } }, "required": [ - "connectionId" + "success", + "topics" ] }, - "ModelsUpdateResponse": { + "ModelsGetTopicResponse": { "type": "object", "properties": { - "model": { + "success": { + "type": "boolean", + "description": "Whether the operation succeeded" + }, + "topic": { "type": "object", "properties": { - "id": { + "base_view_name": { "type": "string", - "format": "uuid", - "description": "Model ID" + "description": "Base view name for the topic" + }, + "description": { + "type": "string", + "description": "Topic description" + }, + "group_label": { + "type": "string", + "description": "Group label" + }, + "hidden": { + "type": "boolean", + "description": "Whether the topic is hidden" + }, + "label": { + "type": "string", + "description": "Topic label" }, "name": { "type": "string", - "description": "Updated model name" + "description": "Topic name" + }, + "relationships": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": {} + }, + "description": "Relationships for the topic" + }, + "views": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": {} + }, + "description": "Views available in the topic" } }, "required": [ - "id", - "name" + "base_view_name", + "name", + "relationships", + "views" ], - "description": "Updated model details" - }, - "success": { - "type": "boolean", - "description": "Whether the operation succeeded" + "description": "Topic details with relationships and views" } }, "required": [ - "model", - "success" + "success", + "topic" ] }, - "ModelsUpdateBody": { + "ModelsUpdateTopicBody": { "type": "object", "properties": { - "name": { + "description": { "type": "string", - "minLength": 1, - "description": "New name for the model", - "example": "My Renamed Model" + "description": "Topic description" + }, + "groupLabel": { + "type": "string", + "description": "Group label for the topic" + }, + "hidden": { + "type": "boolean", + "description": "Whether the topic is hidden" + }, + "label": { + "type": "string", + "description": "Topic label" + }, + "newTopicName": { + "type": "string", + "description": "New topic name (for rename)" } - }, - "required": [ - "name" - ] + } }, - "JobsGetStatusResponse": { + "ModelsCreateFieldBody": { "type": "object", "properties": { - "job_id": { + "aggregateType": { "type": "string", - "description": "The job ID", - "example": "550e8400-e29b-41d4-a716-446655440000" + "enum": [ + "AVERAGE", + "COUNT", + "COUNT_DISTINCT", + "LIST", + "MAX", + "MIN", + "SUM", + "MEDIAN", + "PERCENTILE", + "AVERAGE_DISTINCT_ON", + "SUM_DISTINCT_ON", + "MEDIAN_DISTINCT_ON", + "PERCENTILE_DISTINCT_ON", + "SEMANTIC_VIEW_AGG" + ], + "description": "Aggregate type for measures. Setting this property promotes the field to a measure (written under `measures:`); omit it to create a dimension (written under `dimensions:`). Values must be uppercase canonical names.", + "example": "SUM" }, - "job_type": { + "aiContext": { "type": "string", - "description": "The type of job (e.g., REFRESH_SCHEMA)", - "example": "REFRESH_SCHEMA" + "description": "AI context for the field" }, - "status": { + "description": { "type": "string", - "enum": [ - "IN_PROGRESS", - "COMPLETED", - "FAILED" - ], - "description": "Current status of the job", - "example": "COMPLETED" + "description": "Field description" + }, + "fieldName": { + "type": "string", + "description": "Field name", + "example": "total_revenue" + }, + "format": { + "type": "string", + "description": "Field format" + }, + "hidden": { + "type": "boolean", + "description": "Whether the field is hidden" + }, + "label": { + "type": "string", + "description": "Field label" + }, + "sql": { + "type": "string", + "description": "SQL expression for the field" + }, + "tags": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Tags for the field" + }, + "topicContext": { + "type": "string", + "description": "Topic context for topic-scoped fields" + }, + "viewName": { + "type": "string", + "description": "View to add the field to", + "example": "orders" } }, "required": [ - "job_id", - "job_type", - "status" - ] + "fieldName", + "viewName" + ], + "additionalProperties": false }, - "ModelsGetSchemasResponse": { + "ModelsRefreshResponse": { "type": "object", "properties": { - "schemas": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Sorted list of all available schema names (catalog-scoped if applicable, e.g. warehouse.reporting)" + "jobId": { + "type": "string", + "description": "Job ID for the refresh operation" + }, + "modelId": { + "type": "string", + "description": "Model ID being refreshed" + }, + "status": { + "type": "string", + "enum": [ + "running", + "completed", + "failed" + ], + "description": "Current status of the refresh" } }, "required": [ - "schemas" + "jobId", + "modelId", + "status" ] }, - "ModelsGetViewResponse": { + "ModelsValidateResponse": { "type": "object", "properties": { - "success": { - "type": "boolean", - "description": "Whether the operation succeeded" - }, - "views": { + "issues": { "type": "array", "items": { "type": "object", "properties": { - "description": { + "field": { "type": "string", - "description": "View description" - }, - "fields": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "description": "Field name" - }, - "type": { - "type": "string", - "enum": [ - "dimension", - "measure", - "filter" - ], - "description": "Field type" - } - }, - "required": [ - "name", - "type" - ] - }, - "description": "Fields in the view" + "description": "Field name with the issue" }, - "hidden": { - "type": "boolean", - "description": "Whether the view is hidden" + "message": { + "type": "string", + "description": "Validation issue message" }, - "label": { + "severity": { "type": "string", - "description": "View label" + "enum": [ + "error", + "warning" + ], + "description": "Issue severity" }, - "name": { + "view": { "type": "string", - "description": "View name" + "description": "View name with the issue" } }, "required": [ - "fields", - "name" + "message", + "severity" ] }, - "description": "List of views" + "description": "List of validation issues" + }, + "valid": { + "type": "boolean", + "description": "Whether the model is valid" } }, "required": [ - "success", - "views" + "issues", + "valid" ] }, - "ModelsUpdateViewBody": { + "ModelsMigrateBody": { "type": "object", "properties": { - "aiContext": { - "type": "string", - "description": "AI context for the view" - }, - "description": { + "branchName": { "type": "string", - "description": "View description" + "description": "Branch name for the target model" }, - "format": { + "commitMessage": { "type": "string", - "description": "View format" + "description": "Commit message for git sync" }, - "hidden": { + "deleteViewsAndTopicsMissingFromSource": { "type": "boolean", - "description": "Whether the view is hidden" + "default": true, + "description": "When true (default), views and topics in the target model that are missing from the migrated source are deleted (the source is treated as the complete model). When false, they are kept (inherited) instead — useful when the source git ref may be missing objects that exist in omni but not in git, e.g. a newly synced schema." }, - "label": { + "gitRef": { "type": "string", - "description": "View label" + "description": "Git reference" }, - "tags": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Tags for the view" + "targetModelId": { + "type": "string", + "format": "uuid", + "description": "Target model ID to migrate to" } - } + }, + "required": [ + "targetModelId" + ] }, - "ModelsUpdateFieldBody": { + "ModelsDbtExposuresResponse": { "type": "object", "properties": { - "aiContext": { - "type": "string", - "description": "AI context for the field" - }, - "allValues": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Deprecated: use sampleValues instead" - }, - "binBoundaries": { - "type": "array", - "items": { - "type": "number" - }, - "description": "Bin boundaries for binned fields" + "pageInfo": { + "$ref": "#/components/schemas/PageInfo" }, - "binLabels": { + "records": { "type": "array", "items": { - "type": "string" - }, - "description": "Labels for bins" + "$ref": "#/components/schemas/DbtExposureWithMeta" + } + } + }, + "required": [ + "pageInfo", + "records" + ] + }, + "DbtExposureWithMeta": { + "type": "object", + "properties": { + "dashboard_identifier": { + "type": "string", + "description": "Identifier of the dashboard that generated this exposure" }, - "description": { + "deduplication_name": { "type": "string", - "description": "Field description" + "description": "A unique name for this exposure. Use this instead of exposure.name to avoid duplicate names, or use it as a fallback when exposure.name collides with another exposure." }, - "drillFields": { + "exposure": { + "$ref": "#/components/schemas/DbtExposure" + } + }, + "required": [ + "dashboard_identifier", + "deduplication_name", + "exposure" + ] + }, + "DbtExposure": { + "type": "object", + "properties": { + "depends_on": { "type": "array", "items": { "type": "string" }, - "description": "Drill-down fields" + "description": "List of dbt model references (e.g. ref('model_name'))", + "example": [ + "ref('orders')", + "ref('customers')" + ] }, - "elseValue": { + "label": { "type": "string", - "description": "Else value for grouped fields" - }, - "filters": { - "type": "object", - "additionalProperties": {}, - "description": "Filters for the field" + "description": "Original dashboard name" }, - "format": { + "name": { "type": "string", - "description": "Field format" + "description": "Sanitized exposure name. May contain duplicates across exposures; use deduplication_name for a guaranteed-unique alternative.", + "example": "my_dashboard" }, - "groupFilters": { - "type": "array", - "items": { - "type": "object", - "additionalProperties": {} - }, - "description": "Group filters" + "owner": { + "$ref": "#/components/schemas/DbtExposureOwner" }, - "groupLabel": { + "type": { "type": "string", - "description": "Group label" - }, - "groupNames": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Group names" - }, - "hidden": { - "type": "boolean", - "description": "Whether the field is hidden" - }, - "ignored": { - "type": "boolean", - "description": "Whether the field is ignored" - }, - "isCalc": { - "type": "boolean", - "description": "Whether this is a calculation field" + "enum": [ + "dashboard", + "notebook", + "analysis", + "ml", + "application" + ], + "description": "Type of the exposure", + "example": "dashboard" }, - "label": { + "url": { "type": "string", - "description": "Field label" + "description": "URL of the dashboard" + } + }, + "required": [ + "depends_on", + "name", + "owner", + "type" + ], + "description": "The dbt exposure for this dashboard." + }, + "DbtExposureOwner": { + "type": "object", + "properties": { + "email": { + "type": "string", + "description": "Email of the dashboard owner" }, - "newFieldName": { + "name": { "type": "string", - "description": "New field name (for rename)" + "description": "Name of the dashboard owner" + } + }, + "required": [ + "email", + "name" + ] + }, + "ModelsBranchDbtBody": { + "type": "object", + "properties": { + "dbt_environment_id": { + "type": "string", + "format": "uuid", + "description": "ID of the dbt environment to activate on this branch", + "example": "123e4567-e89b-12d3-a456-426614174000" }, - "newViewName": { + "dbt_git_branch": { "type": "string", - "description": "New view name (for move)" + "description": "Git branch to associate with the dbt environment", + "example": "feature/new-metrics" + } + }, + "required": [ + "dbt_environment_id" + ] + }, + "ModelsMergeBranchResponse": { + "type": "object", + "properties": { + "failed_drafts_count": { + "type": "number", + "description": "Number of drafts that failed to publish" }, - "sampleValues": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Sample values for the field" + "git_synced": { + "type": "boolean", + "description": "Whether git was synced" }, - "sql": { - "type": "string", - "description": "SQL expression for the field" + "published_drafts_count": { + "type": "number", + "description": "Number of drafts published" }, - "synonyms": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Synonyms for the field" + "success": { + "type": "boolean", + "description": "Whether the merge succeeded" + } + }, + "required": [ + "failed_drafts_count", + "git_synced", + "published_drafts_count", + "success" + ] + }, + "ModelsMergeBranchBody": { + "type": "object", + "properties": { + "commit_message": { + "type": "string", + "description": "Custom commit message for git sync" }, - "tags": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Tags for the field" + "delete_branch": { + "type": "boolean", + "default": false, + "description": "Delete the branch after merging" }, - "topicContext": { - "type": "string", - "description": "Topic context for the field" + "force_override_git_settings": { + "type": "boolean", + "default": false, + "description": "Override PR-required or git-follower settings" + }, + "publish_drafts": { + "type": "boolean", + "default": true, + "description": "Publish branch-attached drafts" } } }, - "ModelsListTopicsResponse": { + "ModelsCommitResponse": { "type": "object", "properties": { - "success": { + "did_sync": { "type": "boolean", - "description": "Whether the operation succeeded" + "description": "Whether a sync operation was performed against git" }, - "topics": { - "type": "array", - "items": { - "type": "object", - "properties": { - "base_view_name": { - "type": "string", - "description": "Base view name for the topic" - }, - "description": { - "type": "string", - "description": "Topic description" - }, - "group_label": { - "type": "string", - "description": "Group label" - }, - "hidden": { - "type": "boolean", - "description": "Whether the topic is hidden" - }, - "label": { - "type": "string", - "description": "Topic label" - }, - "name": { - "type": "string", - "description": "Topic name" - } - }, - "required": [ - "base_view_name", - "name" - ] - }, - "description": "List of topics" + "git_sha": { + "type": [ + "string", + "null" + ], + "description": "The git SHA of the commit that was pushed (null if no commit was needed)" + }, + "in_sync": { + "type": "boolean", + "description": "Whether the branch is in sync with git after the operation" + }, + "pr_url": { + "type": [ + "string", + "null" + ], + "description": "The URL of the pull request (or PR creation page for newly-created PRs). May be null when the underlying git provider is not recognized." } }, "required": [ - "success", - "topics" + "did_sync", + "git_sha", + "in_sync", + "pr_url" ] }, - "ModelsGetTopicResponse": { + "ModelsCommitBody": { "type": "object", "properties": { - "success": { + "allow_branch_exists": { "type": "boolean", - "description": "Whether the operation succeeded" + "default": true, + "description": "If true (default), the commit succeeds whether the git branch already exists or not. If false, the request fails when the git branch already exists — use this to ensure only new pull requests are created. Cannot be false when require_branch_exists is true.", + "example": true }, - "topic": { + "branch_id": { + "type": "string", + "format": "uuid", + "description": "UUID of the branch to commit.", + "example": "123e4567-e89b-12d3-a456-426614174001" + }, + "commit_message": { + "type": "string", + "minLength": 1, + "description": "Commit message for the git commit.", + "example": "Add new orders view" + }, + "require_branch_exists": { + "type": "boolean", + "default": false, + "description": "If true, the request fails when the git branch does not already exist — use this to ensure only existing pull requests are updated. Defaults to false. Cannot be true when allow_branch_exists is false.", + "example": false + } + }, + "required": [ + "branch_id", + "commit_message" + ] + }, + "ModelsCacheResetResponse": { + "type": "object", + "properties": { + "cache_reset": { "type": "object", "properties": { - "base_view_name": { - "type": "string", - "description": "Base view name for the topic" - }, - "description": { - "type": "string", - "description": "Topic description" - }, - "group_label": { - "type": "string", - "description": "Group label" - }, - "hidden": { - "type": "boolean", - "description": "Whether the topic is hidden" + "created_at": { + "type": [ + "string", + "null" + ], + "description": "Creation timestamp" }, - "label": { + "model_id": { "type": "string", - "description": "Topic label" + "description": "Model ID" }, - "name": { + "policy_name": { "type": "string", - "description": "Topic name" + "description": "Cache policy name" }, - "relationships": { - "type": "array", - "items": { - "type": "object", - "additionalProperties": {} - }, - "description": "Relationships for the topic" + "reset_at": { + "type": [ + "string", + "null" + ], + "description": "Reset timestamp" }, - "views": { - "type": "array", - "items": { - "type": "object", - "additionalProperties": {} - }, - "description": "Views available in the topic" + "updated_at": { + "type": [ + "string", + "null" + ], + "description": "Last update timestamp" } }, "required": [ - "base_view_name", - "name", - "relationships", - "views" + "created_at", + "model_id", + "policy_name", + "reset_at", + "updated_at" + ], + "description": "Cache reset details" + }, + "success": { + "type": "boolean", + "description": "Whether the operation succeeded" + } + }, + "required": [ + "cache_reset", + "success" + ] + }, + "ModelsCacheResetBody": { + "type": "object", + "properties": { + "resetAt": { + "type": "string", + "description": "ISO-8601 timestamp for when to reset the cache", + "example": "2024-01-15T12:00:00Z" + } + } + }, + "ModelsGitGetResponse": { + "type": "object", + "properties": { + "authMethod": { + "type": "string", + "enum": [ + "ssh", + "https_token" + ], + "description": "Authentication method. \"ssh\" for deploy key, \"https_token\" for deploy token/PAT.", + "example": "ssh" + }, + "baseBranch": { + "type": "string", + "description": "The target branch for Omni pull requests", + "example": "main" + }, + "branchPerPullRequest": { + "type": "boolean", + "description": "If true, all pull requests will create a branch in Omni, even those created outside of the tool", + "example": false + }, + "cloneUrl": { + "type": "string", + "description": "Clone URL of the git repository (SSH or HTTPS)", + "example": "git@github.com:org/repo.git" + }, + "gitFollower": { + "type": "boolean", + "description": "If true, the shared model is read-only and can only be updated by merging pull requests to the base branch", + "example": false + }, + "gitServiceProvider": { + "type": "string", + "description": "The git provider type", + "example": "github" + }, + "modelPath": { + "type": [ + "string", + "null" + ], + "description": "Path to model files in the repository", + "example": "omni/my_model" + }, + "publicKey": { + "type": [ + "string", + "null" ], - "description": "Topic details with relationships and views" + "description": "SSH public key for repository access (deploy key). Null for HTTPS token auth.", + "example": "ssh-ed25519 AAAA..." + }, + "requirePullRequest": { + "type": "string", + "enum": [ + "always", + "users-only", + "never" + ], + "description": "When pull requests are required: \"always\" for all changes, \"users-only\" for user-initiated changes only, \"never\" for direct commits.", + "example": "users-only" + }, + "sshUrl": { + "type": "string", + "deprecated": true, + "description": "Deprecated — use cloneUrl. Clone URL of the git repository." + }, + "webUrl": { + "type": [ + "string", + "null" + ], + "description": "Custom web URL for the git repository, or null if not set", + "example": "https://github.com/org/repo" + }, + "webhookSecret": { + "type": "string", + "description": "Webhook secret for signature verification. Only included if requested via ?include=webhookSecret" + }, + "webhookUrl": { + "type": "string", + "description": "Webhook URL to configure in your git provider", + "example": "https://app.omni.co/api/webhooks/model/..." } }, "required": [ - "success", - "topic" + "authMethod", + "baseBranch", + "branchPerPullRequest", + "cloneUrl", + "gitFollower", + "gitServiceProvider", + "modelPath", + "publicKey", + "requirePullRequest", + "sshUrl", + "webUrl", + "webhookUrl" ] }, - "ModelsUpdateTopicBody": { + "ModelsGitCreateResponse": { "type": "object", "properties": { - "description": { + "authMethod": { "type": "string", - "description": "Topic description" + "enum": [ + "ssh", + "https_token" + ], + "description": "Authentication method. \"ssh\" for deploy key, \"https_token\" for deploy token/PAT.", + "example": "ssh" }, - "groupLabel": { + "baseBranch": { "type": "string", - "description": "Group label for the topic" + "description": "The target branch for Omni pull requests", + "example": "main" }, - "hidden": { + "branchPerPullRequest": { "type": "boolean", - "description": "Whether the topic is hidden" + "description": "If true, all pull requests will create a branch in Omni, even those created outside of the tool", + "example": false }, - "label": { + "cloneUrl": { "type": "string", - "description": "Topic label" + "description": "Clone URL of the git repository (SSH or HTTPS)", + "example": "git@github.com:org/repo.git" }, - "newTopicName": { + "gitFollower": { + "type": "boolean", + "description": "If true, the shared model is read-only and can only be updated by merging pull requests to the base branch", + "example": false + }, + "gitServiceProvider": { "type": "string", - "description": "New topic name (for rename)" + "description": "The git provider type", + "example": "github" + }, + "modelPath": { + "type": [ + "string", + "null" + ], + "description": "Path to model files in the repository", + "example": "omni/my_model" + }, + "publicKey": { + "type": [ + "string", + "null" + ], + "description": "SSH public key for repository access (deploy key). Null for HTTPS token auth.", + "example": "ssh-ed25519 AAAA..." + }, + "requirePullRequest": { + "type": "string", + "enum": [ + "always", + "users-only", + "never" + ], + "description": "When pull requests are required: \"always\" for all changes, \"users-only\" for user-initiated changes only, \"never\" for direct commits.", + "example": "users-only" + }, + "sshUrl": { + "type": "string", + "deprecated": true, + "description": "Deprecated — use cloneUrl. Clone URL of the git repository." + }, + "webUrl": { + "type": [ + "string", + "null" + ], + "description": "Custom web URL for the git repository, or null if not set", + "example": "https://github.com/org/repo" + }, + "webhookSecret": { + "type": "string", + "description": "Webhook secret for signature verification. Only included if requested via ?include=webhookSecret" + }, + "webhookUrl": { + "type": "string", + "description": "Webhook URL to configure in your git provider", + "example": "https://app.omni.co/api/webhooks/model/..." } - } + }, + "required": [ + "authMethod", + "baseBranch", + "branchPerPullRequest", + "cloneUrl", + "gitFollower", + "gitServiceProvider", + "modelPath", + "publicKey", + "requirePullRequest", + "sshUrl", + "webUrl", + "webhookUrl" + ] }, - "ModelsCreateFieldBody": { + "ModelsGitCreateBody": { "type": "object", "properties": { - "aggregateType": { - "type": "string", - "description": "Aggregate type for measures" - }, - "aiContext": { + "authMethod": { "type": "string", - "description": "AI context for the field" + "enum": [ + "ssh", + "https_token" + ], + "default": "ssh", + "description": "Authentication method. \"ssh\" for deploy key (default), \"https_token\" for deploy token/PAT.", + "example": "ssh" }, - "description": { + "baseBranch": { "type": "string", - "description": "Field description" + "default": "main", + "description": "The target branch for Omni pull requests. Defaults to \"main\"", + "example": "main" }, - "fieldName": { - "type": "string", - "description": "Field name", - "example": "total_revenue" + "branchPerPullRequest": { + "type": "boolean", + "default": false, + "description": "If true, all pull requests will create a branch in Omni. Defaults to false", + "example": false }, - "format": { + "cloneUrl": { "type": "string", - "description": "Field format" + "minLength": 1, + "description": "Clone URL of the git repository. SSH (git@...) for deploy key auth, HTTPS (https://...) for token auth.", + "example": "git@github.com:org/repo.git" }, - "hidden": { + "gitFollower": { "type": "boolean", - "description": "Whether the field is hidden" + "default": false, + "description": "If true, the shared model will be read-only. Defaults to false", + "example": false }, - "label": { + "gitServiceProvider": { "type": "string", - "description": "Field label" + "enum": [ + "github", + "gitlab", + "azure_devops", + "bitbucket", + "bitbucket_datacenter", + "auto" + ], + "default": "auto", + "description": "The git provider type. Use \"auto\" for automatic detection. Defaults to \"auto\"", + "example": "auto" }, - "sql": { + "modelPath": { "type": "string", - "description": "SQL expression for the field" + "description": "Path to model files in the repository. Defaults to omni/. Use a plain name (e.g., \"my_model\") for omni/my_model, or a leading slash for a custom path (e.g., \"/bi/models/sales\")", + "example": "my_model" }, - "tags": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Tags for the field" + "requirePullRequest": { + "type": "string", + "enum": [ + "always", + "users-only", + "never" + ], + "default": "never", + "description": "Controls when pull requests are required. Defaults to \"never\"", + "example": "never" }, - "topicContext": { + "sshUrl": { "type": "string", - "description": "Topic context for topic-scoped fields" + "minLength": 1, + "description": "Deprecated — use cloneUrl. Clone URL of the git repository.", + "example": "git@github.com:org/repo.git", + "deprecated": true }, - "viewName": { + "token": { "type": "string", - "description": "View to add the field to", - "example": "orders" - } - }, - "required": [ - "fieldName", - "viewName" - ] + "maxLength": 1000, + "pattern": "^[a-zA-Z0-9_\\-.]+$", + "description": "HTTPS token for authentication (deploy token value, PAT, etc.). Required when authMethod is \"https_token\"." + }, + "webUrl": { + "type": "string", + "description": "Custom web URL for the git repository. Use when the clone URL goes through a tunnel/VPC and differs from the inferred HTTPS address", + "example": "https://github.com/org/repo" + } + } }, - "ModelsRefreshResponse": { + "ModelsGitUpdateResponse": { "type": "object", "properties": { - "jobId": { + "authMethod": { "type": "string", - "description": "Job ID for the refresh operation" + "enum": [ + "ssh", + "https_token" + ], + "description": "Authentication method. \"ssh\" for deploy key, \"https_token\" for deploy token/PAT.", + "example": "ssh" }, - "modelId": { + "baseBranch": { "type": "string", - "description": "Model ID being refreshed" + "description": "The target branch for Omni pull requests", + "example": "main" }, - "status": { + "branchPerPullRequest": { + "type": "boolean", + "description": "If true, all pull requests will create a branch in Omni, even those created outside of the tool", + "example": false + }, + "cloneUrl": { "type": "string", - "enum": [ - "running", - "completed", - "failed" - ], - "description": "Current status of the refresh" - } - }, - "required": [ - "jobId", - "modelId", - "status" - ] - }, - "ModelsValidateResponse": { - "type": "object", - "properties": { - "issues": { - "type": "array", - "items": { - "type": "object", - "properties": { - "field": { - "type": "string", - "description": "Field name with the issue" - }, - "message": { - "type": "string", - "description": "Validation issue message" - }, - "severity": { - "type": "string", - "enum": [ - "error", - "warning" - ], - "description": "Issue severity" - }, - "view": { - "type": "string", - "description": "View name with the issue" - } - }, - "required": [ - "message", - "severity" - ] - }, - "description": "List of validation issues" + "description": "Clone URL of the git repository (SSH or HTTPS)", + "example": "git@github.com:org/repo.git" }, - "valid": { + "gitFollower": { "type": "boolean", - "description": "Whether the model is valid" - } - }, - "required": [ - "issues", - "valid" - ] - }, - "ModelsMigrateBody": { - "type": "object", - "properties": { - "branchName": { + "description": "If true, the shared model is read-only and can only be updated by merging pull requests to the base branch", + "example": false + }, + "gitServiceProvider": { "type": "string", - "description": "Branch name for the target model" + "description": "The git provider type", + "example": "github" }, - "commitMessage": { + "modelPath": { + "type": [ + "string", + "null" + ], + "description": "Path to model files in the repository", + "example": "omni/my_model" + }, + "publicKey": { + "type": [ + "string", + "null" + ], + "description": "SSH public key for repository access (deploy key). Null for HTTPS token auth.", + "example": "ssh-ed25519 AAAA..." + }, + "requirePullRequest": { "type": "string", - "description": "Commit message for git sync" + "enum": [ + "always", + "users-only", + "never" + ], + "description": "When pull requests are required: \"always\" for all changes, \"users-only\" for user-initiated changes only, \"never\" for direct commits.", + "example": "users-only" }, - "gitRef": { + "sshUrl": { "type": "string", - "description": "Git reference" + "deprecated": true, + "description": "Deprecated — use cloneUrl. Clone URL of the git repository." }, - "targetModelId": { + "webUrl": { + "type": [ + "string", + "null" + ], + "description": "Custom web URL for the git repository, or null if not set", + "example": "https://github.com/org/repo" + }, + "webhookSecret": { "type": "string", - "format": "uuid", - "description": "Target model ID to migrate to" - } - }, - "required": [ - "targetModelId" - ] - }, - "ModelsDbtExposuresResponse": { - "type": "object", - "properties": { - "pageInfo": { - "$ref": "#/components/schemas/PageInfo" + "description": "Webhook secret for signature verification. Only included if requested via ?include=webhookSecret" }, - "records": { - "type": "array", - "items": { - "$ref": "#/components/schemas/DbtExposureWithMeta" - } + "webhookUrl": { + "type": "string", + "description": "Webhook URL to configure in your git provider", + "example": "https://app.omni.co/api/webhooks/model/..." } }, "required": [ - "pageInfo", - "records" + "authMethod", + "baseBranch", + "branchPerPullRequest", + "cloneUrl", + "gitFollower", + "gitServiceProvider", + "modelPath", + "publicKey", + "requirePullRequest", + "sshUrl", + "webUrl", + "webhookUrl" ] }, - "DbtExposureWithMeta": { + "ModelsGitUpdateBody": { "type": "object", "properties": { - "dashboard_identifier": { + "authMethod": { "type": "string", - "description": "Identifier of the dashboard that generated this exposure" + "enum": [ + "ssh", + "https_token" + ], + "description": "Authentication method to change to.", + "example": "ssh" }, - "deduplication_name": { + "baseBranch": { "type": "string", - "description": "A unique name for this exposure. Use this instead of exposure.name to avoid duplicate names, or use it as a fallback when exposure.name collides with another exposure." + "description": "The target branch for Omni pull requests", + "example": "main" }, - "exposure": { - "$ref": "#/components/schemas/DbtExposure" - } - }, - "required": [ - "dashboard_identifier", - "deduplication_name", - "exposure" - ] - }, - "DbtExposure": { - "type": "object", - "properties": { - "depends_on": { - "type": "array", - "items": { - "type": "string" - }, - "description": "List of dbt model references (e.g. ref('model_name'))", - "example": [ - "ref('orders')", - "ref('customers')" - ] + "branchPerPullRequest": { + "type": "boolean", + "description": "If true, all pull requests will create a branch in Omni", + "example": false }, - "label": { + "cloneUrl": { "type": "string", - "description": "Original dashboard name" + "minLength": 1, + "description": "Clone URL of the git repository (SSH or HTTPS).", + "example": "git@github.com:org/repo.git" }, - "name": { + "gitFollower": { + "type": "boolean", + "description": "If true, the shared model will be read-only", + "example": false + }, + "gitServiceProvider": { "type": "string", - "description": "Sanitized exposure name. May contain duplicates across exposures; use deduplication_name for a guaranteed-unique alternative.", - "example": "my_dashboard" + "enum": [ + "github", + "gitlab", + "azure_devops", + "bitbucket", + "bitbucket_datacenter", + "auto" + ], + "description": "The git provider type", + "example": "github" }, - "owner": { - "$ref": "#/components/schemas/DbtExposureOwner" + "modelPath": { + "type": "string", + "description": "Path to model files in the repository", + "example": "my_model" }, - "type": { + "requirePullRequest": { "type": "string", "enum": [ - "dashboard", - "notebook", - "analysis", - "ml", - "application" + "always", + "users-only", + "never" ], - "description": "Type of the exposure", - "example": "dashboard" + "description": "Controls when pull requests are required", + "example": "users-only" }, - "url": { - "type": "string", - "description": "URL of the dashboard" - } - }, - "required": [ - "depends_on", - "name", - "owner", - "type" - ], - "description": "The dbt exposure for this dashboard." - }, - "DbtExposureOwner": { - "type": "object", - "properties": { - "email": { + "sshUrl": { "type": "string", - "description": "Email of the dashboard owner" + "minLength": 1, + "description": "Deprecated — use cloneUrl. Clone URL of the git repository.", + "example": "git@github.com:org/repo.git", + "deprecated": true }, - "name": { - "type": "string", - "description": "Name of the dashboard owner" - } - }, - "required": [ - "email", - "name" - ] - }, - "ModelsBranchDbtBody": { - "type": "object", - "properties": { - "dbt_environment_id": { + "token": { "type": "string", - "format": "uuid", - "description": "ID of the dbt environment to activate on this branch", - "example": "123e4567-e89b-12d3-a456-426614174000" + "maxLength": 1000, + "pattern": "^[a-zA-Z0-9_\\-.]+$", + "description": "HTTPS token for authentication (deploy token value, PAT, etc.)." }, - "dbt_git_branch": { + "webUrl": { "type": "string", - "description": "Git branch to associate with the dbt environment", - "example": "feature/new-metrics" + "description": "Custom web URL for the git repository. Use when the clone URL goes through a tunnel/VPC and differs from the inferred HTTPS address", + "example": "https://github.com/org/repo" } - }, - "required": [ - "dbt_environment_id" - ] + } }, - "ModelsMergeBranchResponse": { + "ModelsGitDeleteResponse": { "type": "object", "properties": { - "failed_drafts_count": { - "type": "number", - "description": "Number of drafts that failed to publish" - }, - "git_synced": { - "type": "boolean", - "description": "Whether git was synced" - }, - "published_drafts_count": { - "type": "number", - "description": "Number of drafts published" + "message": { + "type": "string", + "description": "Success message", + "example": "Git repository unlinked successfully" }, "success": { "type": "boolean", - "description": "Whether the merge succeeded" + "description": "Whether the operation succeeded", + "example": true } }, "required": [ - "failed_drafts_count", - "git_synced", - "published_drafts_count", + "message", "success" ] }, - "ModelsMergeBranchBody": { - "type": "object", - "properties": { - "commit_message": { - "type": "string", - "description": "Custom commit message for git sync" - }, - "delete_branch": { - "type": "boolean", - "default": false, - "description": "Delete the branch after merging" - }, - "force_override_git_settings": { - "type": "boolean", - "default": false, - "description": "Override PR-required or git-follower settings" - }, - "publish_drafts": { - "type": "boolean", - "default": true, - "description": "Publish branch-attached drafts" - } - } - }, - "ModelsCommitResponse": { + "ModelsGitSyncResponse": { "type": "object", "properties": { - "did_sync": { + "didSync": { "type": "boolean", - "description": "Whether a sync operation was performed against git" + "description": "Whether a sync operation was performed" }, - "git_sha": { + "gitSha": { "type": [ "string", "null" ], - "description": "The git SHA of the commit that was pushed (null if no commit was needed)" + "description": "The git SHA after the sync operation" }, - "in_sync": { + "inSync": { "type": "boolean", - "description": "Whether the branch is in sync with git after the operation" + "description": "Whether the model is currently in sync with git" }, - "pr_url": { - "type": [ - "string", - "null" - ], - "description": "The URL of the pull request (or PR creation page for newly-created PRs). May be null when the underlying git provider is not recognized." + "message": { + "type": "string", + "description": "Human-readable message about the sync status" } }, "required": [ - "did_sync", - "git_sha", - "in_sync", - "pr_url" + "didSync", + "gitSha", + "inSync", + "message" ] }, - "ModelsCommitBody": { + "ModelsGitSyncBody": { "type": "object", "properties": { - "allow_branch_exists": { - "type": "boolean", - "default": true, - "description": "If true (default), the commit succeeds whether the git branch already exists or not. If false, the request fails when the git branch already exists — use this to ensure only new pull requests are created. Cannot be false when require_branch_exists is true.", - "example": true - }, - "branch_id": { - "type": "string", - "format": "uuid", - "description": "UUID of the branch to commit.", - "example": "123e4567-e89b-12d3-a456-426614174001" - }, - "commit_message": { + "commitMessage": { "type": "string", - "minLength": 1, - "description": "Commit message for the git commit.", - "example": "Add new orders view" - }, - "require_branch_exists": { - "type": "boolean", - "default": false, - "description": "If true, the request fails when the git branch does not already exist — use this to ensure only existing pull requests are updated. Defaults to false. Cannot be true when allow_branch_exists is false.", - "example": false + "description": "Optional commit message for the git sync operation", + "example": "Update model schema" } - }, - "required": [ - "branch_id", - "commit_message" - ] + } }, - "ModelsCacheResetResponse": { + "ModelsContentValidatorGetResponse": { "type": "object", "properties": { - "cache_reset": { - "type": "object", + "branch": { + "type": [ + "object", + "null" + ], "properties": { - "created_at": { - "type": [ - "string", - "null" - ], - "description": "Creation timestamp" - }, - "model_id": { + "id": { "type": "string", - "description": "Model ID" + "description": "Branch UUID" }, - "policy_name": { + "name": { "type": "string", - "description": "Cache policy name" - }, - "reset_at": { - "type": [ - "string", - "null" - ], - "description": "Reset timestamp" - }, - "updated_at": { - "type": [ - "string", - "null" - ], - "description": "Last update timestamp" + "description": "Branch name" } }, "required": [ - "created_at", - "model_id", - "policy_name", - "reset_at", - "updated_at" + "id", + "name" ], - "description": "Cache reset details" + "description": "Branch info (present if branch_id was specified)" + }, + "content": { + "type": "array", + "items": {}, + "description": "Documents with their validation results" + }, + "model_id": { + "type": "string", + "description": "Model UUID" + } + }, + "required": [ + "branch", + "content", + "model_id" + ] + }, + "ContentFilterMode": { + "type": "string", + "enum": [ + "ALL", + "WITH_ISSUES", + "NO_ISSUES" + ], + "description": "Filter documents by issue status. ALL (default) returns all documents with at least one query. WITH_ISSUES returns only documents with at least one query issue, dashboard filter issue, or document error. NO_ISSUES returns only documents with zero issues and no document errors." + }, + "ModelsContentValidatorReplaceResponse": { + "type": "object", + "properties": { + "replaced_dashboard_filters_count": { + "type": "integer", + "description": "Number of dashboard filters replaced" + }, + "replaced_documents_count": { + "type": "integer", + "description": "Number of documents modified" }, - "success": { - "type": "boolean", - "description": "Whether the operation succeeded" + "replaced_queries_count": { + "type": "integer", + "description": "Number of queries replaced" + }, + "replaced_workbook_models_count": { + "type": "integer", + "description": "Number of workbook models replaced" + }, + "skipped_pr_required_count": { + "type": "integer", + "description": "Number of documents skipped due to pull request requirements" } }, "required": [ - "cache_reset", - "success" + "replaced_dashboard_filters_count", + "replaced_documents_count", + "replaced_queries_count", + "replaced_workbook_models_count", + "skipped_pr_required_count" ] }, - "ModelsCacheResetBody": { - "type": "object", - "properties": { - "resetAt": { - "type": "string", - "description": "ISO-8601 timestamp for when to reset the cache", - "example": "2024-01-15T12:00:00Z" - } - } - }, - "ModelsGitGetResponse": { + "ModelsContentValidatorReplaceBody": { "type": "object", "properties": { - "authMethod": { + "branch_id": { "type": "string", - "enum": [ - "ssh", - "https_token" - ], - "description": "Authentication method. \"ssh\" for deploy key, \"https_token\" for deploy token/PAT.", - "example": "ssh" + "description": "Optional branch ID" }, - "baseBranch": { + "creator_id": { "type": "string", - "description": "The target branch for Omni pull requests", - "example": "main" - }, - "branchPerPullRequest": { - "type": "boolean", - "description": "If true, all pull requests will create a branch in Omni, even those created outside of the tool", - "example": false + "format": "uuid", + "description": "Restrict replacement to documents created by this user (user ID). Unknown IDs return 400." }, - "cloneUrl": { + "find": { "type": "string", - "description": "Clone URL of the git repository (SSH or HTTPS)", - "example": "git@github.com:org/repo.git" - }, - "gitFollower": { - "type": "boolean", - "description": "If true, the shared model is read-only and can only be updated by merging pull requests to the base branch", - "example": false + "minLength": 1, + "description": "The string to find" }, - "gitServiceProvider": { + "find_or_replace_type": { "type": "string", - "description": "The git provider type", - "example": "github" - }, - "modelPath": { - "type": [ - "string", - "null" + "enum": [ + "FIELD", + "TOPIC", + "VIEW" ], - "description": "Path to model files in the repository", - "example": "omni/my_model" + "description": "Type of find/replace operation." }, - "publicKey": { - "type": [ - "string", - "null" - ], - "description": "SSH public key for repository access (deploy key). Null for HTTPS token auth.", - "example": "ssh-ed25519 AAAA..." + "folder_paths": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Restrict replacement to documents in matching folder paths (prefix match). Documents with no folder are excluded unless \"\" is specified." }, - "requirePullRequest": { - "type": "string", - "enum": [ - "always", - "users-only", - "never" - ], - "description": "When pull requests are required: \"always\" for all changes, \"users-only\" for user-initiated changes only, \"never\" for direct commits.", - "example": "users-only" + "include_personal_folders": { + "type": "boolean", + "default": false, + "description": "Whether to include personal folders" }, - "sshUrl": { + "labels": { "type": "string", - "deprecated": true, - "description": "Deprecated — use cloneUrl. Clone URL of the git repository." - }, - "webUrl": { - "type": [ - "string", - "null" - ], - "description": "Custom web URL for the git repository, or null if not set", - "example": "https://github.com/org/repo" + "description": "Comma-separated label names to scope replacement. Unknown labels return 400." }, - "webhookSecret": { + "only_in_workbook_id": { "type": "string", - "description": "Webhook secret for signature verification. Only included if requested via ?include=webhookSecret" + "description": "Optional workbook ID to limit the replace scope" }, - "webhookUrl": { + "replacement": { "type": "string", - "description": "Webhook URL to configure in your git provider", - "example": "https://app.omni.co/api/webhooks/model/..." + "minLength": 1, + "description": "The replacement string" } }, "required": [ - "authMethod", - "baseBranch", - "branchPerPullRequest", - "cloneUrl", - "gitFollower", - "gitServiceProvider", - "modelPath", - "publicKey", - "requirePullRequest", - "sshUrl", - "webUrl", - "webhookUrl" + "find", + "find_or_replace_type", + "replacement" ] }, - "ModelsGitCreateResponse": { + "ModelYamlResponse": { "type": "object", "properties": { - "authMethod": { - "type": "string", - "enum": [ - "ssh", - "https_token" - ], - "description": "Authentication method. \"ssh\" for deploy key, \"https_token\" for deploy token/PAT.", - "example": "ssh" + "checksums": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Checksums for each file" }, - "baseBranch": { - "type": "string", - "description": "The target branch for Omni pull requests", - "example": "main" + "files": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "YAML content for each file" }, - "branchPerPullRequest": { - "type": "boolean", - "description": "If true, all pull requests will create a branch in Omni, even those created outside of the tool", - "example": false + "version": { + "type": "number", + "description": "Model version number" }, - "cloneUrl": { + "viewNames": { + "type": "object", + "additionalProperties": {}, + "description": "View name mappings" + } + }, + "required": [ + "files", + "version" + ] + }, + "ModelYamlCreateRequestBody": { + "type": "object", + "properties": { + "branchId": { "type": "string", - "description": "Clone URL of the git repository (SSH or HTTPS)", - "example": "git@github.com:org/repo.git" - }, - "gitFollower": { - "type": "boolean", - "description": "If true, the shared model is read-only and can only be updated by merging pull requests to the base branch", - "example": false + "format": "uuid", + "description": "Branch ID for branch-aware operations" }, - "gitServiceProvider": { + "fileName": { "type": "string", - "description": "The git provider type", - "example": "github" - }, - "modelPath": { - "type": [ - "string", - "null" - ], - "description": "Path to model files in the repository", - "example": "omni/my_model" - }, - "publicKey": { - "type": [ - "string", - "null" - ], - "description": "SSH public key for repository access (deploy key). Null for HTTPS token auth.", - "example": "ssh-ed25519 AAAA..." + "minLength": 1, + "description": "File name to create or update" }, - "requirePullRequest": { + "mode": { "type": "string", "enum": [ - "always", - "users-only", - "never" + "combined", + "extension", + "staged", + "merged", + "fully-resolved" ], - "description": "When pull requests are required: \"always\" for all changes, \"users-only\" for user-initiated changes only, \"never\" for direct commits.", - "example": "users-only" + "default": "combined", + "description": "IDE mode for YAML operations" }, - "sshUrl": { + "commitMessage": { "type": "string", - "deprecated": true, - "description": "Deprecated — use cloneUrl. Clone URL of the git repository." + "description": "Commit message for git sync" }, - "webUrl": { - "type": [ - "string", - "null" - ], - "description": "Custom web URL for the git repository, or null if not set", - "example": "https://github.com/org/repo" + "fetchedAtMillis": { + "type": "number", + "description": "Timestamp when the file was fetched" + }, + "fullyResolved": { + "type": "boolean", + "default": false, + "description": "Treat the posted YAML as fully resolved (with the extends chain expanded). Only valid with mode=combined." }, - "webhookSecret": { + "previousChecksum": { "type": "string", - "description": "Webhook secret for signature verification. Only included if requested via ?include=webhookSecret" + "description": "Previous checksum for conflict detection" }, - "webhookUrl": { + "yaml": { "type": "string", - "description": "Webhook URL to configure in your git provider", - "example": "https://app.omni.co/api/webhooks/model/..." + "description": "YAML content for the file" } }, "required": [ - "authMethod", - "baseBranch", - "branchPerPullRequest", - "cloneUrl", - "gitFollower", - "gitServiceProvider", - "modelPath", - "publicKey", - "requirePullRequest", - "sshUrl", - "webUrl", - "webhookUrl" + "fileName", + "yaml" + ], + "additionalProperties": false + }, + "AiAgentActionsResponse": { + "type": "object", + "properties": { + "records": { + "type": "array", + "items": { + "$ref": "#/components/schemas/AiAgentAction" + }, + "description": "AI agent actions in display order: sample queries first, then skills. Topic-level entries follow model-level ones, and skills are deduped by id with topic skills winning over model skills." + } + }, + "required": [ + "records" ] }, - "ModelsGitCreateBody": { + "AiAgentAction": { "type": "object", "properties": { - "authMethod": { + "kind": { "type": "string", "enum": [ - "ssh", - "https_token" + "sample", + "skill" ], - "default": "ssh", - "description": "Authentication method. \"ssh\" for deploy key (default), \"https_token\" for deploy token/PAT.", - "example": "ssh" + "description": "Source of the entry: `sample` for `sample_queries` (model- or topic-level) and `skill` for `skills` (model- or topic-level).", + "example": "skill" }, - "baseBranch": { + "label": { "type": "string", - "default": "main", - "description": "The target branch for Omni pull requests. Defaults to \"main\"", - "example": "main" + "description": "Short, human-readable name for the action — chip text in client UIs and the visible \"prompt\" on the answer card.", + "example": "Revenue trends" }, - "branchPerPullRequest": { - "type": "boolean", - "default": false, - "description": "If true, all pull requests will create a branch in Omni. Defaults to false", - "example": false - }, - "cloneUrl": { + "prompt": { "type": "string", - "minLength": 1, - "description": "Clone URL of the git repository. SSH (git@...) for deploy key auth, HTTPS (https://...) for token auth.", - "example": "git@github.com:org/repo.git" + "description": "Submit this string verbatim as the `prompt` on `POST /api/v1/ai/jobs`. For sample queries this is the raw prompt; for skills it is a pre-formatted wrapper around the skill's input.", + "example": "Skill:\nShow me the recent revenue trends grouped by month…" + } + }, + "required": [ + "kind", + "label", + "prompt" + ] + }, + "QueryRunResponse": { + "type": "object", + "properties": { + "completedQueries": { + "type": "array", + "items": {}, + "description": "Queries that completed synchronously with their results." }, - "gitFollower": { - "type": "boolean", - "default": false, - "description": "If true, the shared model will be read-only. Defaults to false", - "example": false + "jobIds": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Job IDs for queries running asynchronously. Use /api/v1/query/wait to poll for results.", + "example": [ + "job_abc123", + "job_def456" + ] }, - "gitServiceProvider": { + "plan": { + "description": "Query execution plan (only present if planOnly is true)." + } + } + }, + "QueryTimeoutResponse": { + "type": "object", + "properties": { + "detail": { "type": "string", + "description": "Error message indicating the query timed out.", + "example": "Query timed out" + }, + "remaining_job_ids": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Job IDs for queries that have not yet completed. Use /api/v1/query/wait to poll for results." + }, + "timed_out": { + "type": "boolean", "enum": [ - "github", - "gitlab", - "azure_devops", - "bitbucket", - "bitbucket_datacenter", - "auto" + true ], - "default": "auto", - "description": "The git provider type. Use \"auto\" for automatic detection. Defaults to \"auto\"", - "example": "auto" - }, - "modelPath": { + "description": "Always true for timeout responses.", + "example": true + } + }, + "required": [ + "detail", + "timed_out" + ] + }, + "QueryRunBody": { + "type": "object", + "properties": { + "branchId": { "type": "string", - "description": "Path to model files in the repository. Defaults to omni/. Use a plain name (e.g., \"my_model\") for omni/my_model, or a leading slash for a custom path (e.g., \"/bi/models/sales\")", - "example": "my_model" + "format": "uuid", + "description": "Optional model branch to run the query against. Must belong to the same shared model as the query. When omitted, the query runs against the shared model. Takes precedence over the legacy `?branch_id=` URL query parameter.", + "example": "550e8400-e29b-41d4-a716-446655440000" }, - "requirePullRequest": { + "cache": { "type": "string", "enum": [ - "always", - "users-only", - "never" + "disabled", + "normal", + "refresh", + "refresh_all" ], - "default": "never", - "description": "Controls when pull requests are required. Defaults to \"never\"", - "example": "never" + "description": "Cache policy for query execution. Controls whether to use cached results.", + "example": "normal" }, - "sshUrl": { - "type": "string", - "minLength": 1, - "description": "Deprecated — use cloneUrl. Clone URL of the git repository.", - "example": "git@github.com:org/repo.git", - "deprecated": true + "formatResults": { + "type": "boolean", + "description": "Whether to format result values (e.g., apply number formatting). Only valid when resultType is specified." }, - "token": { + "planOnly": { + "type": "boolean", + "default": false, + "description": "If true, returns only the query execution plan without running the query." + }, + "query": { + "description": "The semantic query definition including fields, filters, sorts, and other query parameters." + }, + "resultType": { "type": "string", - "maxLength": 1000, - "pattern": "^[a-zA-Z0-9_\\-.]+$", - "description": "HTTPS token for authentication (deploy token value, PAT, etc.). Required when authMethod is \"https_token\"." + "enum": [ + "csv", + "json", + "xlsx" + ], + "description": "Output format for the results. If not specified, returns base64-encoded Arrow format." }, - "webUrl": { + "userId": { "type": "string", - "description": "Custom web URL for the git repository. Use when the clone URL goes through a tunnel/VPC and differs from the inferred HTTPS address", - "example": "https://github.com/org/repo" + "format": "uuid", + "description": "Alternate location for the `?userId=` query parameter. Prefer the query parameter — this body field exists for backwards compatibility. Supplying both forms results in a 400. Only valid for org-scoped API keys; when set, the user's attributes are applied for row-level security and connection-environment switching.", + "example": "550e8400-e29b-41d4-a716-446655440000" } } }, - "ModelsGitUpdateResponse": { + "QueryWaitResponse": { "type": "object", "properties": { - "authMethod": { - "type": "string", - "enum": [ - "ssh", - "https_token" + "results": { + "type": "array", + "items": {}, + "description": "Array of completed query results. Each result contains the query data or an error." + } + }, + "required": [ + "results" + ] + }, + "SchedulesListItem": { + "type": "object", + "properties": { + "alert": { + "type": "object", + "properties": { + "conditionQueryName": { + "type": [ + "string", + "null" + ], + "description": "Name of the query used for alert condition" + }, + "conditionType": { + "type": "string", + "description": "Type of alert condition: RESULTS_CHANGED, RESULTS_PRESENT, RESULTS_MISSING" + } + }, + "required": [ + "conditionQueryName", + "conditionType" ], - "description": "Authentication method. \"ssh\" for deploy key, \"https_token\" for deploy token/PAT.", - "example": "ssh" + "description": "Alert configuration (only present for alert-type schedules)" }, - "baseBranch": { + "content": { "type": "string", - "description": "The target branch for Omni pull requests", - "example": "main" + "description": "Content type: dashboard or tile", + "example": "dashboard" }, - "branchPerPullRequest": { - "type": "boolean", - "description": "If true, all pull requests will create a branch in Omni, even those created outside of the tool", - "example": false + "dashboardName": { + "type": "string", + "description": "Name of the dashboard", + "example": "Weekly Sales Report" }, - "cloneUrl": { + "destinationType": { + "type": "string", + "description": "Delivery destination type: email, slack, webhook, sftp, s3, google_sheets", + "example": "email" + }, + "disabledAt": { + "type": [ + "string", + "null" + ], + "format": "date-time", + "description": "Timestamp when the schedule was paused (null if active)" + }, + "format": { "type": "string", - "description": "Clone URL of the git repository (SSH or HTTPS)", - "example": "git@github.com:org/repo.git" + "description": "Output format: pdf, png, csv, xlsx, json, link_only", + "example": "pdf" }, - "gitFollower": { - "type": "boolean", - "description": "If true, the shared model is read-only and can only be updated by merging pull requests to the base branch", - "example": false + "id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the schedule" }, - "gitServiceProvider": { + "identifier": { "type": "string", - "description": "The git provider type", - "example": "github" + "description": "Dashboard identifier", + "example": "12db1a0a" }, - "modelPath": { + "lastCompletedAt": { "type": [ "string", "null" ], - "description": "Path to model files in the repository", - "example": "omni/my_model" + "format": "date-time", + "description": "Timestamp of last completed delivery" }, - "publicKey": { + "lastStatus": { "type": [ "string", "null" ], - "description": "SSH public key for repository access (deploy key). Null for HTTPS token auth.", - "example": "ssh-ed25519 AAAA..." + "description": "Status of last delivery: COMPLETE, ERROR, ERROR_DELIVERED, KILLED, CONDITION_UNMET" }, - "requirePullRequest": { + "name": { "type": "string", - "enum": [ - "always", - "users-only", - "never" - ], - "description": "When pull requests are required: \"always\" for all changes, \"users-only\" for user-initiated changes only, \"never\" for direct commits.", - "example": "users-only" + "description": "Name of the schedule", + "example": "Weekly Sales Report" }, - "sshUrl": { + "ownerId": { "type": "string", - "deprecated": true, - "description": "Deprecated — use cloneUrl. Clone URL of the git repository." + "format": "uuid", + "description": "User ID of the schedule owner" }, - "webUrl": { + "ownerName": { + "type": "string", + "description": "Display name of the schedule owner", + "example": "John Doe" + }, + "recipientCount": { + "type": "number", + "description": "Number of recipients (-1 for non-email destinations)", + "example": 5 + }, + "schedule": { + "type": "string", + "description": "AWS EventBridge cron expression (minute hour day-of-month month day-of-week year)", + "example": "0 9 ? * MON *" + }, + "slackRecipientType": { "type": [ "string", "null" ], - "description": "Custom web URL for the git repository, or null if not set", - "example": "https://github.com/org/repo" + "description": "Slack recipient type: Channel or Users (null for non-Slack)" }, - "webhookSecret": { - "type": "string", - "description": "Webhook secret for signature verification. Only included if requested via ?include=webhookSecret" + "systemDisabledAt": { + "type": [ + "string", + "null" + ], + "format": "date-time", + "description": "Timestamp when system disabled the schedule (null if not system-disabled)" }, - "webhookUrl": { + "systemDisabledReason": { + "type": [ + "string", + "null" + ], + "description": "Reason for system disabling: missingQuery, noAccess, orphanedFilterConfigKeys" + }, + "timezone": { "type": "string", - "description": "Webhook URL to configure in your git provider", - "example": "https://app.omni.co/api/webhooks/model/..." + "description": "IANA timezone for the schedule", + "example": "America/New_York" } }, "required": [ - "authMethod", - "baseBranch", - "branchPerPullRequest", - "cloneUrl", - "gitFollower", - "gitServiceProvider", - "modelPath", - "publicKey", - "requirePullRequest", - "sshUrl", - "webUrl", - "webhookUrl" + "content", + "dashboardName", + "destinationType", + "disabledAt", + "format", + "id", + "identifier", + "lastCompletedAt", + "lastStatus", + "name", + "ownerId", + "ownerName", + "recipientCount", + "schedule", + "slackRecipientType", + "systemDisabledAt", + "systemDisabledReason", + "timezone" ] }, - "ModelsGitUpdateBody": { + "SchedulesGetResponse": { "type": "object", "properties": { - "authMethod": { - "type": "string", - "enum": [ - "ssh", - "https_token" + "conditionQueryMapKey": { + "type": [ + "string", + "null" ], - "description": "Authentication method to change to.", - "example": "ssh" - }, - "baseBranch": { - "type": "string", - "description": "The target branch for Omni pull requests", - "example": "main" + "description": "Query key used for alert condition (null for standard schedules)" }, - "branchPerPullRequest": { - "type": "boolean", - "description": "If true, all pull requests will create a branch in Omni", - "example": false + "conditionType": { + "type": [ + "string", + "null" + ], + "description": "Alert condition type: RESULTS_CHANGED, RESULTS_PRESENT, RESULTS_MISSING" }, - "cloneUrl": { + "createdAt": { "type": "string", - "minLength": 1, - "description": "Clone URL of the git repository (SSH or HTTPS).", - "example": "git@github.com:org/repo.git" + "format": "date-time", + "description": "Creation timestamp" }, - "gitFollower": { - "type": "boolean", - "description": "If true, the shared model will be read-only", - "example": false + "destinations": { + "type": "array", + "items": { + "$ref": "#/components/schemas/SchedulesGetDestination" + }, + "description": "Delivery destination configurations" }, - "gitServiceProvider": { - "type": "string", - "enum": [ - "github", - "gitlab", - "azure_devops", - "bitbucket", - "bitbucket_datacenter", - "auto" + "disabledAt": { + "type": [ + "string", + "null" ], - "description": "The git provider type", - "example": "github" - }, - "modelPath": { - "type": "string", - "description": "Path to model files in the repository", - "example": "my_model" + "format": "date-time", + "description": "Timestamp when the schedule was paused (null if active)" }, - "requirePullRequest": { + "entityId": { "type": "string", - "enum": [ - "always", - "users-only", - "never" - ], - "description": "Controls when pull requests are required", - "example": "users-only" + "description": "ID of the associated dashboard" }, - "sshUrl": { - "type": "string", - "minLength": 1, - "description": "Deprecated — use cloneUrl. Clone URL of the git repository.", - "example": "git@github.com:org/repo.git", - "deprecated": true + "fanOut": { + "type": "boolean", + "description": "Whether personalized fan-out delivery is enabled", + "example": false }, - "token": { - "type": "string", - "maxLength": 1000, - "pattern": "^[a-zA-Z0-9_\\-.]+$", - "description": "HTTPS token for authentication (deploy token value, PAT, etc.)." + "filterConfig": { + "description": "The effective dashboard filter configuration that the schedule will run with: the dashboard's current default filters merged under the schedule's persisted overrides, with any keys no longer present on the dashboard dropped. This matches what is shown when the schedule is opened in the Edit Delivery panel, and may differ from the schedule's persisted filter configuration." }, - "webUrl": { - "type": "string", - "description": "Custom web URL for the git repository. Use when the clone URL goes through a tunnel/VPC and differs from the inferred HTTPS address", - "example": "https://github.com/org/repo" - } - } - }, - "ModelsGitDeleteResponse": { - "type": "object", - "properties": { - "message": { + "id": { "type": "string", - "description": "Success message", - "example": "Git repository unlinked successfully" - }, - "success": { - "type": "boolean", - "description": "Whether the operation succeeded", - "example": true - } - }, - "required": [ - "message", - "success" - ] - }, - "ModelsGitSyncResponse": { - "type": "object", - "properties": { - "didSync": { - "type": "boolean", - "description": "Whether a sync operation was performed" - }, - "gitSha": { - "type": [ - "string", - "null" - ], - "description": "The git SHA after the sync operation" + "format": "uuid", + "description": "Schedule UUID", + "example": "123e4567-e89b-12d3-a456-426614174000" }, - "inSync": { + "killJobsOnFailure": { "type": "boolean", - "description": "Whether the model is currently in sync with git" + "description": "Whether to stop the job if any queries fail", + "example": false }, - "message": { + "metadata": { + "description": "Schedule metadata including format options and delivery settings" + }, + "name": { "type": "string", - "description": "Human-readable message about the sync status" - } - }, - "required": [ - "didSync", - "gitSha", - "inSync", - "message" - ] - }, - "ModelsGitSyncBody": { - "type": "object", - "properties": { - "commitMessage": { + "description": "Schedule name", + "example": "Weekly Sales Report" + }, + "organizationId": { "type": "string", - "description": "Optional commit message for the git sync operation", - "example": "Update model schema" - } - } - }, - "ModelsContentValidatorGetResponse": { - "type": "object", - "properties": { - "branch": { - "type": [ - "object", - "null" - ], + "format": "uuid", + "description": "Organization UUID" + }, + "owner": { + "type": "object", "properties": { - "id": { - "type": "string", - "description": "Branch UUID" - }, "name": { "type": "string", - "description": "Branch name" + "description": "Schedule owner name" } }, "required": [ - "id", "name" - ], - "description": "Branch info (present if branch_id was specified)" + ] }, - "content": { - "type": "array", - "items": {}, - "description": "Documents with their validation results" + "ownerId": { + "type": "string", + "format": "uuid", + "description": "User ID of the schedule owner" }, - "model_id": { + "schedule": { "type": "string", - "description": "Model UUID" - } - }, - "required": [ - "branch", - "content", - "model_id" - ] - }, - "ContentFilterMode": { - "type": "string", - "enum": [ - "ALL", - "WITH_ISSUES", - "NO_ISSUES" - ], - "description": "Filter documents by issue status. ALL (default) returns all documents with at least one query. WITH_ISSUES returns only documents with at least one query issue, dashboard filter issue, or document error. NO_ISSUES returns only documents with zero issues and no document errors." - }, - "ModelsContentValidatorReplaceResponse": { - "type": "object", - "properties": { - "replaced_dashboard_filters_count": { - "type": "integer", - "description": "Number of dashboard filters replaced" + "description": "AWS EventBridge cron expression (minute hour day-of-month month day-of-week year)", + "example": "0 9 ? * MON *" }, - "replaced_documents_count": { - "type": "integer", - "description": "Number of documents modified" + "systemDisabledAt": { + "type": [ + "string", + "null" + ], + "format": "date-time", + "description": "Timestamp when the system disabled the schedule" }, - "replaced_queries_count": { - "type": "integer", - "description": "Number of queries replaced" + "systemDisabledReason": { + "type": [ + "string", + "null" + ], + "description": "Reason for system disabling: missingQuery, noAccess, orphanedFilterConfigKeys" }, - "replaced_workbook_models_count": { - "type": "integer", - "description": "Number of workbook models replaced" + "timezone": { + "type": "string", + "description": "IANA timezone for the schedule", + "example": "America/New_York" }, - "skipped_pr_required_count": { - "type": "integer", - "description": "Number of documents skipped due to pull request requirements" + "updatedAt": { + "type": "string", + "format": "date-time", + "description": "Last update timestamp" } }, "required": [ - "replaced_dashboard_filters_count", - "replaced_documents_count", - "replaced_queries_count", - "replaced_workbook_models_count", - "skipped_pr_required_count" + "conditionQueryMapKey", + "conditionType", + "createdAt", + "destinations", + "disabledAt", + "entityId", + "fanOut", + "id", + "killJobsOnFailure", + "name", + "organizationId", + "owner", + "ownerId", + "schedule", + "systemDisabledAt", + "systemDisabledReason", + "timezone", + "updatedAt" ] }, - "ModelsContentValidatorReplaceBody": { + "SchedulesGetDestination": { "type": "object", "properties": { - "branch_id": { + "format": { "type": "string", - "description": "Optional branch ID" + "description": "Output format: pdf, png, csv, xlsx, json, link_only", + "example": "pdf" }, - "find": { + "id": { "type": "string", - "minLength": 1, - "description": "The string to find" + "format": "uuid", + "description": "Destination UUID" }, - "find_or_replace_type": { - "type": "string", - "enum": [ - "FIELD", - "TOPIC", - "VIEW" + "lastCompletedAt": { + "type": [ + "string", + "null" ], - "description": "Type of find/replace operation." + "format": "date-time", + "description": "Timestamp of last completed delivery" }, - "folder_paths": { + "lastStatus": { + "type": [ + "string", + "null" + ], + "description": "Status of last delivery: COMPLETE, ERROR, ERROR_DELIVERED, KILLED, CONDITION_UNMET" + }, + "metadata": { + "description": "Destination-specific configuration (type, recipients, credentials, etc.)" + }, + "recipients": { "type": "array", "items": { - "type": "string" + "$ref": "#/components/schemas/SchedulesGetRecipient" }, - "description": "Restrict replacement to documents in matching folder paths (prefix match). Documents with no folder are excluded unless \"\" is specified." - }, - "include_personal_folders": { - "type": "boolean", - "default": false, - "description": "Whether to include personal folders" - }, - "labels": { - "type": "string", - "description": "Comma-separated label names to scope replacement. Unknown labels return 400." - }, - "only_in_workbook_id": { - "type": "string", - "description": "Optional workbook ID to limit the replace scope" + "description": "Individual email recipients" }, - "replacement": { - "type": "string", - "minLength": 1, - "description": "The replacement string" + "userGroupRecipients": { + "type": "array", + "items": {}, + "description": "User group recipients" } }, "required": [ - "find", - "find_or_replace_type", - "replacement" + "format", + "id", + "lastCompletedAt", + "lastStatus", + "recipients", + "userGroupRecipients" ] }, - "ModelYamlResponse": { + "SchedulesGetRecipient": { "type": "object", "properties": { - "checksums": { - "type": "object", - "additionalProperties": { - "type": "string" - }, - "description": "Checksums for each file" + "id": { + "type": "string", + "format": "uuid", + "description": "Recipient ID" }, - "files": { + "membership": { "type": "object", - "additionalProperties": { - "type": "string" + "properties": { + "user": { + "type": "object", + "properties": { + "email": { + "type": "string", + "format": "email", + "description": "Recipient email" + }, + "name": { + "type": [ + "string", + "null" + ], + "description": "Recipient name" + } + }, + "required": [ + "email", + "name" + ] + } }, - "description": "YAML content for each file" - }, - "version": { - "type": "number", - "description": "Model version number" + "required": [ + "user" + ] }, - "viewNames": { - "type": "object", - "additionalProperties": {}, - "description": "View name mappings" + "membershipId": { + "type": "string", + "format": "uuid", + "description": "Membership ID" } }, "required": [ - "files", - "version" + "id", + "membership", + "membershipId" ] }, - "ModelYamlCreateRequestBody": { + "SchedulesRecipientsGetResponse": { "type": "object", "properties": { - "branchId": { - "type": "string", - "format": "uuid", - "description": "Branch ID for branch-aware operations" - }, - "fileName": { - "type": "string", - "minLength": 1, - "description": "File name to create or update" + "recipients": { + "type": "array", + "items": { + "$ref": "#/components/schemas/EmailRecipient" + }, + "description": "List of individual recipients (for email destinations)." }, - "mode": { + "type": { "type": "string", "enum": [ - "combined", - "extension", - "staged", - "merged", - "history" + "email", + "google_sheets", + "s3", + "sftp", + "slack", + "webhook" ], - "default": "combined", - "description": "IDE mode for YAML operations" + "description": "The schedule's destination type.", + "example": "email" }, - "commitMessage": { + "userGroupRecipients": { + "type": "array", + "items": { + "$ref": "#/components/schemas/UserGroupRecipient" + }, + "description": "List of user group recipients (for email destinations)." + } + }, + "required": [ + "type" + ] + }, + "EmailRecipient": { + "type": "object", + "properties": { + "email": { "type": "string", - "description": "Commit message for git sync" - }, - "fetchedAtMillis": { - "type": "number", - "description": "Timestamp when the file was fetched" - }, - "fullyResolved": { - "type": "boolean", - "default": false, - "description": "Treat the posted YAML as fully resolved (with the extends chain expanded). Only valid with mode=combined." + "format": "email", + "description": "Recipient's email address.", + "example": "user@example.com" }, - "previousChecksum": { + "id": { "type": "string", - "description": "Previous checksum for conflict detection" + "description": "Unique identifier for the recipient." }, - "yaml": { + "name": { "type": "string", - "description": "YAML content for the file" + "description": "Recipient's display name.", + "example": "John Doe" } }, "required": [ - "fileName", - "yaml" - ], - "additionalProperties": false + "email", + "id", + "name" + ] }, - "QueryRunResponse": { + "UserGroupRecipient": { "type": "object", "properties": { - "completedQueries": { - "type": "array", - "items": {}, - "description": "Queries that completed synchronously with their results." + "id": { + "type": "string", + "description": "User group ID." }, - "jobIds": { + "name": { + "type": "string", + "description": "User group name.", + "example": "Sales Team" + }, + "recipients": { "type": "array", "items": { - "type": "string" + "$ref": "#/components/schemas/EmailRecipient" }, - "description": "Job IDs for queries running asynchronously. Use /api/v1/query/wait to poll for results.", - "example": [ - "job_abc123", - "job_def456" - ] - }, - "plan": { - "description": "Query execution plan (only present if planOnly is true)." + "description": "List of recipients in the user group." } - } + }, + "required": [ + "id", + "name", + "recipients" + ] }, - "QueryTimeoutResponse": { + "SchedulesAddRecipientsResponse": { "type": "object", "properties": { - "detail": { - "type": "string", - "description": "Error message indicating the query timed out.", - "example": "Query timed out" + "addedGroupRecipientsCount": { + "type": "number", + "description": "Number of user group recipients added.", + "example": 1 }, - "remaining_job_ids": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Job IDs for queries that have not yet completed. Use /api/v1/query/wait to poll for results." + "addedRecipientsCount": { + "type": "number", + "description": "Number of individual recipients added.", + "example": 2 }, - "timed_out": { + "success": { "type": "boolean", - "enum": [ - true - ], - "description": "Always true for timeout responses.", + "description": "Whether the operation was successful.", "example": true } }, "required": [ - "detail", - "timed_out" + "addedGroupRecipientsCount", + "addedRecipientsCount", + "success" ] }, - "QueryRunBody": { + "SchedulesAddRecipientsBody": { "type": "object", "properties": { - "branchId": { - "type": "string", - "format": "uuid", - "description": "Optional model branch to run the query against. Must belong to the same shared model as the query. When omitted, the query runs against the shared model. Takes precedence over the legacy `?branch_id=` URL query parameter.", - "example": "550e8400-e29b-41d4-a716-446655440000" - }, - "cache": { - "type": "string", - "enum": [ - "disabled", - "normal", - "refresh", - "refresh_all" - ], - "description": "Cache policy for query execution. Controls whether to use cached results.", - "example": "normal" - }, - "formatResults": { - "type": "boolean", - "description": "Whether to format result values (e.g., apply number formatting). Only valid when resultType is specified." - }, - "planOnly": { - "type": "boolean", - "default": false, - "description": "If true, returns only the query execution plan without running the query." - }, - "query": { - "description": "The semantic query definition including fields, filters, sorts, and other query parameters." + "emails": { + "type": "array", + "items": { + "type": "string", + "format": "email" + }, + "default": [], + "description": "At least one email, userId, or userGroupId must be provided. Array of email addresses to add as recipients.", + "example": [ + "user@example.com" + ] }, - "resultType": { - "type": "string", - "enum": [ - "csv", - "json", - "xlsx" - ], - "description": "Output format for the results. If not specified, returns base64-encoded Arrow format." + "userGroupIds": { + "type": "array", + "items": { + "type": "string", + "format": "uuid" + }, + "default": [], + "description": "At least one email, userId, or userGroupId must be provided. Array of user group UUIDs to add as recipients.", + "example": [ + "123e4567-e89b-12d3-a456-426614174000" + ] }, - "userId": { - "type": "string", - "format": "uuid", - "description": "User ID to execute the query as (for row-level security). Only valid for org-scoped API keys.", - "example": "550e8400-e29b-41d4-a716-446655440000" + "userIds": { + "type": "array", + "items": { + "type": "string", + "format": "uuid" + }, + "default": [], + "description": "At least one email, userId, or userGroupId must be provided. Array of user UUIDs to add as recipients. Use the List users and List embed users endpoints to retrieve user IDs.", + "example": [ + "987fcdeb-51a2-43d7-9b56-254415f67890" + ] } } }, - "QueryWaitResponse": { + "SchedulesRemoveRecipientsResponse": { "type": "object", "properties": { - "results": { - "type": "array", - "items": {}, - "description": "Array of completed query results. Each result contains the query data or an error." + "removedGroupRecipientsCount": { + "type": "number", + "description": "Number of user group recipients removed.", + "example": 1 + }, + "removedRecipientsCount": { + "type": "number", + "description": "Number of individual recipients removed.", + "example": 2 + }, + "success": { + "type": "boolean", + "description": "Whether the operation was successful.", + "example": true } }, "required": [ - "results" + "removedGroupRecipientsCount", + "removedRecipientsCount", + "success" ] }, - "SchedulesListItem": { + "SchedulesRemoveRecipientsBody": { "type": "object", "properties": { - "alert": { - "type": "object", - "properties": { - "conditionQueryName": { - "type": [ - "string", - "null" - ], - "description": "Name of the query used for alert condition" - }, - "conditionType": { - "type": "string", - "description": "Type of alert condition: RESULTS_CHANGED, RESULTS_PRESENT, RESULTS_MISSING" - } + "emails": { + "type": "array", + "items": { + "type": "string", + "format": "email" }, - "required": [ - "conditionQueryName", - "conditionType" - ], - "description": "Alert configuration (only present for alert-type schedules)" - }, - "content": { - "type": "string", - "description": "Content type: dashboard or tile", - "example": "dashboard" - }, - "dashboardName": { - "type": "string", - "description": "Name of the dashboard", - "example": "Weekly Sales Report" - }, - "destinationType": { - "type": "string", - "description": "Delivery destination type: email, slack, webhook, sftp, s3, google_sheets", - "example": "email" - }, - "disabledAt": { - "type": [ - "string", - "null" - ], - "format": "date-time", - "description": "Timestamp when the schedule was paused (null if active)" - }, - "format": { - "type": "string", - "description": "Output format: pdf, png, csv, xlsx, json, link_only", - "example": "pdf" - }, - "id": { - "type": "string", - "format": "uuid", - "description": "Unique identifier for the schedule" - }, - "identifier": { - "type": "string", - "description": "Dashboard identifier", - "example": "12db1a0a" - }, - "lastCompletedAt": { - "type": [ - "string", - "null" - ], - "format": "date-time", - "description": "Timestamp of last completed delivery" - }, - "lastStatus": { - "type": [ - "string", - "null" - ], - "description": "Status of last delivery: COMPLETE, ERROR, ERROR_DELIVERED, KILLED, CONDITION_UNMET" + "default": [], + "description": "At least one email, userId, or userGroupId must be provided. Array of recipient email addresses to remove from the scheduled task.", + "example": [ + "user@example.com" + ] }, - "name": { - "type": "string", - "description": "Name of the schedule", - "example": "Weekly Sales Report" + "userGroupIds": { + "type": "array", + "items": { + "type": "string", + "format": "uuid" + }, + "default": [], + "description": "At least one email, userId, or userGroupId must be provided. Array of user group UUIDs to remove as recipients.", + "example": [ + "123e4567-e89b-12d3-a456-426614174000" + ] }, - "ownerId": { + "userIds": { + "type": "array", + "items": { + "type": "string", + "format": "uuid" + }, + "default": [], + "description": "At least one email, userId, or userGroupId must be provided. Array of recipient user UUIDs to remove from the scheduled task. Use the List users and List embed users endpoints to retrieve user IDs.", + "example": [ + "987fcdeb-51a2-43d7-9b56-254415f67890" + ] + } + } + }, + "SchedulesTransferOwnershipBody": { + "type": "object", + "properties": { + "userId": { "type": "string", "format": "uuid", - "description": "User ID of the schedule owner" - }, - "ownerName": { - "type": "string", - "description": "Display name of the schedule owner", - "example": "John Doe" - }, - "recipientCount": { - "type": "number", - "description": "Number of recipients (-1 for non-email destinations)", - "example": 5 - }, - "schedule": { - "type": "string", - "description": "AWS EventBridge cron expression (minute hour day-of-month month day-of-week year)", - "example": "0 9 ? * MON *" - }, - "slackRecipientType": { - "type": [ - "string", - "null" - ], - "description": "Slack recipient type: Channel or Users (null for non-Slack)" - }, - "systemDisabledAt": { - "type": [ - "string", - "null" - ], - "format": "date-time", - "description": "Timestamp when system disabled the schedule (null if not system-disabled)" - }, - "systemDisabledReason": { - "type": [ - "string", - "null" - ], - "description": "Reason for system disabling: missingQuery, noAccess, orphanedFilterConfigKeys" - }, - "timezone": { - "type": "string", - "description": "IANA timezone for the schedule", - "example": "America/New_York" + "description": "The UUID of the user to transfer schedule ownership to. Use the List users endpoint to retrieve user IDs. The new owner must be a member of the same organization, not be the current owner, and have permission to view the dashboard associated with the schedule.", + "example": "987fcdeb-51a2-43d7-9b56-254415f67890" } }, "required": [ - "content", - "dashboardName", - "destinationType", - "disabledAt", - "format", - "id", - "identifier", - "lastCompletedAt", - "lastStatus", - "name", - "ownerId", - "ownerName", - "recipientCount", - "schedule", - "slackRecipientType", - "systemDisabledAt", - "systemDisabledReason", - "timezone" + "userId" ] }, - "SchedulesGetResponse": { + "ScimUsersListResponse": { "type": "object", "properties": { - "conditionQueryMapKey": { - "type": [ - "string", - "null" - ], - "description": "Query key used for alert condition (null for standard schedules)" - }, - "conditionType": { - "type": [ - "string", - "null" - ], - "description": "Alert condition type: RESULTS_CHANGED, RESULTS_PRESENT, RESULTS_MISSING" + "Resources": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ScimUserResponse" + }, + "description": "List of SCIM users" }, - "createdAt": { - "type": "string", - "format": "date-time", - "description": "Creation timestamp" + "itemsPerPage": { + "type": "number", + "description": "Items per page" }, - "destinations": { + "schemas": { "type": "array", "items": { - "$ref": "#/components/schemas/SchedulesGetDestination" + "type": "string" }, - "description": "Delivery destination configurations" - }, - "disabledAt": { - "type": [ - "string", - "null" - ], - "format": "date-time", - "description": "Timestamp when the schedule was paused (null if active)" + "description": "SCIM schema URIs" }, - "entityId": { - "type": "string", - "description": "ID of the associated dashboard" + "startIndex": { + "type": "number", + "description": "Start index (1-based)" }, - "fanOut": { + "totalResults": { + "type": "number", + "description": "Total number of results" + } + }, + "required": [ + "Resources", + "itemsPerPage", + "schemas", + "startIndex", + "totalResults" + ] + }, + "ScimUserResponse": { + "type": "object", + "properties": { + "active": { "type": "boolean", - "description": "Whether personalized fan-out delivery is enabled", - "example": false + "description": "Whether the user is active" }, - "filterConfig": { - "description": "Applied dashboard filter configuration" + "displayName": { + "type": "string", + "description": "Display name" }, "id": { "type": "string", "format": "uuid", - "description": "Schedule UUID", - "example": "123e4567-e89b-12d3-a456-426614174000" - }, - "killJobsOnFailure": { - "type": "boolean", - "description": "Whether to stop the job if any queries fail", - "example": false + "description": "SCIM user ID" }, - "metadata": { - "description": "Schedule metadata including format options and delivery settings" + "schemas": { + "type": "array", + "items": { + "type": "string" + }, + "description": "SCIM schema URIs" }, - "name": { + "userName": { "type": "string", - "description": "Schedule name", - "example": "Weekly Sales Report" - }, - "organizationId": { + "format": "email", + "description": "Username (email)" + } + }, + "required": [ + "active", + "displayName", + "id", + "schemas", + "userName" + ] + }, + "ScimUserCreateRequest": { + "type": "object", + "properties": { + "displayName": { "type": "string", - "format": "uuid", - "description": "Organization UUID" + "description": "Display name of the user", + "example": "John Doe" }, - "owner": { + "urn:omni:params:1.0:UserAttribute": { "type": "object", - "properties": { - "name": { - "type": "string", - "description": "Schedule owner name" - } + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "array", + "items": { + "type": "number" + } + }, + { + "type": "null" + }, + { + "type": "boolean" + }, + { + "type": "object", + "properties": {} + } + ] }, - "required": [ - "name" - ] - }, - "ownerId": { - "type": "string", - "format": "uuid", - "description": "User ID of the schedule owner" - }, - "schedule": { - "type": "string", - "description": "AWS EventBridge cron expression (minute hour day-of-month month day-of-week year)", - "example": "0 9 ? * MON *" - }, - "systemDisabledAt": { - "type": [ - "string", - "null" - ], - "format": "date-time", - "description": "Timestamp when the system disabled the schedule" - }, - "systemDisabledReason": { - "type": [ - "string", - "null" - ], - "description": "Reason for system disabling: missingQuery, noAccess, orphanedFilterConfigKeys" - }, - "timezone": { - "type": "string", - "description": "IANA timezone for the schedule", - "example": "America/New_York" + "description": "Omni user attributes" }, - "updatedAt": { + "userName": { "type": "string", - "format": "date-time", - "description": "Last update timestamp" + "format": "email", + "description": "Email address (username) of the user", + "example": "user@example.com" } }, "required": [ - "conditionQueryMapKey", - "conditionType", - "createdAt", - "destinations", - "disabledAt", - "entityId", - "fanOut", - "id", - "killJobsOnFailure", - "name", - "organizationId", - "owner", - "ownerId", - "schedule", - "systemDisabledAt", - "systemDisabledReason", - "timezone", - "updatedAt" + "displayName", + "userName" ] }, - "SchedulesGetDestination": { + "ScimUserPutRequest": { "type": "object", "properties": { - "format": { - "type": "string", - "description": "Output format: pdf, png, csv, xlsx, json, link_only", - "example": "pdf" + "active": { + "type": "boolean", + "default": true, + "description": "Whether the user is active" }, - "id": { + "displayName": { "type": "string", - "format": "uuid", - "description": "Destination UUID" - }, - "lastCompletedAt": { - "type": [ - "string", - "null" - ], - "format": "date-time", - "description": "Timestamp of last completed delivery" - }, - "lastStatus": { - "type": [ - "string", - "null" - ], - "description": "Status of last delivery: COMPLETE, ERROR, ERROR_DELIVERED, KILLED, CONDITION_UNMET" + "description": "Display name of the user" }, - "metadata": { - "description": "Destination-specific configuration (type, recipients, credentials, etc.)" + "urn:ietf:params:scim:schemas:extension:enterprise:2.0:User": { + "type": "object", + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "array", + "items": { + "type": "number" + } + }, + { + "type": "null" + }, + { + "type": "boolean" + }, + { + "type": "object", + "properties": {} + } + ] + }, + "description": "Enterprise SCIM user attributes" }, - "recipients": { - "type": "array", - "items": { - "$ref": "#/components/schemas/SchedulesGetRecipient" + "urn:omni:params:1.0:UserAttribute": { + "type": "object", + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "array", + "items": { + "type": "number" + } + }, + { + "type": "null" + }, + { + "type": "boolean" + }, + { + "type": "object", + "properties": {} + } + ] }, - "description": "Individual email recipients" + "description": "Omni user attributes" }, - "userGroupRecipients": { - "type": "array", - "items": {}, - "description": "User group recipients" + "userName": { + "type": "string", + "format": "email", + "description": "Email address (username) of the user", + "example": "user@example.com" } }, "required": [ - "format", - "id", - "lastCompletedAt", - "lastStatus", - "recipients", - "userGroupRecipients" + "userName" ] }, - "SchedulesGetRecipient": { + "ScimUserPatchRequest": { "type": "object", "properties": { - "id": { - "type": "string", - "format": "uuid", - "description": "Recipient ID" - }, - "membership": { - "type": "object", - "properties": { - "user": { - "type": "object", - "properties": { - "email": { - "type": "string", - "format": "email", - "description": "Recipient email" - }, - "name": { - "type": [ - "string", - "null" - ], - "description": "Recipient name" - } + "Operations": { + "type": "array", + "items": { + "type": "object", + "properties": { + "op": { + "type": "string", + "enum": [ + "replace", + "Replace", + "add", + "Add", + "Remove", + "remove" + ] }, - "required": [ - "email", - "name" - ] - } + "path": { + "type": "string" + }, + "value": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "array", + "items": { + "type": "number" + } + }, + { + "type": "null" + }, + { + "type": "boolean" + }, + { + "type": "object", + "properties": { + "urn:ietf:params:scim:schemas:extension:enterprise:2.0:User": { + "type": "object", + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "array", + "items": { + "type": "number" + } + }, + { + "type": "null" + }, + { + "type": "boolean" + }, + { + "type": "object", + "properties": {} + } + ] + } + }, + "urn:omni:params:1.0:UserAttribute": { + "type": "object", + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "array", + "items": { + "type": "number" + } + }, + { + "type": "null" + }, + { + "type": "boolean" + }, + { + "type": "object", + "properties": {} + } + ] + } + }, + "active": { + "type": "boolean" + }, + "displayName": { + "type": "string" + }, + "userName": { + "type": "string", + "format": "email" + } + } + } + ] + } + }, + "required": [ + "op", + "value" + ] }, - "required": [ - "user" - ] + "minItems": 1, + "description": "List of patch operations to apply" }, - "membershipId": { - "type": "string", - "format": "uuid", - "description": "Membership ID" + "schemas": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "urn:ietf:params:scim:api:messages:2.0:PatchOp" + ] + }, + "description": "SCIM schema URIs" } }, "required": [ - "id", - "membership", - "membershipId" + "Operations", + "schemas" ] }, - "SchedulesRecipientsGetResponse": { + "ScimGroupsListResponse": { "type": "object", "properties": { - "recipients": { + "Resources": { "type": "array", "items": { - "$ref": "#/components/schemas/EmailRecipient" + "$ref": "#/components/schemas/ScimGroupResponse" }, - "description": "List of individual recipients (for email destinations)." + "description": "List of SCIM groups" }, - "type": { - "type": "string", - "enum": [ - "email", - "google_sheets", - "s3", - "sftp", - "slack", - "webhook" - ], - "description": "The schedule's destination type.", - "example": "email" + "itemsPerPage": { + "type": "number", + "description": "Items per page" }, - "userGroupRecipients": { + "schemas": { "type": "array", "items": { - "$ref": "#/components/schemas/UserGroupRecipient" + "type": "string" }, - "description": "List of user group recipients (for email destinations)." + "description": "SCIM schema URIs" + }, + "startIndex": { + "type": "number", + "description": "Start index (1-based)" + }, + "totalResults": { + "type": "number", + "description": "Total number of results" } }, "required": [ - "type" + "Resources", + "itemsPerPage", + "schemas", + "startIndex", + "totalResults" ] }, - "EmailRecipient": { + "ScimGroupResponse": { "type": "object", "properties": { - "email": { + "displayName": { "type": "string", - "format": "email", - "description": "Recipient's email address.", - "example": "user@example.com" + "description": "Group display name" }, "id": { "type": "string", - "description": "Unique identifier for the recipient." + "description": "SCIM group ID (miniUuid)" }, - "name": { - "type": "string", - "description": "Recipient's display name.", - "example": "John Doe" + "members": { + "type": "array", + "items": { + "type": "object", + "properties": { + "display": { + "type": "string", + "description": "Member display name" + }, + "value": { + "type": "string", + "format": "uuid", + "description": "Member user ID" + } + }, + "required": [ + "display", + "value" + ] + }, + "description": "Group members" + }, + "schemas": { + "type": "array", + "items": { + "type": "string" + }, + "description": "SCIM schema URIs" } }, "required": [ - "email", + "displayName", "id", - "name" + "schemas" ] }, - "UserGroupRecipient": { + "ScimGroupsCreateBody": { "type": "object", "properties": { - "id": { - "type": "string", - "description": "User group ID." - }, - "name": { + "displayName": { "type": "string", - "description": "User group name.", - "example": "Sales Team" + "description": "Display name of the group", + "example": "Engineering Team" }, - "recipients": { + "members": { "type": "array", "items": { - "$ref": "#/components/schemas/EmailRecipient" + "type": "object", + "properties": { + "value": { + "type": "string", + "format": "uuid", + "description": "User membership ID", + "example": "550e8400-e29b-41d4-a716-446655440000" + } + }, + "required": [ + "value" + ] }, - "description": "List of recipients in the user group." + "default": [], + "description": "List of group members" } }, "required": [ - "id", - "name", - "recipients" + "displayName" ] }, - "SchedulesAddRecipientsResponse": { + "ScimGroupsReplaceBody": { "type": "object", "properties": { - "addedGroupRecipientsCount": { - "type": "number", - "description": "Number of user group recipients added.", - "example": 1 - }, - "addedRecipientsCount": { - "type": "number", - "description": "Number of individual recipients added.", - "example": 2 + "displayName": { + "type": "string", + "description": "Display name of the group", + "example": "Engineering Team" }, - "success": { - "type": "boolean", - "description": "Whether the operation was successful.", - "example": true + "members": { + "type": "array", + "items": { + "type": "object", + "properties": { + "display": { + "type": "string", + "description": "Display name of the member", + "example": "john.doe@example.com" + }, + "value": { + "type": "string", + "format": "uuid", + "description": "User membership ID", + "example": "550e8400-e29b-41d4-a716-446655440000" + } + }, + "required": [ + "display", + "value" + ] + }, + "description": "List of group members" } }, "required": [ - "addedGroupRecipientsCount", - "addedRecipientsCount", - "success" + "displayName", + "members" ] }, - "SchedulesAddRecipientsBody": { + "ScimGroupsPatchBody": { "type": "object", "properties": { - "emails": { - "type": "array", - "items": { - "type": "string", - "format": "email" - }, - "default": [], - "description": "At least one email, userId, or userGroupId must be provided. Array of email addresses to add as recipients.", - "example": [ - "user@example.com" - ] - }, - "userGroupIds": { + "Operations": { "type": "array", "items": { - "type": "string", - "format": "uuid" + "anyOf": [ + { + "type": "object", + "properties": { + "op": { + "type": "string", + "enum": [ + "replace", + "Replace" + ], + "description": "Operation type", + "example": "replace" + }, + "value": { + "type": "object", + "properties": { + "displayName": { + "type": "string", + "description": "New display name", + "example": "Engineering Team" + }, + "id": { + "type": "string", + "description": "Group ID" + } + }, + "required": [ + "displayName" + ] + } + }, + "required": [ + "op", + "value" + ] + }, + { + "type": "object", + "properties": { + "op": { + "type": "string", + "enum": [ + "remove", + "Remove" + ], + "description": "Operation type", + "example": "remove" + }, + "path": { + "type": "string", + "pattern": "members\\[value eq \"(.{36})\"\\]", + "description": "SCIM path for member to remove", + "example": "members[value eq \"550e8400-e29b-41d4-a716-446655440000\"]" + } + }, + "required": [ + "op", + "path" + ] + }, + { + "type": "object", + "properties": { + "op": { + "type": "string", + "enum": [ + "add", + "Add" + ], + "description": "Operation type", + "example": "add" + }, + "path": { + "type": "string", + "enum": [ + "members" + ], + "description": "Path for members", + "example": "members" + }, + "value": { + "type": "array", + "items": { + "type": "object", + "properties": { + "display": { + "type": "string", + "description": "Display name of the member", + "example": "john.doe@example.com" + }, + "value": { + "type": "string", + "format": "uuid", + "description": "User membership ID", + "example": "550e8400-e29b-41d4-a716-446655440000" + } + }, + "required": [ + "value" + ] + } + } + }, + "required": [ + "op", + "path", + "value" + ] + }, + { + "type": "object", + "properties": { + "op": { + "type": "string", + "enum": [ + "replace", + "Replace" + ], + "description": "Operation type", + "example": "replace" + }, + "path": { + "type": "string", + "enum": [ + "members", + "displayName" + ], + "description": "Path for attribute to replace", + "example": "members" + }, + "value": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "object", + "properties": { + "display": { + "type": "string", + "description": "Display name of the member", + "example": "john.doe@example.com" + }, + "value": { + "type": "string", + "format": "uuid", + "description": "User membership ID", + "example": "550e8400-e29b-41d4-a716-446655440000" + } + }, + "required": [ + "value" + ] + } + }, + { + "type": "string" + } + ] + } + }, + "required": [ + "op", + "path", + "value" + ] + } + ] }, - "default": [], - "description": "At least one email, userId, or userGroupId must be provided. Array of user group UUIDs to add as recipients.", - "example": [ - "123e4567-e89b-12d3-a456-426614174000" - ] + "description": "List of SCIM patch operations" }, - "userIds": { + "schemas": { "type": "array", "items": { "type": "string", - "format": "uuid" + "enum": [ + "urn:ietf:params:scim:api:messages:2.0:PatchOp" + ] }, - "default": [], - "description": "At least one email, userId, or userGroupId must be provided. Array of user UUIDs to add as recipients. Use the List users and List embed users endpoints to retrieve user IDs.", - "example": [ - "987fcdeb-51a2-43d7-9b56-254415f67890" - ] - } - } - }, - "SchedulesRemoveRecipientsResponse": { - "type": "object", - "properties": { - "removedGroupRecipientsCount": { - "type": "number", - "description": "Number of user group recipients removed.", - "example": 1 - }, - "removedRecipientsCount": { - "type": "number", - "description": "Number of individual recipients removed.", - "example": 2 - }, - "success": { - "type": "boolean", - "description": "Whether the operation was successful.", - "example": true + "description": "SCIM schema URIs" } }, "required": [ - "removedGroupRecipientsCount", - "removedRecipientsCount", - "success" + "Operations", + "schemas" ] }, - "SchedulesRemoveRecipientsBody": { + "DocumentExportResponse": { "type": "object", "properties": { - "emails": { - "type": "array", - "items": { - "type": "string", - "format": "email" - }, - "default": [], - "description": "At least one email, userId, or userGroupId must be provided. Array of recipient email addresses to remove from the scheduled task.", - "example": [ - "user@example.com" - ] - }, - "userGroupIds": { - "type": "array", - "items": { - "type": "string", - "format": "uuid" - }, - "default": [], - "description": "At least one email, userId, or userGroupId must be provided. Array of user group UUIDs to remove as recipients.", - "example": [ - "123e4567-e89b-12d3-a456-426614174000" - ] + "dashboard": { + "description": "Dashboard configuration and layout" }, - "userIds": { - "type": "array", - "items": { - "type": "string", - "format": "uuid" + "document": { + "type": "object", + "properties": { + "ephemeral": { + "type": "string" + }, + "name": { + "type": "string" + } }, - "default": [], - "description": "At least one email, userId, or userGroupId must be provided. Array of recipient user UUIDs to remove from the scheduled task. Use the List users and List embed users endpoints to retrieve user IDs.", - "example": [ - "987fcdeb-51a2-43d7-9b56-254415f67890" + "required": [ + "name" ] - } - } - }, - "SchedulesTransferOwnershipBody": { - "type": "object", - "properties": { - "userId": { - "type": "string", - "format": "uuid", - "description": "The UUID of the user to transfer schedule ownership to. Use the List users endpoint to retrieve user IDs. The new owner must be a member of the same organization, not be the current owner, and have permission to view the dashboard associated with the schedule.", - "example": "987fcdeb-51a2-43d7-9b56-254415f67890" - } - }, - "required": [ - "userId" - ] - }, - "ScimUsersListResponse": { - "type": "object", - "properties": { - "Resources": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ScimUserResponse" - }, - "description": "List of SCIM users" }, - "itemsPerPage": { - "type": "number", - "description": "Items per page" + "exportVersion": { + "type": "string" }, - "schemas": { - "type": "array", - "items": { - "type": "string" - }, - "description": "SCIM schema URIs" + "fileUploads": { + "type": "object", + "additionalProperties": {} }, - "startIndex": { - "type": "number", - "description": "Start index (1-based)" + "queryModels": { + "type": "object", + "additionalProperties": {} }, - "totalResults": { - "type": "number", - "description": "Total number of results" - } + "workbookModel": {} }, "required": [ - "Resources", - "itemsPerPage", - "schemas", - "startIndex", - "totalResults" + "document", + "exportVersion", + "queryModels" ] }, - "ScimUserResponse": { + "DocumentImportResponse": { "type": "object", "properties": { - "active": { - "type": "boolean", - "description": "Whether the user is active" - }, - "displayName": { - "type": "string", - "description": "Display name" - }, - "id": { + "documentId": { "type": "string", "format": "uuid", - "description": "SCIM user ID" - }, - "schemas": { - "type": "array", - "items": { - "type": "string" - }, - "description": "SCIM schema URIs" + "description": "ID of the imported document" }, - "userName": { + "identifier": { "type": "string", - "format": "email", - "description": "Username (email)" + "description": "Document identifier (miniUuid)" } }, "required": [ - "active", - "displayName", - "id", - "schemas", - "userName" + "documentId", + "identifier" ] }, - "ScimUserCreateRequest": { + "DocumentImportBody": { "type": "object", "properties": { - "displayName": { + "baseModelId": { "type": "string", - "description": "Display name of the user", - "example": "John Doe" + "format": "uuid", + "description": "Base model ID for the imported document" }, - "urn:omni:params:1.0:UserAttribute": { + "dashboard": { + "description": "Dashboard export data" + }, + "document": { "type": "object", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "array", - "items": { - "type": "string" - } - }, - { - "type": "array", - "items": { - "type": "number" - } - }, - { - "type": "null" - }, - { - "type": "boolean" - }, - { - "type": "object", - "properties": {} - } - ] + "properties": { + "ephemeral": { + "type": "string" + }, + "name": { + "type": "string" + } }, - "description": "Omni user attributes" - }, - "userName": { - "type": "string", - "format": "email", - "description": "Email address (username) of the user", - "example": "user@example.com" - } - }, - "required": [ - "displayName", - "userName" - ] - }, - "ScimUserPutRequest": { - "type": "object", - "properties": { - "active": { - "type": "boolean", - "default": true, - "description": "Whether the user is active" + "required": [ + "name" + ] }, - "displayName": { + "exportVersion": { "type": "string", - "description": "Display name of the user" + "enum": [ + "0.1" + ] }, - "urn:ietf:params:scim:schemas:extension:enterprise:2.0:User": { + "fileUploads": { "type": "object", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "array", - "items": { - "type": "string" - } - }, - { - "type": "array", - "items": { - "type": "number" - } - }, - { - "type": "null" - }, - { - "type": "boolean" - }, - { - "type": "object", - "properties": {} - } - ] - }, - "description": "Enterprise SCIM user attributes" + "additionalProperties": {} }, - "urn:omni:params:1.0:UserAttribute": { + "folderPath": { + "type": "string" + }, + "identifier": { + "type": "string" + }, + "queryModels": { "type": "object", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "array", - "items": { - "type": "string" - } - }, - { - "type": "array", - "items": { - "type": "number" - } - }, - { - "type": "null" - }, - { - "type": "boolean" - }, - { - "type": "object", - "properties": {} - } - ] - }, - "description": "Omni user attributes" + "additionalProperties": {} }, - "userName": { - "type": "string", - "format": "email", - "description": "Email address (username) of the user", - "example": "user@example.com" - } + "workbookModel": {} }, "required": [ - "userName" + "baseModelId", + "document", + "exportVersion", + "queryModels" ] }, - "ScimUserPatchRequest": { + "UserAttributesListResponse": { "type": "object", "properties": { - "Operations": { + "records": { "type": "array", "items": { "type": "object", "properties": { - "op": { - "type": "string", - "enum": [ - "replace", - "Replace", - "add", - "Add", - "Remove", - "remove" - ] - }, - "path": { - "type": "string" - }, - "value": { + "default_value": { "anyOf": [ { "type": "string" @@ -6614,1988 +29478,3177 @@ { "type": "array", "items": { - "type": "string" - } - }, - { - "type": "array", - "items": { - "type": "number" + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + } + ] } }, { "type": "null" - }, - { - "type": "boolean" - }, - { - "type": "object", - "properties": { - "active": { - "type": "boolean" - }, - "displayName": { - "type": "string" - }, - "userName": { - "type": "string", - "format": "email" - } - } } - ] + ], + "description": "Default value applied when no user-specific value is set. When multiple_values is true, this is an array. Null if no default is configured.", + "example": "us-east" + }, + "description": { + "type": [ + "string", + "null" + ], + "description": "Human-readable description of the attribute and its purpose", + "example": "User region for row-level security filtering" + }, + "id": { + "type": "string", + "description": "Unique identifier for custom attributes. Empty string for system-defined attributes.", + "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" + }, + "label": { + "type": "string", + "description": "Display name shown in the Omni UI", + "example": "Region" + }, + "multiple_values": { + "type": "boolean", + "description": "Whether the attribute accepts an array of values. When true, default_value and user-specific values are arrays.", + "example": false + }, + "name": { + "type": "string", + "description": "Reference name used in model SQL and in embed SSO URL parameters", + "example": "region" + }, + "system": { + "type": "boolean", + "description": "System-defined attributes (e.g. omni_user_id, omni_user_email) are built-in and read-only. Custom attributes have system=false.", + "example": false + }, + "type": { + "type": "string", + "enum": [ + "String", + "Number" + ], + "description": "Data type that determines valid values. String attributes accept text, Number attributes accept numeric values stored as strings for precision.", + "example": "String" } }, - "required": [ - "op", - "value" - ] + "required": [ + "default_value", + "description", + "id", + "label", + "multiple_values", + "name", + "system", + "type" + ] + }, + "description": "All user attribute definitions in the organization, including both system-defined and custom attributes" + } + }, + "required": [ + "records" + ] + }, + "UploadsListResponse": { + "type": "object", + "properties": { + "pageInfo": { + "$ref": "#/components/schemas/PageInfo" + }, + "records": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Upload" + } + } + }, + "required": [ + "pageInfo", + "records" + ] + }, + "Upload": { + "type": "object", + "properties": { + "connection_id": { + "type": "string", + "format": "uuid", + "description": "Connection ID the upload is associated with" + }, + "created_at": { + "type": "string", + "format": "date-time", + "description": "When the file was uploaded" + }, + "file_name": { + "type": "string", + "description": "Original file name", + "example": "users.csv" + }, + "id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the upload" + }, + "in_db_as_table_name": { + "type": [ + "string", + "null" + ], + "description": "Database table name if uploaded to database scratch schema" + }, + "model_id": { + "type": [ + "string", + "null" + ], + "format": "uuid", + "description": "Model ID the upload is associated with (inferred from connection's shared model if not explicitly set)" + }, + "size_bytes": { + "type": [ + "number", + "null" + ], + "description": "File size in bytes" + }, + "updated_at": { + "type": "string", + "format": "date-time", + "description": "Last update timestamp" + }, + "uploaded_by_user": { + "type": [ + "object", + "null" + ], + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "User ID of the uploader" + }, + "name": { + "type": "string", + "description": "Name of the user who uploaded the file" + } }, - "minItems": 1, - "description": "List of patch operations to apply" + "required": [ + "id", + "name" + ], + "description": "User who uploaded the file" }, - "schemas": { - "type": "array", - "items": { - "type": "string", - "enum": [ - "urn:ietf:params:scim:api:messages:2.0:PatchOp" - ] - }, - "description": "SCIM schema URIs" + "view_name": { + "type": "string", + "description": "View name associated with the upload" } }, "required": [ - "Operations", - "schemas" + "connection_id", + "created_at", + "file_name", + "id", + "in_db_as_table_name", + "model_id", + "size_bytes", + "updated_at", + "uploaded_by_user", + "view_name" ] }, - "ScimGroupsListResponse": { + "UploadCreateResponse": { "type": "object", "properties": { - "Resources": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ScimGroupResponse" - }, - "description": "List of SCIM groups" + "fileName": { + "type": "string", + "description": "Original file name", + "example": "users.csv" }, - "itemsPerPage": { - "type": "number", - "description": "Items per page" + "id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for the upload" }, - "schemas": { - "type": "array", - "items": { - "type": "string" - }, - "description": "SCIM schema URIs" + "inDbAsTableName": { + "type": "string", + "description": "Database table name in the scratch schema" }, - "startIndex": { - "type": "number", - "description": "Start index (1-based)" + "modelId": { + "type": "string", + "format": "uuid", + "description": "Model ID the view was created in" }, - "totalResults": { - "type": "number", - "description": "Total number of results" + "rowCount": { + "type": "integer", + "description": "Number of rows in the uploaded file" + }, + "truncated": { + "type": "boolean", + "description": "Whether the file was truncated due to row limit" + }, + "viewCreated": { + "type": "boolean", + "description": "Whether a view was created in the model" + }, + "viewName": { + "type": "string", + "description": "Name of the view created" } }, "required": [ - "Resources", - "itemsPerPage", - "schemas", - "startIndex", - "totalResults" + "fileName", + "id", + "inDbAsTableName", + "modelId", + "rowCount", + "truncated", + "viewCreated", + "viewName" ] }, - "ScimGroupResponse": { + "UploadCreateBody": { "type": "object", "properties": { - "displayName": { + "branchId": { "type": "string", - "description": "Group display name" + "format": "uuid", + "description": "UUID of the branch to create the view in (mutually exclusive with branchName)" }, - "id": { + "branchName": { "type": "string", - "description": "SCIM group ID (miniUuid)" + "description": "Name of the branch to create the view in (mutually exclusive with branchId)" }, - "members": { - "type": "array", - "items": { - "type": "object", - "properties": { - "display": { - "type": "string", - "description": "Member display name" - }, - "value": { - "type": "string", - "format": "uuid", - "description": "Member user ID" - } - }, - "required": [ - "display", - "value" - ] - }, - "description": "Group members" + "file": { + "type": "string", + "description": "The CSV file to upload", + "format": "binary" }, - "schemas": { - "type": "array", - "items": { - "type": "string" - }, - "description": "SCIM schema URIs" + "modelId": { + "type": "string", + "format": "uuid", + "description": "UUID of the model to create the view in" + }, + "viewName": { + "type": "string", + "description": "Override the view name (defaults to sanitized file name)" } }, "required": [ - "displayName", - "id", - "schemas" + "file", + "modelId" ] }, - "ScimGroupsCreateBody": { + "UploadDeleteResponse": { "type": "object", "properties": { - "displayName": { - "type": "string", - "description": "Display name of the group", - "example": "Engineering Team" - }, - "members": { - "type": "array", - "items": { - "type": "object", - "properties": { - "value": { - "type": "string", - "format": "uuid", - "description": "User membership ID", - "example": "550e8400-e29b-41d4-a716-446655440000" - } - }, - "required": [ - "value" - ] - }, - "default": [], - "description": "List of group members" + "success": { + "type": "boolean", + "description": "Whether the deletion was successful" } }, "required": [ - "displayName" + "success" ] }, - "ScimGroupsReplaceBody": { + "UsersGetModelRolesResponse": { "type": "object", "properties": { - "displayName": { + "membershipId": { "type": "string", - "description": "Display name of the group", - "example": "Engineering Team" - }, - "members": { - "type": "array", - "items": { - "type": "object", - "properties": { - "display": { - "type": "string", - "description": "Display name of the member", - "example": "john.doe@example.com" - }, - "value": { - "type": "string", - "format": "uuid", - "description": "User membership ID", - "example": "550e8400-e29b-41d4-a716-446655440000" - } - }, - "required": [ - "display", - "value" - ] + "format": "uuid", + "description": "The user membership ID" + }, + "results": { + "type": "array", + "items": { + "$ref": "#/components/schemas/RoleAssignmentResult" }, - "description": "List of group members" + "description": "List of role assignments" } }, "required": [ - "displayName", - "members" + "membershipId", + "results" ] }, - "ScimGroupsPatchBody": { + "RoleAssignmentResult": { "type": "object", "properties": { - "Operations": { - "type": "array", - "items": { - "anyOf": [ - { - "type": "object", - "properties": { - "op": { - "type": "string", - "enum": [ - "replace", - "Replace" - ], - "description": "Operation type", - "example": "replace" - }, - "value": { - "type": "object", - "properties": { - "displayName": { - "type": "string", - "description": "New display name", - "example": "Engineering Team" - }, - "id": { - "type": "string", - "description": "Group ID" - } - }, - "required": [ - "displayName" - ] - } - }, - "required": [ - "op", - "value" - ] - }, - { - "type": "object", - "properties": { - "op": { - "type": "string", - "enum": [ - "remove", - "Remove" - ], - "description": "Operation type", - "example": "remove" - }, - "path": { - "type": "string", - "pattern": "members\\[value eq \"(.{36})\"\\]", - "description": "SCIM path for member to remove", - "example": "members[value eq \"550e8400-e29b-41d4-a716-446655440000\"]" - } - }, - "required": [ - "op", - "path" - ] - }, - { - "type": "object", - "properties": { - "op": { - "type": "string", - "enum": [ - "add", - "Add" - ], - "description": "Operation type", - "example": "add" - }, - "path": { - "type": "string", - "enum": [ - "members" - ], - "description": "Path for members", - "example": "members" - }, - "value": { - "type": "array", - "items": { - "type": "object", - "properties": { - "display": { - "type": "string", - "description": "Display name of the member", - "example": "john.doe@example.com" - }, - "value": { - "type": "string", - "format": "uuid", - "description": "User membership ID", - "example": "550e8400-e29b-41d4-a716-446655440000" - } - }, - "required": [ - "value" - ] - } - } - }, - "required": [ - "op", - "path", - "value" - ] - }, - { - "type": "object", - "properties": { - "op": { - "type": "string", - "enum": [ - "replace", - "Replace" - ], - "description": "Operation type", - "example": "replace" - }, - "path": { - "type": "string", - "enum": [ - "members", - "displayName" - ], - "description": "Path for attribute to replace", - "example": "members" - }, - "value": { - "anyOf": [ - { - "type": "array", - "items": { - "type": "object", - "properties": { - "display": { - "type": "string", - "description": "Display name of the member", - "example": "john.doe@example.com" - }, - "value": { - "type": "string", - "format": "uuid", - "description": "User membership ID", - "example": "550e8400-e29b-41d4-a716-446655440000" - } - }, - "required": [ - "value" - ] - } - }, - { - "type": "string" - } - ] - } - }, - "required": [ - "op", - "path", - "value" - ] - } - ] + "baseRole": { + "type": "string", + "description": "The base role definition name", + "example": "VIEWER" + }, + "connectionId": { + "type": "string", + "format": "uuid", + "description": "Connection this role applies to" + }, + "from": { + "$ref": "#/components/schemas/RoleOrigin" + }, + "modelId": { + "type": "string", + "format": "uuid", + "description": "Model this role applies to" + }, + "priority": { + "type": "number", + "description": "Priority for role resolution (higher = more permissive)" + }, + "resolved": { + "type": "boolean", + "description": "Whether this is the resolved (effective) role" + }, + "roleName": { + "type": "string", + "description": "The role name (base or custom)", + "example": "VIEWER" + } + }, + "required": [ + "baseRole", + "connectionId", + "from", + "modelId", + "priority", + "resolved", + "roleName" + ] + }, + "RoleOrigin": { + "oneOf": [ + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "USER" + ], + "description": "Role assigned directly to user" + } }, - "description": "List of SCIM patch operations" + "required": [ + "type" + ] + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "ORG" + ], + "description": "Role inherited from organization" + } + }, + "required": [ + "type" + ] }, - "schemas": { - "type": "array", - "items": { - "type": "string", - "enum": [ - "urn:ietf:params:scim:api:messages:2.0:PatchOp" - ] + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "BASE" + ], + "description": "Connection base role" + } }, - "description": "SCIM schema URIs" - } - }, - "required": [ - "Operations", - "schemas" - ] - }, - "DocumentExportResponse": { - "type": "object", - "properties": { - "dashboard": { - "description": "Dashboard configuration and layout" + "required": [ + "type" + ] }, - "document": { + { "type": "object", "properties": { - "ephemeral": { - "type": "string" + "depth": { + "type": "number", + "description": "Nesting depth of the group" + }, + "miniUuid": { + "type": "string", + "description": "Short identifier of the group", + "example": "abc123" }, "name": { - "type": "string" + "type": "string", + "description": "Name of the group", + "example": "Engineering Team" + }, + "type": { + "type": "string", + "enum": [ + "GROUP" + ], + "description": "Role inherited from group membership" } }, "required": [ - "name" + "depth", + "miniUuid", + "name", + "type" ] + } + ], + "description": "Origin of this role assignment" + }, + "UsersAssignModelRoleResponse": { + "type": "object", + "properties": { + "connectionId": { + "type": "string", + "format": "uuid", + "description": "The connection ID for this role assignment" }, - "exportVersion": { - "type": "string" - }, - "fileUploads": { - "type": "object", - "additionalProperties": {} + "membershipId": { + "type": "string", + "format": "uuid", + "description": "The user membership ID" }, - "queryModels": { - "type": "object", - "additionalProperties": {} + "modelId": { + "type": "string", + "format": "uuid", + "description": "The model ID for this role assignment" }, - "workbookModel": {} + "roleName": { + "type": "string", + "description": "The assigned role name", + "example": "VIEWER" + } }, "required": [ - "document", - "exportVersion", - "queryModels" + "connectionId", + "membershipId", + "modelId", + "roleName" ] }, - "DocumentImportResponse": { + "UsersAssignModelRoleBody": { "type": "object", "properties": { - "documentId": { + "connectionId": { "type": "string", "format": "uuid", - "description": "ID of the imported document" + "description": "Connection ID for connection-level role assignment. Required if modelId not provided.", + "example": "550e8400-e29b-41d4-a716-446655440000" }, - "identifier": { + "modelId": { "type": "string", - "description": "Document identifier (miniUuid)" + "format": "uuid", + "description": "Model ID for model-level role assignment. Required if connectionId not provided.", + "example": "550e8400-e29b-41d4-a716-446655440000" + }, + "roleName": { + "type": "string", + "minLength": 1, + "description": "Name of the role to assign (base or custom role)", + "example": "VIEWER" } }, "required": [ - "documentId", - "identifier" + "roleName" ] }, - "DocumentImportBody": { + "UsersListEmailOnlyResponse": { "type": "object", "properties": { - "baseModelId": { - "type": "string", - "format": "uuid", - "description": "Base model ID for the imported document" - }, - "dashboard": { - "description": "Dashboard export data" + "pageInfo": { + "$ref": "#/components/schemas/PageInfo" }, - "document": { - "type": "object", - "properties": { - "ephemeral": { - "type": "string" + "records": { + "type": "array", + "items": { + "type": "object", + "properties": { + "email": { + "type": "string", + "description": "User email address", + "example": "user@example.com" + }, + "user_attributes": { + "type": "object", + "additionalProperties": {}, + "description": "User attributes as key-value pairs" + }, + "user_id": { + "type": "string", + "format": "uuid", + "description": "User ID" + } }, - "name": { - "type": "string" - } - }, - "required": [ - "name" - ] - }, - "exportVersion": { + "required": [ + "email", + "user_attributes", + "user_id" + ] + } + } + }, + "required": [ + "pageInfo", + "records" + ] + }, + "UsersCreateEmailOnlyResponse": { + "type": "object", + "properties": { + "email": { "type": "string", - "enum": [ - "0.1" - ] - }, - "fileUploads": { - "type": "object", - "additionalProperties": {} - }, - "folderPath": { - "type": "string" + "format": "email", + "description": "Email address of the created user", + "example": "user@example.com" }, - "identifier": { - "type": "string" + "userId": { + "type": "string", + "format": "uuid", + "description": "ID of the created user" + } + }, + "required": [ + "email", + "userId" + ] + }, + "UsersCreateEmailOnlyBody": { + "type": "object", + "properties": { + "email": { + "type": "string", + "format": "email", + "description": "Email address for the user", + "example": "user@example.com" }, - "queryModels": { + "userAttributes": { "type": "object", - "additionalProperties": {} - }, - "workbookModel": {} + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "type": "null" + } + ] + }, + "description": "Optional user attributes as key-value pairs" + } + }, + "required": [ + "email" + ] + }, + "UsersCreateEmailOnlyBulkResponse": { + "type": "object", + "properties": { + "results": { + "type": "array", + "items": { + "type": "object", + "properties": { + "email": { + "type": "string", + "format": "email", + "description": "Email address of the created user", + "example": "user@example.com" + }, + "userId": { + "type": "string", + "format": "uuid", + "description": "ID of the created user" + } + }, + "required": [ + "email", + "userId" + ] + }, + "description": "Results for each created user" + } }, "required": [ - "baseModelId", - "document", - "exportVersion", - "queryModels" + "results" ] }, - "UserAttributesListResponse": { + "UsersCreateEmailOnlyBulkBody": { "type": "object", "properties": { - "records": { + "users": { "type": "array", "items": { "type": "object", "properties": { - "default_value": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "array", - "items": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - } - ] - } - }, - { - "type": "null" - } - ], - "description": "Default value applied when no user-specific value is set. When multiple_values is true, this is an array. Null if no default is configured.", - "example": "us-east" - }, - "description": { - "type": [ - "string", - "null" - ], - "description": "Human-readable description of the attribute and its purpose", - "example": "User region for row-level security filtering" - }, - "id": { - "type": "string", - "description": "Unique identifier for custom attributes. Empty string for system-defined attributes.", - "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" - }, - "label": { - "type": "string", - "description": "Display name shown in the Omni UI", - "example": "Region" - }, - "multiple_values": { - "type": "boolean", - "description": "Whether the attribute accepts an array of values. When true, default_value and user-specific values are arrays.", - "example": false - }, - "name": { + "email": { "type": "string", - "description": "Reference name used in model SQL and in embed SSO URL parameters", - "example": "region" - }, - "system": { - "type": "boolean", - "description": "System-defined attributes (e.g. omni_user_id, omni_user_email) are built-in and read-only. Custom attributes have system=false.", - "example": false + "format": "email", + "description": "Email address for the user", + "example": "user@example.com" }, - "type": { - "type": "string", - "enum": [ - "String", - "Number" - ], - "description": "Data type that determines valid values. String attributes accept text, Number attributes accept numeric values stored as strings for precision.", - "example": "String" + "userAttributes": { + "type": "object", + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "type": "null" + } + ] + }, + "description": "Optional user attributes as key-value pairs" } }, "required": [ - "default_value", - "description", - "id", - "label", - "multiple_values", - "name", - "system", - "type" + "email" ] }, - "description": "All user attribute definitions in the organization, including both system-defined and custom attributes" + "minItems": 1, + "maxItems": 20, + "description": "Array of users to create (1-20 users)" } }, "required": [ - "records" + "users" ] }, - "UploadsListResponse": { + "UserGroupsGetModelRolesResponse": { "type": "object", "properties": { - "pageInfo": { - "$ref": "#/components/schemas/PageInfo" - }, - "records": { + "results": { "type": "array", "items": { - "$ref": "#/components/schemas/Upload" - } + "$ref": "#/components/schemas/UserGroupRoleAssignmentResult" + }, + "description": "List of role assignments" + }, + "userGroupId": { + "type": "string", + "description": "The user group short identifier", + "example": "abc123" } }, "required": [ - "pageInfo", - "records" + "results", + "userGroupId" ] }, - "Upload": { + "UserGroupRoleAssignmentResult": { "type": "object", "properties": { - "connection_id": { + "baseRole": { + "type": "string", + "description": "The base role definition name", + "example": "VIEWER" + }, + "connectionId": { "type": "string", "format": "uuid", - "description": "Connection ID the upload is associated with" + "description": "Connection this role applies to" }, - "created_at": { + "from": { + "$ref": "#/components/schemas/UserGroupRoleOrigin" + }, + "modelId": { "type": "string", - "format": "date-time", - "description": "When the file was uploaded" + "format": "uuid", + "description": "Model this role applies to" }, - "file_name": { + "priority": { + "type": "number", + "description": "Priority for role resolution (higher = more permissive)" + }, + "roleName": { "type": "string", - "description": "Original file name", - "example": "users.csv" + "description": "The role name (base or custom)", + "example": "VIEWER" + } + }, + "required": [ + "baseRole", + "connectionId", + "from", + "modelId", + "priority", + "roleName" + ] + }, + "UserGroupRoleOrigin": { + "type": "object", + "properties": { + "depth": { + "type": "number", + "description": "Nesting depth of the group (0 for direct assignment)" }, - "id": { + "miniUuid": { "type": "string", - "format": "uuid", - "description": "Unique identifier for the upload" + "description": "Short identifier of the group", + "example": "abc123" }, - "in_db_as_table_name": { - "type": [ - "string", - "null" - ], - "description": "Database table name if uploaded to database scratch schema" + "name": { + "type": "string", + "description": "Name of the group", + "example": "Engineering Team" }, - "model_id": { - "type": [ - "string", - "null" + "type": { + "type": "string", + "enum": [ + "GROUP" ], + "description": "Role assigned to group" + } + }, + "required": [ + "depth", + "miniUuid", + "name", + "type" + ], + "description": "Origin of this role assignment" + }, + "UserGroupsAssignModelRoleResponse": { + "type": "object", + "properties": { + "connectionId": { + "type": "string", "format": "uuid", - "description": "Model ID the upload is associated with (inferred from connection's shared model if not explicitly set)" - }, - "size_bytes": { - "type": [ - "number", - "null" - ], - "description": "File size in bytes" + "description": "The connection ID for this role assignment" }, - "updated_at": { + "modelId": { "type": "string", - "format": "date-time", - "description": "Last update timestamp" + "format": "uuid", + "description": "The model ID for this role assignment" }, - "uploaded_by_user": { - "type": [ - "object", - "null" - ], - "properties": { - "id": { - "type": "string", - "format": "uuid", - "description": "User ID of the uploader" - }, - "name": { - "type": "string", - "description": "Name of the user who uploaded the file" - } - }, - "required": [ - "id", - "name" - ], - "description": "User who uploaded the file" + "roleName": { + "type": "string", + "description": "The assigned role name", + "example": "VIEWER" }, - "view_name": { + "userGroupId": { "type": "string", - "description": "View name associated with the upload" + "description": "The user group short identifier", + "example": "abc123" } }, "required": [ - "connection_id", - "created_at", - "file_name", - "id", - "in_db_as_table_name", - "model_id", - "size_bytes", - "updated_at", - "uploaded_by_user", - "view_name" + "connectionId", + "modelId", + "roleName", + "userGroupId" ] }, - "UploadCreateResponse": { + "UserGroupsAssignModelRoleBody": { "type": "object", "properties": { - "fileName": { + "connectionId": { "type": "string", - "description": "Original file name", - "example": "users.csv" + "format": "uuid", + "description": "Connection ID for connection-level role assignment. Required if modelId not provided.", + "example": "550e8400-e29b-41d4-a716-446655440000" }, - "id": { + "modelId": { "type": "string", "format": "uuid", - "description": "Unique identifier for the upload" + "description": "Model ID for model-level role assignment. Required if connectionId not provided.", + "example": "550e8400-e29b-41d4-a716-446655440000" }, - "inDbAsTableName": { + "roleName": { "type": "string", - "description": "Database table name in the scratch schema" + "minLength": 1, + "description": "Name of the role to assign (base or custom role)", + "example": "VIEWER" + } + }, + "required": [ + "roleName" + ] + } + }, + "parameters": {} + }, + "paths": { + "/api/v1/ai/generate-query": { + "post": { + "description": "Generate an Omni semantic query from a natural language prompt. Optionally executes the generated query and returns results. The AI analyzes the prompt, selects appropriate fields and filters from the model, and constructs a query. Requires the querier role on the target model.", + "operationId": "aiGenerateQuery", + "summary": "Generate query from natural language", + "tags": [ + "AI" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AiGenerateQueryBody" + } + } + } + }, + "responses": { + "200": { + "description": "Query generated successfully. If runQuery is true (default), includes execution results. Check the error field — a 200 response may still contain a partial error if the query was generated but execution failed. When the organization is over its AI downgrade threshold the response also carries `downgradedModelTier` naming the cheaper tier the query was generated with.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AiGenerateQueryResponse" + } + } + } }, - "modelId": { - "type": "string", - "format": "uuid", - "description": "Model ID the view was created in" + "400": { + "description": "Invalid request. The prompt may be missing, the modelId may be invalid, or the AI was unable to generate a query for the given prompt.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError400" + } + } + } + }, + "401": { + "description": "Missing or invalid API key.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError401" + } + } + } + }, + "402": { + "description": "AI is unavailable because the organization is over its AI credit limit. The body carries the stable reason code `shutoff`.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AiCreditShutoffError" + } + } + } + }, + "403": { + "description": "Insufficient permissions. Requires the querier role on the target model and AI query generation must be enabled for the organization.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError403" + } + } + } + }, + "404": { + "description": "The specified model or topic was not found in the organization.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError404" + } + } + } + }, + "500": { + "description": "AI service error." + } + } + } + }, + "/api/v1/ai/pick-topic": { + "post": { + "description": "Analyze a natural language prompt and determine which topic in the model is the best fit for answering the question. Useful as a preprocessing step before calling generate-query or submitting an AI job, especially when the user's question could relate to multiple topics.", + "operationId": "aiPickTopic", + "summary": "Pick the best topic for a prompt", + "tags": [ + "AI" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AiPickTopicBody" + } + } + } + }, + "responses": { + "200": { + "description": "Topic selected successfully. The returned topicId can be used as the topicName parameter in other AI endpoints.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AiPickTopicResponse" + } + } + } + }, + "400": { + "description": "Invalid request body. The prompt or modelId may be missing or malformed.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError400" + } + } + } + }, + "401": { + "description": "Missing or invalid API key.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError401" + } + } + } + }, + "403": { + "description": "Insufficient permissions. Requires the querier role on the target model and AI must be enabled for the organization.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError403" + } + } + } + }, + "404": { + "description": "The specified model was not found, or no accessible topics exist in the model.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError404" + } + } + } + }, + "500": { + "description": "AI service error." + } + } + } + }, + "/api/v1/ai/search-omni-docs": { + "post": { + "description": "Search the Omni documentation using AI to answer questions about Omni features, configuration, modeling, dashboards, and more. Sends a natural language question and returns a synthesized answer with source links to the relevant documentation pages.", + "operationId": "aiSearchOmniDocs", + "summary": "Search Omni documentation", + "tags": [ + "AI" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AiSearchOmniDocsBody" + } + } + } + }, + "responses": { + "200": { + "description": "Documentation search completed successfully. Returns a synthesized answer with source links.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AiSearchOmniDocsResponse" + } + } + } }, - "rowCount": { - "type": "integer", - "description": "Number of rows in the uploaded file" + "400": { + "description": "Invalid request. The question may be missing or exceed the 2000 character limit.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError400" + } + } + } }, - "truncated": { - "type": "boolean", - "description": "Whether the file was truncated due to row limit" + "401": { + "description": "Missing or invalid API key.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError401" + } + } + } }, - "viewCreated": { - "type": "boolean", - "description": "Whether a view was created in the model" + "403": { + "description": "Omni Agent is not enabled for this organization.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError403" + } + } + } }, - "viewName": { - "type": "string", - "description": "Name of the view created" + "500": { + "description": "AI service error." + } + } + } + }, + "/api/v1/ai/jobs": { + "post": { + "description": "Submit a new AI job for asynchronous execution. The AI will analyze the prompt, generate and execute queries against the specified model, and produce a summarized answer. Jobs are processed by a background worker and typically complete within 15–60 seconds. Use GET /api/v1/ai/jobs/{jobId} to poll for status, or configure a webhookUrl to receive a notification when the job completes. Optionally continue an existing conversation by providing a conversationId.", + "operationId": "aiJobSubmit", + "summary": "Submit an AI job", + "tags": [ + "AI" + ], + "parameters": [ + { + "schema": { + "type": "string", + "format": "uuid", + "description": "Target user membership ID (for org-scoped API keys)" + }, + "required": false, + "description": "Target user membership ID (for org-scoped API keys)", + "name": "userId", + "in": "query" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AiJobSubmitBody" + } + } } }, - "required": [ - "fileName", - "id", - "inDbAsTableName", - "modelId", - "rowCount", - "truncated", - "viewCreated", - "viewName" - ] - }, - "UploadCreateBody": { - "type": "object", - "properties": { - "branchId": { - "type": "string", - "format": "uuid", - "description": "UUID of the branch to create the view in (mutually exclusive with branchName)" + "responses": { + "201": { + "description": "Job created and queued for execution. Use the returned jobId to poll for status or retrieve results.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AiJobSubmitResponse" + } + } + } }, - "branchName": { - "type": "string", - "description": "Name of the branch to create the view in (mutually exclusive with branchId)" + "400": { + "description": "Invalid request body. Common causes: missing or empty prompt, invalid UUID for modelId/branchId/conversationId, invalid webhook URL format.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError400" + } + } + } }, - "file": { - "type": "string", - "description": "The CSV file to upload", - "format": "binary" + "401": { + "description": "Missing or invalid API key.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError401" + } + } + } }, - "modelId": { - "type": "string", - "format": "uuid", - "description": "UUID of the model to create the view in" + "403": { + "description": "Insufficient permissions. The AI jobs API must be enabled for the organization, AI query generation must be enabled, and the user must have appropriate model access. User-scoped API keys cannot act on behalf of other users.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError403" + } + } + } }, - "viewName": { - "type": "string", - "description": "Override the view name (defaults to sanitized file name)" + "404": { + "description": "The specified model was not found in the organization, the branchId does not belong to the specified model, or the topicName does not exist in the model (or is excluded by ai_chat_topics restrictions).", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError404" + } + } + } + }, + "409": { + "description": "An active job already exists for the specified conversationId. Wait for the current job to complete before submitting another job to the same conversation.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError409" + } + } + } } - }, - "required": [ - "modelId" - ] - }, - "UploadDeleteResponse": { - "type": "object", - "properties": { - "success": { - "type": "boolean", - "description": "Whether the deletion was successful" + } + } + }, + "/api/v1/ai/jobs/{jobId}": { + "get": { + "description": "Get the current status of an AI job, including its state, progress information, and result summary. The response fields vary by state — for example, progress is only present during EXECUTING, and resultSummary is only present when COMPLETE. Poll this endpoint every 2–5 seconds until the job reaches a terminal state (COMPLETE, FAILED, or CANCELLED).", + "operationId": "aiJobStatus", + "summary": "Get AI job status", + "tags": [ + "AI" + ], + "parameters": [ + { + "schema": { + "type": "string", + "format": "uuid", + "description": "The unique identifier of the AI job", + "example": "123e4567-e89b-12d3-a456-426614174000" + }, + "required": true, + "description": "The unique identifier of the AI job", + "name": "jobId", + "in": "path" } - }, - "required": [ - "success" - ] - }, - "UsersGetModelRolesResponse": { - "type": "object", - "properties": { - "membershipId": { - "type": "string", - "format": "uuid", - "description": "The user membership ID" + ], + "responses": { + "200": { + "description": "Job status retrieved successfully. Check the state field to determine if the job is still running or has reached a terminal state.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AiJobStatusResponse" + } + } + } }, - "results": { - "type": "array", - "items": { - "$ref": "#/components/schemas/RoleAssignmentResult" + "400": { + "description": "Invalid job ID format. Must be a valid UUID.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError400" + } + } + } + }, + "401": { + "description": "Missing or invalid API key.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError401" + } + } + } + }, + "404": { + "description": "Job not found. The job may not exist or may belong to a different organization.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError404" + } + } + } + } + } + } + }, + "/api/v1/ai/jobs/{jobId}/cancel": { + "post": { + "description": "Request cancellation of an AI job. This endpoint is idempotent — calling it on an already-cancelled or completed job returns success with the current state. For QUEUED jobs, cancellation is immediate. For EXECUTING jobs, the worker will stop after completing its current iteration. Jobs in DELIVERING state cannot be cancelled as they are already finalizing results. Only the job owner or organization admins can cancel jobs.", + "operationId": "aiJobCancel", + "summary": "Cancel an AI job", + "tags": [ + "AI" + ], + "parameters": [ + { + "schema": { + "type": "string", + "format": "uuid", + "description": "The unique identifier of the AI job", + "example": "123e4567-e89b-12d3-a456-426614174000" }, - "description": "List of role assignments" + "required": true, + "description": "The unique identifier of the AI job", + "name": "jobId", + "in": "path" } - }, - "required": [ - "membershipId", - "results" - ] - }, - "RoleAssignmentResult": { - "type": "object", - "properties": { - "baseRole": { - "type": "string", - "description": "The base role definition name", - "example": "VIEWER" - }, - "connectionId": { - "type": "string", - "format": "uuid", - "description": "Connection this role applies to" + ], + "responses": { + "200": { + "description": "Cancellation request processed. The state field indicates the job's state after the attempt — CANCELLED if successful, or the current terminal state if the job had already completed.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AiJobCancelResponse" + } + } + } }, - "from": { - "$ref": "#/components/schemas/RoleOrigin" + "400": { + "description": "Invalid job ID format. Must be a valid UUID.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError400" + } + } + } }, - "modelId": { - "type": "string", - "format": "uuid", - "description": "Model this role applies to" + "401": { + "description": "Missing or invalid API key.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError401" + } + } + } }, - "priority": { - "type": "number", - "description": "Priority for role resolution (higher = more permissive)" + "403": { + "description": "Permission denied. Only the job owner or organization admins can cancel jobs.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError403" + } + } + } }, - "resolved": { - "type": "boolean", - "description": "Whether this is the resolved (effective) role" + "404": { + "description": "Job not found. The job may not exist or may belong to a different organization.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError404" + } + } + } }, - "roleName": { - "type": "string", - "description": "The role name (base or custom)", - "example": "VIEWER" + "409": { + "description": "Concurrent modification conflict. The job state was changed by another request. Retry the cancellation.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError409" + } + } + } } - }, - "required": [ - "baseRole", - "connectionId", - "from", - "modelId", - "priority", - "resolved", - "roleName" - ] - }, - "RoleOrigin": { - "oneOf": [ + } + } + }, + "/api/v1/ai/jobs/{jobId}/result": { + "get": { + "description": "Retrieve the full result of a completed AI job, including all actions taken by the AI (queries generated, data retrieved) and the final summarized answer. Results are only available for jobs in COMPLETE state and are retained for 14 days after completion. The response is streamed directly from storage.", + "operationId": "aiJobResult", + "summary": "Get AI job result", + "tags": [ + "AI" + ], + "parameters": [ { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "USER" - ], - "description": "Role assigned directly to user" - } + "schema": { + "type": "string", + "format": "uuid", + "description": "The unique identifier of the AI job", + "example": "123e4567-e89b-12d3-a456-426614174000" }, - "required": [ - "type" - ] + "required": true, + "description": "The unique identifier of the AI job", + "name": "jobId", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Full job result including the AI's actions, query results (with CSV data), and the final Markdown-formatted answer.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AiJobResultResponse" + } + } + } }, - { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "ORG" - ], - "description": "Role inherited from organization" + "400": { + "description": "Invalid job ID format. Must be a valid UUID.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError400" + } } - }, - "required": [ - "type" - ] + } }, - { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "BASE" - ], - "description": "Connection base role" + "401": { + "description": "Missing or invalid API key.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError401" + } } - }, - "required": [ - "type" - ] + } }, - { - "type": "object", - "properties": { - "depth": { - "type": "number", - "description": "Nesting depth of the group" - }, - "miniUuid": { - "type": "string", - "description": "Short identifier of the group", - "example": "abc123" - }, - "name": { - "type": "string", - "description": "Name of the group", - "example": "Engineering Team" - }, - "type": { - "type": "string", - "enum": [ - "GROUP" - ], - "description": "Role inherited from group membership" + "404": { + "description": "Job not found, not in COMPLETE state, or result is no longer available (results are retained for 14 days).", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError404" + } } + } + } + } + } + }, + "/api/v1/ai/jobs/{jobId}/vis": { + "get": { + "description": "Render the visualization from a completed AI job as a PNG image. The endpoint extracts the visualization configuration from the job result, loads Arrow IPC data, and renders it server-side using Vega. For style-only follow-ups (e.g., \"make it a bar chart\"), the endpoint walks back through previous jobs in the conversation to find the original query data.", + "operationId": "aiJobVisualization", + "summary": "Render AI job visualization", + "tags": [ + "AI" + ], + "parameters": [ + { + "schema": { + "type": "string", + "format": "uuid", + "description": "The unique identifier of the AI job", + "example": "123e4567-e89b-12d3-a456-426614174000" }, - "required": [ - "depth", - "miniUuid", - "name", - "type" - ] + "required": true, + "description": "The unique identifier of the AI job", + "name": "jobId", + "in": "path" } ], - "description": "Origin of this role assignment" - }, - "UsersAssignModelRoleResponse": { - "type": "object", - "properties": { - "connectionId": { - "type": "string", - "format": "uuid", - "description": "The connection ID for this role assignment" - }, - "membershipId": { - "type": "string", - "format": "uuid", - "description": "The user membership ID" + "responses": { + "200": { + "description": "Visualization rendered as a PNG image. The Content-Type header is image/png.", + "content": { + "image/png": { + "schema": { + "format": "binary", + "type": "string" + } + } + } }, - "modelId": { - "type": "string", - "format": "uuid", - "description": "The model ID for this role assignment" + "400": { + "description": "Invalid job ID format. Must be a valid UUID.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError400" + } + } + } }, - "roleName": { - "type": "string", - "description": "The assigned role name", - "example": "VIEWER" - } - }, - "required": [ - "connectionId", - "membershipId", - "modelId", - "roleName" - ] - }, - "UsersAssignModelRoleBody": { - "type": "object", - "properties": { - "connectionId": { - "type": "string", - "format": "uuid", - "description": "Connection ID for connection-level role assignment. Required if modelId not provided.", - "example": "550e8400-e29b-41d4-a716-446655440000" + "401": { + "description": "Missing or invalid API key.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError401" + } + } + } }, - "modelId": { - "type": "string", - "format": "uuid", - "description": "Model ID for model-level role assignment. Required if connectionId not provided.", - "example": "550e8400-e29b-41d4-a716-446655440000" + "404": { + "description": "Job not found, not in COMPLETE state, or the apiAiVis feature flag is not enabled.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError404" + } + } + } }, - "roleName": { - "type": "string", - "minLength": 1, - "description": "Name of the role to assign (base or custom role)", - "example": "VIEWER" + "422": { + "description": "The job completed but cannot be rendered as a visualization. Common causes: no visualization action in the job result, no Arrow IPC data available, missing summary fields, or the chart type is not renderable as an image (e.g., tables, KPIs).", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError422" + } + } + } } - }, - "required": [ - "roleName" - ] - }, - "UsersListEmailOnlyResponse": { - "type": "object", - "properties": { - "pageInfo": { - "$ref": "#/components/schemas/PageInfo" + } + } + }, + "/api/v1/ai/branding": { + "get": { + "description": "Returns the organization's AI helper branding — display name, optional custom logo URL, and copy used on AI helper landing surfaces (headline, body, prompt placeholder). Falls back to Omni's defaults when the organization hasn't configured custom branding, so the response is always populated. Used by client apps (iOS, embeds) to render the AI helper with the org's chosen identity.", + "operationId": "aiBranding", + "summary": "Get AI helper branding", + "tags": [ + "AI" + ], + "responses": { + "200": { + "description": "AI branding retrieved successfully.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AiBrandingResponse" + } + } + } }, - "records": { - "type": "array", - "items": { - "type": "object", - "properties": { - "email": { - "type": "string", - "description": "User email address", - "example": "user@example.com" - }, - "user_attributes": { - "type": "object", - "additionalProperties": {}, - "description": "User attributes as key-value pairs" - }, - "user_id": { - "type": "string", - "format": "uuid", - "description": "User ID" + "401": { + "description": "Missing or invalid API key.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError401" } - }, - "required": [ - "email", - "user_attributes", - "user_id" - ] + } } - } - }, - "required": [ - "pageInfo", - "records" - ] - }, - "UsersCreateEmailOnlyResponse": { - "type": "object", - "properties": { - "email": { - "type": "string", - "format": "email", - "description": "Email address of the created user", - "example": "user@example.com" }, - "userId": { - "type": "string", - "format": "uuid", - "description": "ID of the created user" + "403": { + "description": "AI access is required to view AI helper branding (no model in the org grants USE_AI to the caller).", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError403" + } + } + } } - }, - "required": [ - "email", - "userId" - ] - }, - "UsersCreateEmailOnlyBody": { - "type": "object", - "properties": { - "email": { - "type": "string", - "format": "email", - "description": "Email address for the user", - "example": "user@example.com" + } + } + }, + "/api/v1/ai/conversations": { + "get": { + "description": "List the user's recent AI conversations, ordered by most-recent activity. Each record includes the conversation id (pass it back as `conversationId` on subsequent /api/v1/ai/jobs submissions to continue the thread), an optional name, and a one-line summary of the most recent prompt for display. Paginated via opaque `pageInfo.nextCursor` — pass it back as `cursor` to fetch the next page.", + "operationId": "aiConversationsList", + "summary": "List AI conversations", + "tags": [ + "AI" + ], + "parameters": [ + { + "schema": { + "type": "string", + "description": "Cursor for pagination (from previous response nextCursor)", + "example": "eyJpZCI6IjEyMzQ1In0" + }, + "required": false, + "description": "Cursor for pagination (from previous response nextCursor)", + "name": "cursor", + "in": "query" }, - "userAttributes": { - "type": "object", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - }, - { - "type": "null" - } - ] + { + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 100, + "default": 20, + "description": "Number of results per page (1-100, integer)", + "example": 20 + }, + "required": false, + "description": "Number of results per page (1-100, integer)", + "name": "pageSize", + "in": "query" + }, + { + "schema": { + "type": "string", + "format": "uuid", + "description": "Target user membership ID (for org-scoped API keys)" }, - "description": "Optional user attributes as key-value pairs" + "required": false, + "description": "Target user membership ID (for org-scoped API keys)", + "name": "userId", + "in": "query" } - }, - "required": [ - "email" - ] - }, - "UsersCreateEmailOnlyBulkResponse": { - "type": "object", - "properties": { - "results": { - "type": "array", - "items": { - "type": "object", - "properties": { - "email": { - "type": "string", - "format": "email", - "description": "Email address of the created user", - "example": "user@example.com" - }, - "userId": { - "type": "string", - "format": "uuid", - "description": "ID of the created user" + ], + "responses": { + "200": { + "description": "Paginated list of conversations.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AiConversationsListResponse" } - }, - "required": [ - "email", - "userId" - ] - }, - "description": "Results for each created user" - } - }, - "required": [ - "results" - ] - }, - "UsersCreateEmailOnlyBulkBody": { - "type": "object", - "properties": { - "users": { - "type": "array", - "items": { - "type": "object", - "properties": { - "email": { - "type": "string", - "format": "email", - "description": "Email address for the user", - "example": "user@example.com" - }, - "userAttributes": { - "type": "object", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - }, - { - "type": "null" - } - ] - }, - "description": "Optional user attributes as key-value pairs" + } + } + }, + "401": { + "description": "Missing or invalid API key.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError401" } - }, - "required": [ - "email" - ] - }, - "minItems": 1, - "maxItems": 20, - "description": "Array of users to create (1-20 users)" + } + } + }, + "403": { + "description": "Insufficient permissions.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError403" + } + } + } } - }, - "required": [ - "users" - ] - }, - "UserGroupsGetModelRolesResponse": { - "type": "object", - "properties": { - "results": { - "type": "array", - "items": { - "$ref": "#/components/schemas/UserGroupRoleAssignmentResult" + } + } + }, + "/api/v1/ai/conversations/{conversationId}": { + "get": { + "description": "Return a conversation with its full message history (alternating user / assistant turns). Used by clients (iOS app, embed widgets) to restore a prior conversation in their UI.", + "operationId": "aiConversationDetail", + "summary": "Get AI conversation with messages", + "tags": [ + "AI" + ], + "parameters": [ + { + "schema": { + "type": "string", + "format": "uuid" }, - "description": "List of role assignments" - }, - "userGroupId": { - "type": "string", - "description": "The user group short identifier", - "example": "abc123" + "required": true, + "name": "conversationId", + "in": "path" } - }, - "required": [ - "results", - "userGroupId" - ] - }, - "UserGroupRoleAssignmentResult": { - "type": "object", - "properties": { - "baseRole": { - "type": "string", - "description": "The base role definition name", - "example": "VIEWER" + ], + "responses": { + "200": { + "description": "Conversation with messages in chronological order.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AiConversationDetailResponse" + } + } + } }, - "connectionId": { - "type": "string", - "format": "uuid", - "description": "Connection this role applies to" + "401": { + "description": "Missing or invalid API key.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError401" + } + } + } }, - "from": { - "$ref": "#/components/schemas/UserGroupRoleOrigin" + "403": { + "description": "AI access is required to view chat conversations (no model in the org grants USE_AI to the caller).", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError403" + } + } + } }, - "modelId": { - "type": "string", - "format": "uuid", - "description": "Model this role applies to" + "404": { + "description": "Conversation not found. User-scoped keys also get 404 (not 403) when the conversation exists but belongs to a different user — existence of another user's conversations is not disclosed.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError404" + } + } + } + } + } + } + }, + "/api/v1/api-keys": { + "get": { + "description": "Returns all API tokens in the organization, including organization-level keys, personal access tokens, and MCP OAuth grants. Secrets are never returned. Requires organization admin permissions.", + "operationId": "apiKeysList", + "summary": "List API tokens", + "tags": [ + "API Tokens" + ], + "parameters": [ + { + "schema": { + "type": "string", + "format": "uuid", + "description": "Cursor from the previous response (token UUID)" + }, + "required": false, + "description": "Cursor from the previous response (token UUID)", + "name": "cursor", + "in": "query" + }, + { + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 100, + "default": 20, + "description": "Number of results per page (1-100, integer)", + "example": 20 + }, + "required": false, + "description": "Number of results per page (1-100, integer)", + "name": "pageSize", + "in": "query" + }, + { + "schema": { + "type": "string", + "enum": [ + "asc", + "desc" + ], + "default": "desc", + "description": "Sort direction for results", + "example": "desc" + }, + "required": false, + "description": "Sort direction for results", + "name": "sortDirection", + "in": "query" }, - "priority": { - "type": "number", - "description": "Priority for role resolution (higher = more permissive)" + { + "schema": { + "type": "string", + "enum": [ + "createdAt", + "name" + ], + "default": "createdAt" + }, + "required": false, + "name": "sortField", + "in": "query" }, - "roleName": { - "type": "string", - "description": "The role name (base or custom)", - "example": "VIEWER" + { + "schema": { + "type": "string", + "enum": [ + "organization", + "personal", + "mcp" + ], + "description": "Filter by API token type. When omitted, all types are returned.", + "example": "personal" + }, + "required": false, + "description": "Filter by API token type. When omitted, all types are returned.", + "name": "type", + "in": "query" } - }, - "required": [ - "baseRole", - "connectionId", - "from", - "modelId", - "priority", - "roleName" - ] - }, - "UserGroupRoleOrigin": { - "type": "object", - "properties": { - "depth": { - "type": "number", - "description": "Nesting depth of the group (0 for direct assignment)" + ], + "responses": { + "200": { + "description": "Paginated list of API tokens", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiKeyListResponse" + } + } + } }, - "miniUuid": { - "type": "string", - "description": "Short identifier of the group", - "example": "abc123" + "400": { + "description": "Invalid query parameters" }, - "name": { - "type": "string", - "description": "Name of the group", - "example": "Engineering Team" + "401": { + "description": "Authentication required" }, - "type": { - "type": "string", - "enum": [ - "GROUP" - ], - "description": "Role assigned to group" + "403": { + "description": "Insufficient permissions" } - }, - "required": [ - "depth", - "miniUuid", - "name", - "type" + } + } + }, + "/api/v1/api-keys/{id}": { + "get": { + "description": "Returns a single API token by id. Requires organization admin permissions.", + "operationId": "apiKeysGet", + "summary": "Get API token", + "tags": [ + "API Tokens" ], - "description": "Origin of this role assignment" - }, - "UserGroupsAssignModelRoleResponse": { - "type": "object", - "properties": { - "connectionId": { - "type": "string", - "format": "uuid", - "description": "The connection ID for this role assignment" - }, - "modelId": { - "type": "string", - "format": "uuid", - "description": "The model ID for this role assignment" + "parameters": [ + { + "schema": { + "type": "string", + "format": "uuid", + "description": "Token UUID", + "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" + }, + "required": true, + "description": "Token UUID", + "name": "id", + "in": "path" + } + ], + "responses": { + "200": { + "description": "The requested API token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiKey" + } + } + } }, - "roleName": { - "type": "string", - "description": "The assigned role name", - "example": "VIEWER" + "400": { + "description": "Malformed `id` (must be a UUID)" }, - "userGroupId": { - "type": "string", - "description": "The user group short identifier", - "example": "abc123" - } - }, - "required": [ - "connectionId", - "modelId", - "roleName", - "userGroupId" - ] - }, - "UserGroupsAssignModelRoleBody": { - "type": "object", - "properties": { - "connectionId": { - "type": "string", - "format": "uuid", - "description": "Connection ID for connection-level role assignment. Required if modelId not provided.", - "example": "550e8400-e29b-41d4-a716-446655440000" + "401": { + "description": "Authentication required" }, - "modelId": { - "type": "string", - "format": "uuid", - "description": "Model ID for model-level role assignment. Required if connectionId not provided.", - "example": "550e8400-e29b-41d4-a716-446655440000" + "403": { + "description": "Insufficient permissions" }, - "roleName": { - "type": "string", - "minLength": 1, - "description": "Name of the role to assign (base or custom role)", - "example": "VIEWER" + "404": { + "description": "Token not found in this organization" } - }, - "required": [ - "roleName" - ] - } - }, - "parameters": {} - }, - "paths": { - "/api/v1/ai/generate-query": { - "post": { - "description": "Generate an Omni semantic query from a natural language prompt. Optionally executes the generated query and returns results. The AI analyzes the prompt, selects appropriate fields and filters from the model, and constructs a query. Requires the querier role on the target model.", - "operationId": "aiGenerateQuery", - "summary": "Generate query from natural language", + } + }, + "put": { + "description": "Enables or disables an API token. Requires organization admin permissions.", + "operationId": "apiKeysUpdate", + "summary": "Enable or disable an API token", "tags": [ - "AI" + "API Tokens" + ], + "parameters": [ + { + "schema": { + "type": "string", + "format": "uuid", + "description": "Token UUID", + "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" + }, + "required": true, + "description": "Token UUID", + "name": "id", + "in": "path" + } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/AiGenerateQueryBody" + "$ref": "#/components/schemas/ApiKeyUpdateBody" + } + } + } + }, + "responses": { + "200": { + "description": "The updated API token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiKey" + } } } + }, + "400": { + "description": "Invalid body, malformed `id`, or missing/malformed `Authorization` header" + }, + "403": { + "description": "Invalid bearer token, or caller lacks organization admin permissions" + }, + "404": { + "description": "Token not found in this organization" + }, + "405": { + "description": "Method not allowed" + } + } + }, + "delete": { + "description": "Revokes an API token by permanently deleting it. Works for all token types. Requires organization admin permissions.", + "operationId": "apiKeysDelete", + "summary": "Revoke an API token", + "tags": [ + "API Tokens" + ], + "parameters": [ + { + "schema": { + "type": "string", + "format": "uuid", + "description": "Token UUID", + "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" + }, + "required": true, + "description": "Token UUID", + "name": "id", + "in": "path" } - }, + ], "responses": { "200": { - "description": "Query generated successfully. If runQuery is true (default), includes execution results. Check the error field — a 200 response may still contain a partial error if the query was generated but execution failed.", + "description": "The token was revoked", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/AiGenerateQueryResponse" + "$ref": "#/components/schemas/ApiKeyDeleteResponse" } } } }, "400": { - "description": "Invalid request. The prompt may be missing, the modelId may be invalid, or the AI was unable to generate a query for the given prompt.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiError400" - } - } - } - }, - "401": { - "description": "Missing or invalid API key.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiError401" - } - } - } + "description": "Malformed `id`, or missing/malformed `Authorization` header" }, "403": { - "description": "Insufficient permissions. Requires the querier role on the target model and AI query generation must be enabled for the organization.", + "description": "Invalid bearer token, or caller lacks organization admin permissions" + }, + "404": { + "description": "Token not found in this organization" + }, + "405": { + "description": "Method not allowed" + } + } + } + }, + "/api/v1/connections": { + "get": { + "operationId": "connectionsList", + "summary": "List connections", + "tags": [ + "Connections" + ], + "parameters": [ + { + "schema": { + "type": "string", + "description": "Filter by database name (case-insensitive contains)", + "example": "analytics" + }, + "required": false, + "description": "Filter by database name (case-insensitive contains)", + "name": "database", + "in": "query" + }, + { + "schema": { + "type": "string", + "description": "Filter by dialect(s). Comma-separated list for multiple values", + "example": "snowflake,bigquery" + }, + "required": false, + "description": "Filter by dialect(s). Comma-separated list for multiple values", + "name": "dialect", + "in": "query" + }, + { + "schema": { + "type": "boolean", + "description": "Include soft-deleted connections in results", + "example": false + }, + "required": false, + "description": "Include soft-deleted connections in results", + "name": "includeDeleted", + "in": "query" + }, + { + "schema": { + "type": "string", + "description": "Filter by connection name (case-insensitive contains)", + "example": "Production" + }, + "required": false, + "description": "Filter by connection name (case-insensitive contains)", + "name": "name", + "in": "query" + }, + { + "schema": { + "type": "string", + "enum": [ + "asc", + "desc" + ], + "description": "Sort direction", + "example": "desc" + }, + "required": false, + "description": "Sort direction", + "name": "sortDirection", + "in": "query" + }, + { + "schema": { + "type": "string", + "enum": [ + "database", + "dialect", + "name" + ], + "description": "Field to sort by", + "example": "name" + }, + "required": false, + "description": "Field to sort by", + "name": "sortField", + "in": "query" + } + ], + "responses": { + "200": { + "description": "List of connections", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ApiError403" + "type": "object", + "properties": { + "connections": { + "type": "array", + "items": { + "type": "object", + "properties": { + "baseRole": { + "type": [ + "string", + "null" + ], + "description": "Default role for users on this connection", + "example": "QUERIER" + }, + "branchConnectionEnvironmentOverridesUserAttr": { + "type": [ + "boolean", + "null" + ], + "description": "Whether branch environments override user attributes", + "example": false + }, + "createdAt": { + "type": "string", + "description": "Timestamp when connection was created (ISO 8601)", + "example": "2024-01-15T10:30:00Z" + }, + "database": { + "type": [ + "string", + "null" + ], + "description": "Database name", + "example": "analytics_db" + }, + "defaultSchema": { + "type": [ + "string", + "null" + ], + "description": "Default schema for the connection", + "example": "public" + }, + "deletedAt": { + "type": [ + "string", + "null" + ], + "description": "Timestamp when connection was deleted (ISO 8601)", + "example": null + }, + "dialect": { + "type": "string", + "enum": [ + "snowflake", + "bigquery", + "redshift", + "postgres", + "mysql", + "mariadb", + "databricks", + "databricks_lakebase", + "trino", + "athena", + "duckdb", + "motherduck", + "sqlserver", + "clickhouse", + "singlestore" + ], + "description": "Database dialect type", + "example": "snowflake" + }, + "environmentConnectionSwitchesSchemaModel": { + "type": [ + "boolean", + "null" + ], + "description": "Whether environment connections switch schema model", + "example": false + }, + "id": { + "type": "string", + "format": "uuid", + "description": "Unique connection identifier", + "example": "550e8400-e29b-41d4-a716-446655440000" + }, + "name": { + "type": "string", + "description": "Connection display name", + "example": "Production Snowflake" + }, + "updatedAt": { + "type": "string", + "description": "Timestamp when connection was last updated (ISO 8601)", + "example": "2024-01-15T10:30:00Z" + }, + "userAttributeNameForConnectionEnvironments": { + "type": [ + "string", + "null" + ], + "description": "User attribute name used for connection environments", + "example": "region" + }, + "userAttributeValuesForDefaultEnvironment": { + "type": [ + "array", + "null" + ], + "items": { + "type": "string" + }, + "description": "Default user attribute values for the base environment", + "example": [ + "us-east", + "us-west" + ] + } + }, + "required": [ + "baseRole", + "branchConnectionEnvironmentOverridesUserAttr", + "createdAt", + "database", + "defaultSchema", + "deletedAt", + "dialect", + "environmentConnectionSwitchesSchemaModel", + "id", + "name", + "updatedAt", + "userAttributeNameForConnectionEnvironments", + "userAttributeValuesForDefaultEnvironment" + ], + "description": "Connection object", + "title": "Connection" + }, + "description": "List of connections" + } + }, + "required": [ + "connections" + ], + "description": "List connections response", + "title": "ConnectionsListResponse" } } } }, - "404": { - "description": "The specified model or topic was not found in the organization.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiError404" - } - } - } + "401": { + "description": "Authentication required" }, - "500": { - "description": "AI service error." + "403": { + "description": "Permission denied - admin role required" } } - } - }, - "/api/v1/ai/pick-topic": { + }, "post": { - "description": "Analyze a natural language prompt and determine which topic in the model is the best fit for answering the question. Useful as a preprocessing step before calling generate-query or submitting an AI job, especially when the user's question could relate to multiple topics.", - "operationId": "aiPickTopic", - "summary": "Pick the best topic for a prompt", + "description": "Create a new database connection. The request body varies by dialect - see dialect-specific documentation for required fields.", + "operationId": "connectionsCreate", + "summary": "Create connection", "tags": [ - "AI" + "Connections" ], "requestBody": { - "required": true, "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/AiPickTopicBody" + "type": "object", + "properties": { + "acceptsLicense": { + "type": "boolean", + "description": "Acceptance of the license terms. Required for Oracle connections.", + "example": true + }, + "allowsUserSpecificTimezones": { + "type": "boolean", + "default": false, + "description": "Whether to allow users to specify their own timezones", + "example": false + }, + "alwaysScopeViewNames": { + "type": "boolean", + "description": "Whether to always include schema (and catalog) prefixes in generated view names, even for tables in the default schema. Defaults to true for dialects that support multiple catalogs, false otherwise.", + "example": true + }, + "authenticationType": { + "type": "string", + "description": "Authentication type. Applicable for BigQuery, MSSQL, Snowflake, Databricks, and Athena.", + "example": "snowflake-password" + }, + "awsRoleArn": { + "type": "string", + "description": "AWS IAM role ARN. Applicable for Athena only.", + "example": "arn:aws:iam::123456789012:role/OmniAthenaRole" + }, + "baseRole": { + "type": "string", + "enum": [ + "NO_ACCESS", + "VIEWER", + "RESTRICTED_QUERIER", + "QUERIER", + "MODELER", + "CONNECTION_ADMIN" + ], + "description": "The default role for users accessing the connection", + "example": "QUERIER" + }, + "database": { + "type": "string", + "description": "The default database/catalog to connect to. For BigQuery, this is the project ID. For Athena, this is the data catalog.", + "example": "analytics_db" + }, + "defaultSchema": { + "type": "string", + "description": "The default schema to use. Required for MSSQL.", + "example": "public" + }, + "dialect": { + "type": "string", + "enum": [ + "athena", + "bigquery", + "clickhouse", + "databricks", + "databricks_lakebase", + "exasol", + "mariadb", + "motherduck", + "mssql", + "mysql", + "oracle", + "postgres", + "redshift", + "sap_hana", + "snowflake", + "starrocks", + "trino" + ], + "description": "The database dialect", + "example": "snowflake" + }, + "enableDbSemanticLayerIntegration": { + "type": "boolean", + "default": false, + "description": "Enable the dialect-native semantic layer integration. Applicable for Snowflake and Databricks.", + "example": false + }, + "enableDbSemanticLayerTopics": { + "type": "boolean", + "default": false, + "description": "Enable the dialect-native semantic layer topics. Applicable for Snowflake and Databricks.", + "example": false + }, + "externalOauthAudience": { + "type": "string", + "description": "External OAuth audience claim. Applicable for Snowflake." + }, + "externalOauthAuthorizationUrl": { + "type": "string", + "format": "uri", + "description": "External OAuth authorization URL (must be HTTPS). Applicable for Snowflake.", + "example": "https://oauth.example.com/authorize" + }, + "externalOauthTokenUrl": { + "type": "string", + "format": "uri", + "description": "External OAuth token URL (must be HTTPS). Applicable for Snowflake.", + "example": "https://oauth.example.com/token" + }, + "host": { + "type": "string", + "description": "The hostname or IP address of the database server. For Snowflake, provide only the account identifier.", + "example": "myaccount" + }, + "hostOverride": { + "type": "string", + "description": "Custom Snowflake host (when not using the account identifier). Mutually exclusive with `host`.", + "example": "myaccount.snowflakecomputing.com" + }, + "includeOtherCatalogs": { + "type": "string", + "description": "Comma-separated list of other catalogs/databases to include. Only applicable for databases that support multi-catalog queries.", + "example": "other_project1,other_project2" + }, + "includeSchemas": { + "type": "string", + "description": "Comma-separated list of schemas to include. Leave empty to include all schemas.", + "example": "public,analytics" + }, + "inferRelationshipsFromColumnNames": { + "type": "boolean", + "default": true, + "description": "Whether to infer relationships from column-name conventions during schema refresh. Defaults to true.", + "example": true + }, + "inferRelationshipsFromForeignKeys": { + "type": "boolean", + "default": false, + "description": "Whether to infer relationships from declared foreign keys during schema refresh. Currently honored for Postgres and Snowflake.", + "example": false + }, + "maxBillingBytes": { + "type": "string", + "description": "Maximum bytes that can be billed for a BigQuery query. Applicable for BigQuery only.", + "example": "1000000000" + }, + "name": { + "type": "string", + "description": "A descriptive name for the connection", + "example": "Production Warehouse" + }, + "oauthClientId": { + "type": "string", + "description": "OAuth client ID for admin schema refresh. Applicable for Snowflake and Databricks." + }, + "oauthClientSecretUnencrypted": { + "type": "string", + "description": "OAuth client secret for admin schema refresh. Applicable for Snowflake and Databricks." + }, + "offloadedSchemas": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ], + "description": "Schemas whose tables should be queried via the offloaded engine. Accepts a comma-separated string or an array of schema names.", + "example": [ + "analytics_archive" + ] + }, + "passwordUnencrypted": { + "type": "string", + "description": "The password to authenticate with. For BigQuery, this must be the JSON service account key file content. For Snowflake with keypair authentication, this can be omitted." + }, + "port": { + "type": "integer", + "description": "The port number for the database connection. Not required for Snowflake, MotherDuck, BigQuery, Databricks, and Athena.", + "example": 5432 + }, + "privateKey": { + "type": "string", + "description": "An RSA key for keypair authentication. Omni will automatically add PEM headers if none are provided. Applicable for Snowflake only." + }, + "queryTimeoutSeconds": { + "type": "integer", + "maximum": 3600, + "description": "The timeout in seconds for queries. Maximum value is 3600 (1 hour). Only applicable for databases that support query timeouts.", + "example": 900 + }, + "queryTimezone": { + "type": "string", + "description": "The timezone to use for queries", + "example": "NONE" + }, + "region": { + "type": "string", + "description": "Required for BigQuery and Athena connections. For BigQuery, specify a region like \"us\". For Athena, specify an AWS region like \"us-east-1\".", + "example": "us-east-1" + }, + "scratchSchema": { + "type": "string", + "description": "Schema to use for data input (upload) tables. If not specified, a suitable default will be chosen.", + "example": "omni_scratch" + }, + "systemTimezone": { + "type": "string", + "description": "The timezone to use for the system", + "example": "UTC" + }, + "trustServerCertificate": { + "type": "boolean", + "default": false, + "description": "Whether to trust the server certificate. Applicable for MSSQL, Exasol, ClickHouse, Trino, and SAP HANA.", + "example": false + }, + "useMachineAuth": { + "type": "boolean", + "description": "Whether to authenticate using machine credentials (OAuth M2M). Applicable for Athena and Databricks.", + "example": false + }, + "username": { + "type": "string", + "description": "The username to authenticate with. For BigQuery, this is the client email from the service account.", + "example": "analytics_user" + }, + "warehouse": { + "type": "string", + "description": "Required for Snowflake (specify the warehouse) and Databricks (specify the HTTP path).", + "example": "COMPUTE_WH" + } + }, + "required": [ + "dialect", + "name", + "passwordUnencrypted" + ], + "description": "Request body for creating a database connection. Required fields: dialect, name, passwordUnencrypted. Additional fields may be required depending on the dialect.", + "title": "ConnectionsCreateBody" } } } }, "responses": { - "200": { - "description": "Topic selected successfully. The returned topicId can be used as the topicName parameter in other AI endpoints.", + "201": { + "description": "Connection created successfully", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/AiPickTopicResponse" + "type": "object", + "properties": { + "data": { + "type": "string", + "format": "uuid", + "description": "Created connection ID", + "example": "550e8400-e29b-41d4-a716-446655440000" + }, + "success": { + "type": "boolean", + "description": "Whether the operation succeeded", + "example": true + } + }, + "required": [ + "data", + "success" + ], + "description": "Create connection response", + "title": "ConnectionsCreateResponse" } } } }, "400": { - "description": "Invalid request body. The prompt or modelId may be missing or malformed.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiError400" - } - } - } + "description": "Invalid request body or dialect" }, "401": { - "description": "Missing or invalid API key.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiError401" - } - } - } + "description": "Authentication required" }, "403": { - "description": "Insufficient permissions. Requires the querier role on the target model and AI must be enabled for the organization.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiError403" - } - } - } - }, - "404": { - "description": "The specified model was not found, or no accessible topics exist in the model.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiError404" - } - } - } - }, - "500": { - "description": "AI service error." + "description": "Permission denied - admin role required" } } } }, - "/api/v1/ai/search-omni-docs": { - "post": { - "description": "Search the Omni documentation using AI to answer questions about Omni features, configuration, modeling, dashboards, and more. Sends a natural language question and returns a synthesized answer with source links to the relevant documentation pages.", - "operationId": "aiSearchOmniDocs", - "summary": "Search Omni documentation", + "/api/v1/connections/{id}": { + "get": { + "description": "Fetch a single connection by ID.", + "operationId": "connectionsGet", + "summary": "Get connection", "tags": [ - "AI" + "Connections" ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AiSearchOmniDocsBody" - } - } + "parameters": [ + { + "schema": { + "type": "string", + "format": "uuid", + "description": "Connection ID", + "example": "550e8400-e29b-41d4-a716-446655440000" + }, + "required": true, + "description": "Connection ID", + "name": "id", + "in": "path" } - }, + ], "responses": { "200": { - "description": "Documentation search completed successfully. Returns a synthesized answer with source links.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AiSearchOmniDocsResponse" - } - } - } - }, - "400": { - "description": "Invalid request. The question may be missing or exceed the 2000 character limit.", + "description": "Connection object", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ApiError400" + "type": "object", + "properties": { + "connection": { + "type": "object", + "properties": { + "baseRole": { + "type": [ + "string", + "null" + ], + "description": "Default role for users on this connection", + "example": "QUERIER" + }, + "branchConnectionEnvironmentOverridesUserAttr": { + "type": [ + "boolean", + "null" + ], + "description": "Whether branch environments override user attributes", + "example": false + }, + "createdAt": { + "type": "string", + "description": "Timestamp when connection was created (ISO 8601)", + "example": "2024-01-15T10:30:00Z" + }, + "database": { + "type": [ + "string", + "null" + ], + "description": "Database name", + "example": "analytics_db" + }, + "defaultSchema": { + "type": [ + "string", + "null" + ], + "description": "Default schema for the connection", + "example": "public" + }, + "deletedAt": { + "type": [ + "string", + "null" + ], + "description": "Timestamp when connection was deleted (ISO 8601)", + "example": null + }, + "dialect": { + "type": "string", + "enum": [ + "snowflake", + "bigquery", + "redshift", + "postgres", + "mysql", + "mariadb", + "databricks", + "databricks_lakebase", + "trino", + "athena", + "duckdb", + "motherduck", + "sqlserver", + "clickhouse", + "singlestore" + ], + "description": "Database dialect type", + "example": "snowflake" + }, + "environmentConnectionSwitchesSchemaModel": { + "type": [ + "boolean", + "null" + ], + "description": "Whether environment connections switch schema model", + "example": false + }, + "id": { + "type": "string", + "format": "uuid", + "description": "Unique connection identifier", + "example": "550e8400-e29b-41d4-a716-446655440000" + }, + "name": { + "type": "string", + "description": "Connection display name", + "example": "Production Snowflake" + }, + "updatedAt": { + "type": "string", + "description": "Timestamp when connection was last updated (ISO 8601)", + "example": "2024-01-15T10:30:00Z" + }, + "userAttributeNameForConnectionEnvironments": { + "type": [ + "string", + "null" + ], + "description": "User attribute name used for connection environments", + "example": "region" + }, + "userAttributeValuesForDefaultEnvironment": { + "type": [ + "array", + "null" + ], + "items": { + "type": "string" + }, + "description": "Default user attribute values for the base environment", + "example": [ + "us-east", + "us-west" + ] + } + }, + "required": [ + "baseRole", + "branchConnectionEnvironmentOverridesUserAttr", + "createdAt", + "database", + "defaultSchema", + "deletedAt", + "dialect", + "environmentConnectionSwitchesSchemaModel", + "id", + "name", + "updatedAt", + "userAttributeNameForConnectionEnvironments", + "userAttributeValuesForDefaultEnvironment" + ], + "description": "Connection object", + "title": "Connection" + } + }, + "required": [ + "connection" + ], + "description": "Get connection response", + "title": "ConnectionsGetResponse" } } } }, "401": { - "description": "Missing or invalid API key.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiError401" - } - } - } + "description": "Authentication required" }, "403": { - "description": "Omni Agent is not enabled for this organization.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiError403" - } - } - } + "description": "Permission denied — caller lacks READ on the connection" }, - "500": { - "description": "AI service error." + "404": { + "description": "Connection does not exist" } } - } - }, - "/api/v1/ai/jobs": { - "post": { - "description": "Submit a new AI job for asynchronous execution. The AI will analyze the prompt, generate and execute queries against the specified model, and produce a summarized answer. Jobs are processed by a background worker and typically complete within 15–60 seconds. Use GET /api/v1/ai/jobs/{jobId} to poll for status, or configure a webhookUrl to receive a notification when the job completes. Optionally continue an existing conversation by providing a conversationId.", - "operationId": "aiJobSubmit", - "summary": "Submit an AI job", + }, + "patch": { + "description": "Update connection settings including base role, environment user attributes, and credentials.\n\nCredential fields:\n- `passwordUnencrypted`: Update password (all dialects) or service account JSON (BigQuery)\n- `privateKey`: Add/rotate RSA keypair for Snowflake keypair authentication\n\nNote: Credentials are encrypted at rest and never returned in API responses.", + "operationId": "connectionsUpdate", + "summary": "Update connection", "tags": [ - "AI" + "Connections" ], "parameters": [ { "schema": { "type": "string", - "description": "Target user membership ID (for org-scoped API keys)" + "format": "uuid", + "description": "Connection ID", + "example": "550e8400-e29b-41d4-a716-446655440000" }, - "required": false, - "description": "Target user membership ID (for org-scoped API keys)", - "name": "userId", - "in": "query" + "required": true, + "description": "Connection ID", + "name": "id", + "in": "path" } ], "requestBody": { - "required": true, "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/AiJobSubmitBody" + "type": "object", + "properties": { + "baseRole": { + "type": "string", + "description": "Default role to assign to this connection", + "example": "QUERIER" + }, + "environmentUserAttribute": { + "type": [ + "object", + "null" + ], + "properties": { + "attributeName": { + "type": "string", + "description": "Name of the user attribute for environment selection", + "example": "region" + }, + "defaultValues": { + "type": [ + "array", + "null" + ], + "items": { + "type": "string" + }, + "description": "Default values for the user attribute", + "example": [ + "us-east", + "us-west" + ] + } + }, + "required": [ + "attributeName", + "defaultValues" + ], + "description": "User attribute settings for connection environments" + }, + "passwordUnencrypted": { + "type": "string", + "description": "New password or service account key. For BigQuery, this must be the JSON service account key file content." + }, + "privateKey": { + "type": "string", + "description": "RSA private key for keypair authentication (Snowflake only). Must be PEM-encoded PKCS#8 format, minimum 2048-bit." + } + }, + "description": "Request body for updating connection attributes and credentials. At least one field must be provided.", + "title": "ConnectionsUpdateBody" } } } }, "responses": { - "201": { - "description": "Job created and queued for execution. Use the returned jobId to poll for status or retrieve results.", + "200": { + "description": "Connection updated successfully", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/AiJobSubmitResponse" + "type": "object", + "properties": { + "message": { + "type": "string", + "description": "Status message describing what was updated", + "example": "Updated connection default role." + }, + "success": { + "type": "boolean", + "description": "Whether the operation succeeded", + "example": true + } + }, + "required": [ + "message", + "success" + ], + "description": "Update connection response", + "title": "ConnectionsUpdateResponse" } } } }, "400": { - "description": "Invalid request body. Common causes: missing or empty prompt, invalid UUID for modelId/branchId/conversationId, invalid webhook URL format.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiError400" - } - } - } + "description": "Invalid request body - at least one field must be provided" }, "401": { - "description": "Missing or invalid API key.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiError401" - } - } - } + "description": "Authentication required" }, "403": { - "description": "Insufficient permissions. The AI jobs API must be enabled for the organization, AI query generation must be enabled, and the user must have appropriate model access. User-scoped API keys cannot act on behalf of other users.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiError403" - } - } - } + "description": "Permission denied - connection admin role required" }, "404": { - "description": "The specified model was not found in the organization, the branchId does not belong to the specified model, or the topicName does not exist in the model (or is excluded by ai_chat_topics restrictions).", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiError404" - } - } - } - }, - "409": { - "description": "An active job already exists for the specified conversationId. Wait for the current job to complete before submitting another job to the same conversation.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiError409" - } - } - } + "description": "Connection not found" } } - } - }, - "/api/v1/ai/jobs/{jobId}": { - "get": { - "description": "Get the current status of an AI job, including its state, progress information, and result summary. The response fields vary by state — for example, progress is only present during EXECUTING, and resultSummary is only present when COMPLETE. Poll this endpoint every 2–5 seconds until the job reaches a terminal state (COMPLETE, FAILED, or CANCELLED).", - "operationId": "aiJobStatus", - "summary": "Get AI job status", + }, + "delete": { + "description": "Archive a connection (move to trash). Archived connections can be restored from the trash in the connection settings UI.\n\nA connection that is already archived returns 410.", + "operationId": "connectionsDelete", + "summary": "Delete connection", "tags": [ - "AI" + "Connections" ], "parameters": [ { "schema": { "type": "string", "format": "uuid", - "description": "The unique identifier of the AI job", - "example": "123e4567-e89b-12d3-a456-426614174000" + "description": "Connection ID", + "example": "550e8400-e29b-41d4-a716-446655440000" }, "required": true, - "description": "The unique identifier of the AI job", - "name": "jobId", + "description": "Connection ID", + "name": "id", "in": "path" } ], "responses": { "200": { - "description": "Job status retrieved successfully. Check the state field to determine if the job is still running or has reached a terminal state.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AiJobStatusResponse" - } - } - } - }, - "400": { - "description": "Invalid job ID format. Must be a valid UUID.", + "description": "Connection moved to trash", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ApiError400" + "type": "object", + "properties": { + "message": { + "type": "string", + "description": "Status message describing the result", + "example": "Connection moved to trash." + }, + "success": { + "type": "boolean", + "description": "True when the connection was archived", + "example": true + } + }, + "required": [ + "message", + "success" + ], + "description": "Archive connection response", + "title": "ConnectionsDeleteResponse" } } } }, "401": { - "description": "Missing or invalid API key.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiError401" - } - } - } + "description": "Authentication required" + }, + "403": { + "description": "Permission denied - connection admin role required" }, "404": { - "description": "Job not found. The job may not exist or may belong to a different organization.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiError404" - } - } - } + "description": "Connection not found" + }, + "410": { + "description": "Connection has already been archived" } } } }, - "/api/v1/ai/jobs/{jobId}/cancel": { - "post": { - "description": "Request cancellation of an AI job. This endpoint is idempotent — calling it on an already-cancelled or completed job returns success with the current state. For QUEUED jobs, cancellation is immediate. For EXECUTING jobs, the worker will stop after completing its current iteration. Jobs in DELIVERING state cannot be cancelled as they are already finalizing results. Only the job owner or organization admins can cancel jobs.", - "operationId": "aiJobCancel", - "summary": "Cancel an AI job", + "/api/v1/connections/{connectionId}/dbt": { + "get": { + "operationId": "connectionsDbtGet", + "summary": "Get dbt configuration", "tags": [ - "AI" + "Connections" ], "parameters": [ { "schema": { "type": "string", "format": "uuid", - "description": "The unique identifier of the AI job", - "example": "123e4567-e89b-12d3-a456-426614174000" + "description": "Connection ID", + "example": "550e8400-e29b-41d4-a716-446655440000" }, "required": true, - "description": "The unique identifier of the AI job", - "name": "jobId", + "description": "Connection ID", + "name": "connectionId", "in": "path" } ], "responses": { "200": { - "description": "Cancellation request processed. The state field indicates the job's state after the attempt — CANCELLED if successful, or the current terminal state if the job had already completed.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AiJobCancelResponse" - } - } - } - }, - "400": { - "description": "Invalid job ID format. Must be a valid UUID.", + "description": "dbt configuration for the connection", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ApiError400" + "anyOf": [ + { + "type": "object", + "properties": { + "autogenRelationships": { + "type": "boolean", + "description": "Whether relationships are auto-generated from dbt", + "example": true + }, + "branch": { + "type": "string", + "description": "Git branch name", + "example": "main" + }, + "dbtVersion": { + "type": "string", + "description": "dbt version being used", + "example": "Auto" + }, + "enableSemanticLayer": { + "type": "boolean", + "description": "Whether the dbt semantic layer integration is enabled", + "example": false + }, + "enableVirtualSchemas": { + "type": "boolean", + "description": "Whether virtual schemas are enabled", + "example": false + }, + "projectRootPath": { + "type": [ + "string", + "null" + ], + "description": "Path to dbt project root", + "example": "dbt_project" + }, + "sshUrl": { + "type": "string", + "description": "SSH URL for git repository", + "example": "git@github.com:org/repo.git" + }, + "supportsDbt": { + "type": "boolean", + "enum": [ + true + ], + "description": "Indicates dbt is supported and configured", + "example": true + } + }, + "required": [ + "autogenRelationships", + "branch", + "dbtVersion", + "enableSemanticLayer", + "enableVirtualSchemas", + "projectRootPath", + "sshUrl", + "supportsDbt" + ], + "description": "dbt repository configuration response", + "title": "DbtConfiguredResponse" + }, + { + "type": "object", + "properties": { + "message": { + "type": "string", + "description": "Message explaining dbt status", + "example": "dbt not configured for this connection" + }, + "supportsDbt": { + "type": "boolean", + "description": "Whether the connection dialect supports dbt", + "example": true + } + }, + "required": [ + "message", + "supportsDbt" + ], + "description": "Response when dbt is not configured", + "title": "DbtNotConfiguredResponse" + } + ], + "description": "dbt configuration response", + "title": "ConnectionsDbtGetResponse" } } } }, "401": { - "description": "Missing or invalid API key.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiError401" - } - } - } + "description": "Authentication required" }, "403": { - "description": "Permission denied. Only the job owner or organization admins can cancel jobs.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiError403" - } - } - } + "description": "Permission denied - connection admin role required" }, "404": { - "description": "Job not found. The job may not exist or may belong to a different organization.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiError404" - } - } - } - }, - "409": { - "description": "Concurrent modification conflict. The job state was changed by another request. Retry the cancellation.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiError409" - } - } - } + "description": "Connection not found" } } - } - }, - "/api/v1/ai/jobs/{jobId}/result": { - "get": { - "description": "Retrieve the full result of a completed AI job, including all actions taken by the AI (queries generated, data retrieved) and the final summarized answer. Results are only available for jobs in COMPLETE state and are retained for 14 days after completion. The response is streamed directly from storage.", - "operationId": "aiJobResult", - "summary": "Get AI job result", + }, + "put": { + "operationId": "connectionsDbtUpdate", + "summary": "Update dbt configuration", "tags": [ - "AI" + "Connections" ], "parameters": [ { "schema": { "type": "string", "format": "uuid", - "description": "The unique identifier of the AI job", - "example": "123e4567-e89b-12d3-a456-426614174000" + "description": "Connection ID", + "example": "550e8400-e29b-41d4-a716-446655440000" }, "required": true, - "description": "The unique identifier of the AI job", - "name": "jobId", + "description": "Connection ID", + "name": "connectionId", "in": "path" } ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "autogenRelationships": { + "type": "boolean", + "description": "Automatically generate relationships from dbt", + "example": true + }, + "branch": { + "type": "string", + "minLength": 1, + "description": "Git branch name", + "example": "main" + }, + "dbtVersion": { + "type": [ + "string", + "null" + ], + "description": "dbt version to use. Supported: Auto, 1.10, 1.11", + "example": "1.11" + }, + "enableSemanticLayer": { + "type": "boolean", + "default": false, + "description": "Enable dbt semantic layer integration", + "example": false + }, + "enableVirtualSchemas": { + "type": "boolean", + "description": "Enable virtual schemas from dbt", + "example": false + }, + "projectRootPath": { + "anyOf": [ + { + "type": "string", + "pattern": "^(?!\\/)(?!.*\\.\\.)[\\w ./-]+$" + }, + { + "type": "string", + "enum": [ + "" + ] + }, + { + "type": [ + "object", + "null" + ], + "enum": [ + null + ] + }, + { + "type": "null" + } + ], + "default": null, + "description": "Path to dbt project root within repository", + "example": "dbt_project" + }, + "rotateKeys": { + "type": "boolean", + "default": false, + "description": "Rotate SSH deploy keys", + "example": false + }, + "sshUrl": { + "type": "string", + "minLength": 1, + "description": "SSH URL for git repository", + "example": "git@github.com:org/repo.git" + } + }, + "required": [ + "autogenRelationships", + "branch", + "enableVirtualSchemas", + "sshUrl" + ], + "description": "dbt repository configuration", + "title": "ConnectionsDbtUpdateBody" + } + } + } + }, "responses": { "200": { - "description": "Full job result including the AI's actions, query results (with CSV data), and the final Markdown-formatted answer.", + "description": "dbt configuration updated successfully", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/AiJobResultResponse" + "type": "object", + "properties": { + "message": { + "type": "string", + "description": "Success message", + "example": "dbt configuration updated successfully" + }, + "success": { + "type": "boolean", + "description": "Whether the operation succeeded", + "example": true + } + }, + "required": [ + "message", + "success" + ], + "description": "dbt update response", + "title": "ConnectionsDbtUpdateResponse" } } } }, "400": { - "description": "Invalid job ID format. Must be a valid UUID.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiError400" - } - } - } + "description": "Invalid request body or validation error" }, "401": { - "description": "Missing or invalid API key.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiError401" - } - } - } + "description": "Authentication required" + }, + "403": { + "description": "Permission denied - connection admin role required" }, "404": { - "description": "Job not found, not in COMPLETE state, or result is no longer available (results are retained for 14 days).", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiError404" - } - } - } + "description": "Connection not found" } } - } - }, - "/api/v1/ai/jobs/{jobId}/vis": { - "get": { - "description": "Render the visualization from a completed AI job as a PNG image. The endpoint extracts the visualization configuration from the job result, loads Arrow IPC data, and renders it server-side using Vega. For style-only follow-ups (e.g., \"make it a bar chart\"), the endpoint walks back through previous jobs in the conversation to find the original query data.", - "operationId": "aiJobVisualization", - "summary": "Render AI job visualization", + }, + "delete": { + "operationId": "connectionsDbtDelete", + "summary": "Delete dbt configuration", "tags": [ - "AI" + "Connections" ], "parameters": [ { "schema": { "type": "string", "format": "uuid", - "description": "The unique identifier of the AI job", - "example": "123e4567-e89b-12d3-a456-426614174000" + "description": "Connection ID", + "example": "550e8400-e29b-41d4-a716-446655440000" }, "required": true, - "description": "The unique identifier of the AI job", - "name": "jobId", + "description": "Connection ID", + "name": "connectionId", "in": "path" } ], "responses": { "200": { - "description": "Visualization rendered as a PNG image. The Content-Type header is image/png.", - "content": { - "image/png": { - "schema": { - "format": "binary", - "type": "string" - } - } - } - }, - "400": { - "description": "Invalid job ID format. Must be a valid UUID.", + "description": "dbt configuration deleted successfully", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ApiError400" + "type": "object", + "properties": { + "message": { + "type": "string", + "description": "Success message", + "example": "dbt repository unlinked successfully" + }, + "success": { + "type": "boolean", + "description": "Whether the operation succeeded", + "example": true + } + }, + "required": [ + "message", + "success" + ], + "description": "dbt delete response", + "title": "ConnectionsDbtDeleteResponse" } } } }, "401": { - "description": "Missing or invalid API key.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiError401" - } - } - } + "description": "Authentication required" }, - "404": { - "description": "Job not found, not in COMPLETE state, or the apiAiVis feature flag is not enabled.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiError404" - } - } - } + "403": { + "description": "Permission denied - connection admin role required" }, - "422": { - "description": "The job completed but cannot be rendered as a visualization. Common causes: no visualization action in the job result, no Arrow IPC data available, missing summary fields, or the chart type is not renderable as an image (e.g., tables, KPIs).", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiError422" - } - } - } + "404": { + "description": "Connection not found or dbt not configured" } } } }, - "/api/v1/api-keys": { + "/api/v1/connections/{connectionId}/dbt/environments": { "get": { - "description": "Returns all API tokens in the organization, including organization-level keys, personal access tokens, and MCP OAuth grants. Secrets are never returned. Requires organization admin permissions.", - "operationId": "apiKeysList", - "summary": "List API tokens", + "description": "List all dbt environments for a connection.", + "operationId": "connectionsDbtEnvironmentsList", + "summary": "List dbt environments", "tags": [ - "API Tokens" + "Connections" ], "parameters": [ { "schema": { "type": "string", "format": "uuid", - "description": "Cursor from the previous response (token UUID)" + "description": "Connection ID", + "example": "550e8400-e29b-41d4-a716-446655440000" + }, + "required": true, + "description": "Connection ID", + "name": "connectionId", + "in": "path" + }, + { + "schema": { + "type": "string", + "description": "Cursor for pagination (from previous response nextCursor)", + "example": "eyJpZCI6IjEyMzQ1In0" }, "required": false, - "description": "Cursor from the previous response (token UUID)", + "description": "Cursor for pagination (from previous response nextCursor)", "name": "cursor", "in": "query" }, { "schema": { - "type": "number", + "type": "integer", "minimum": 1, "maximum": 100, "default": 20, - "description": "Number of results per page (1-100)", + "description": "Number of results per page (1-100, integer)", "example": 20 }, "required": false, - "description": "Number of results per page (1-100)", + "description": "Number of results per page (1-100, integer)", "name": "pageSize", "in": "query" }, @@ -8619,120 +32672,58 @@ "schema": { "type": "string", "enum": [ - "createdAt", "name" ], - "default": "createdAt" + "default": "name", + "description": "Field to sort results by", + "example": "name" }, "required": false, + "description": "Field to sort results by", "name": "sortField", "in": "query" - }, - { - "schema": { - "type": "string", - "enum": [ - "organization", - "personal", - "mcp" - ], - "description": "Filter by API token type. When omitted, all types are returned.", - "example": "personal" - }, - "required": false, - "description": "Filter by API token type. When omitted, all types are returned.", - "name": "type", - "in": "query" - } - ], - "responses": { - "200": { - "description": "Paginated list of API tokens", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiKeyListResponse" - } - } - } - }, - "400": { - "description": "Invalid query parameters" - }, - "401": { - "description": "Authentication required" - }, - "403": { - "description": "Insufficient permissions" - } - } - } - }, - "/api/v1/api-keys/{id}": { - "get": { - "description": "Returns a single API token by id. Requires organization admin permissions.", - "operationId": "apiKeysGet", - "summary": "Get API token", - "tags": [ - "API Tokens" - ], - "parameters": [ - { - "schema": { - "type": "string", - "format": "uuid", - "description": "Token UUID", - "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" - }, - "required": true, - "description": "Token UUID", - "name": "id", - "in": "path" } ], "responses": { "200": { - "description": "The requested API token", + "description": "List of dbt environments", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ApiKey" + "$ref": "#/components/schemas/DbtEnvironmentListResponse" } } } }, - "400": { - "description": "Malformed `id` (must be a UUID)" - }, "401": { "description": "Authentication required" }, "403": { - "description": "Insufficient permissions" + "description": "Permission denied or connection does not support dbt" }, "404": { - "description": "Token not found in this organization" + "description": "Connection not found" } } }, - "put": { - "description": "Enables or disables an organization-level API token. Personal access tokens and MCP OAuth grants do not support this operation. Requires organization admin permissions.", - "operationId": "apiKeysUpdate", - "summary": "Enable or disable an organization API token", + "post": { + "description": "Create a new dbt environment for a connection.", + "operationId": "connectionsDbtEnvironmentsCreate", + "summary": "Create dbt environment", "tags": [ - "API Tokens" + "Connections" ], "parameters": [ { "schema": { "type": "string", "format": "uuid", - "description": "Token UUID", - "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" + "description": "Connection ID", + "example": "550e8400-e29b-41d4-a716-446655440000" }, "required": true, - "description": "Token UUID", - "name": "id", + "description": "Connection ID", + "name": "connectionId", "in": "path" } ], @@ -8741,87 +32732,50 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ApiKeyUpdateBody" + "$ref": "#/components/schemas/DbtEnvironmentCreateBody" } } } }, "responses": { - "200": { - "description": "The updated API token", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiKey" - } - } - } - }, - "400": { - "description": "Invalid body, malformed `id`, target is not an organization token, or missing/malformed `Authorization` header" - }, - "403": { - "description": "Invalid bearer token, or caller lacks organization admin permissions" - }, - "404": { - "description": "Token not found in this organization" - }, - "405": { - "description": "Method not allowed" - } - } - }, - "delete": { - "description": "Revokes an API token by permanently deleting it. Works for all token types. Requires organization admin permissions.", - "operationId": "apiKeysDelete", - "summary": "Revoke an API token", - "tags": [ - "API Tokens" - ], - "parameters": [ - { - "schema": { - "type": "string", - "format": "uuid", - "description": "Token UUID", - "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" - }, - "required": true, - "description": "Token UUID", - "name": "id", - "in": "path" - } - ], - "responses": { - "200": { - "description": "The token was revoked", + "201": { + "description": "dbt environment created successfully", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ApiKeyDeleteResponse" + "allOf": [ + { + "$ref": "#/components/schemas/DbtEnvironmentItem" + }, + { + "description": "Created dbt environment", + "title": "DbtEnvironmentCreateResponse" + } + ] } } } }, "400": { - "description": "Malformed `id`, or missing/malformed `Authorization` header" + "description": "Invalid request body" + }, + "401": { + "description": "Authentication required" }, "403": { - "description": "Invalid bearer token, or caller lacks organization admin permissions" + "description": "Permission denied or connection does not support dbt" }, "404": { - "description": "Token not found in this organization" - }, - "405": { - "description": "Method not allowed" + "description": "Connection not found" } } } }, - "/api/v1/connections": { - "get": { - "operationId": "connectionsList", - "summary": "List connections", + "/api/v1/connections/{connectionId}/dbt/environments/{environmentId}": { + "put": { + "description": "Update an existing dbt environment for a connection.", + "operationId": "connectionsDbtEnvironmentsUpdate", + "summary": "Update dbt environment", "tags": [ "Connections" ], @@ -8829,532 +32783,252 @@ { "schema": { "type": "string", - "description": "Filter by database name (case-insensitive contains)", - "example": "analytics" - }, - "required": false, - "description": "Filter by database name (case-insensitive contains)", - "name": "database", - "in": "query" - }, - { - "schema": { - "type": "string", - "description": "Filter by dialect(s). Comma-separated list for multiple values", - "example": "snowflake,bigquery" - }, - "required": false, - "description": "Filter by dialect(s). Comma-separated list for multiple values", - "name": "dialect", - "in": "query" - }, - { - "schema": { - "type": "boolean", - "description": "Include soft-deleted connections in results", - "example": false - }, - "required": false, - "description": "Include soft-deleted connections in results", - "name": "includeDeleted", - "in": "query" - }, - { - "schema": { - "type": "string", - "description": "Filter by connection name (case-insensitive contains)", - "example": "Production" - }, - "required": false, - "description": "Filter by connection name (case-insensitive contains)", - "name": "name", - "in": "query" - }, - { - "schema": { - "type": "string", - "enum": [ - "asc", - "desc" - ], - "description": "Sort direction", - "example": "desc" + "format": "uuid", + "description": "Connection ID", + "example": "550e8400-e29b-41d4-a716-446655440000" }, - "required": false, - "description": "Sort direction", - "name": "sortDirection", - "in": "query" + "required": true, + "description": "Connection ID", + "name": "connectionId", + "in": "path" }, { "schema": { "type": "string", - "enum": [ - "database", - "dialect", - "name" - ], - "description": "Field to sort by", - "example": "name" + "format": "uuid", + "description": "Environment ID", + "example": "247dc6dc-2a58-4688-9521-c5ed3e99c1e8" }, - "required": false, - "description": "Field to sort by", - "name": "sortField", - "in": "query" + "required": true, + "description": "Environment ID", + "name": "environmentId", + "in": "path" } ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DbtEnvironmentUpdateBody" + } + } + } + }, "responses": { "200": { - "description": "List of connections", + "description": "dbt environment updated successfully", "content": { "application/json": { "schema": { - "type": "object", - "properties": { - "connections": { - "type": "array", - "items": { - "type": "object", - "properties": { - "baseRole": { - "type": [ - "string", - "null" - ], - "description": "Default role for users on this connection", - "example": "QUERIER" - }, - "branchConnectionEnvironmentOverridesUserAttr": { - "type": [ - "boolean", - "null" - ], - "description": "Whether branch environments override user attributes", - "example": false - }, - "database": { - "type": [ - "string", - "null" - ], - "description": "Database name", - "example": "analytics_db" - }, - "defaultSchema": { - "type": [ - "string", - "null" - ], - "description": "Default schema for the connection", - "example": "public" - }, - "deletedAt": { - "type": [ - "string", - "null" - ], - "description": "Timestamp when connection was deleted (ISO 8601)", - "example": null - }, - "dialect": { - "type": "string", - "enum": [ - "snowflake", - "bigquery", - "redshift", - "postgres", - "mysql", - "mariadb", - "databricks", - "databricks_lakebase", - "trino", - "athena", - "duckdb", - "motherduck", - "sqlserver", - "clickhouse", - "singlestore" - ], - "description": "Database dialect type", - "example": "snowflake" - }, - "environmentConnectionSwitchesSchemaModel": { - "type": [ - "boolean", - "null" - ], - "description": "Whether environment connections switch schema model", - "example": false - }, - "id": { - "type": "string", - "format": "uuid", - "description": "Unique connection identifier", - "example": "550e8400-e29b-41d4-a716-446655440000" - }, - "name": { - "type": "string", - "description": "Connection display name", - "example": "Production Snowflake" - }, - "userAttributeNameForConnectionsEnvironments": { - "type": [ - "string", - "null" - ], - "description": "User attribute name used for connection environments", - "example": "region" - }, - "userAttributeValuesForDefaultEnvironment": { - "type": [ - "array", - "null" - ], - "items": { - "type": "string" - }, - "description": "Default user attribute values for the base environment", - "example": [ - "us-east", - "us-west" - ] - } - }, - "required": [ - "baseRole", - "branchConnectionEnvironmentOverridesUserAttr", - "database", - "defaultSchema", - "deletedAt", - "dialect", - "environmentConnectionSwitchesSchemaModel", - "id", - "name", - "userAttributeNameForConnectionsEnvironments", - "userAttributeValuesForDefaultEnvironment" - ], - "description": "Connection object", - "title": "Connection" - }, - "description": "List of connections" + "allOf": [ + { + "$ref": "#/components/schemas/DbtEnvironmentItem" + }, + { + "description": "Updated dbt environment", + "title": "DbtEnvironmentUpdateResponse" } - }, - "required": [ - "connections" - ], - "description": "List connections response", - "title": "ConnectionsListResponse" + ] } } } }, + "400": { + "description": "Invalid request body" + }, "401": { "description": "Authentication required" }, "403": { - "description": "Permission denied - admin role required" + "description": "Permission denied or connection does not support dbt" + }, + "404": { + "description": "Connection or environment not found" } } }, - "post": { - "description": "Create a new database connection. The request body varies by dialect - see dialect-specific documentation for required fields.", - "operationId": "connectionsCreate", - "summary": "Create connection", - "tags": [ - "Connections" - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "acceptsLicense": { - "type": "boolean", - "description": "Acceptance of the license terms. Required for Oracle connections.", - "example": true - }, - "allowsUserSpecificTimezones": { - "type": "boolean", - "default": false, - "description": "Whether to allow users to specify their own timezones", - "example": false - }, - "alwaysScopeViewNames": { - "type": "boolean", - "description": "Whether to always include schema (and catalog) prefixes in generated view names, even for tables in the default schema. Defaults to true for dialects that support multiple catalogs, false otherwise.", - "example": true - }, - "authenticationType": { - "type": "string", - "description": "Authentication type. Applicable for BigQuery, MSSQL, Snowflake, Databricks, and Athena.", - "example": "snowflake-password" - }, - "awsRoleArn": { - "type": "string", - "description": "AWS IAM role ARN. Applicable for Athena only.", - "example": "arn:aws:iam::123456789012:role/OmniAthenaRole" - }, - "baseRole": { - "type": "string", - "enum": [ - "NO_ACCESS", - "VIEWER", - "RESTRICTED_QUERIER", - "QUERIER", - "MODELER", - "CONNECTION_ADMIN" - ], - "description": "The default role for users accessing the connection", - "example": "QUERIER" - }, - "database": { - "type": "string", - "description": "The default database/catalog to connect to. For BigQuery, this is the project ID. For Athena, this is the data catalog.", - "example": "analytics_db" - }, - "defaultSchema": { - "type": "string", - "description": "The default schema to use. Required for MSSQL.", - "example": "public" - }, - "dialect": { - "type": "string", - "enum": [ - "athena", - "bigquery", - "clickhouse", - "databricks", - "databricks_lakebase", - "exasol", - "mariadb", - "motherduck", - "mssql", - "mysql", - "oracle", - "postgres", - "redshift", - "sap_hana", - "snowflake", - "starrocks", - "trino" - ], - "description": "The database dialect", - "example": "snowflake" - }, - "enableDbSemanticLayerIntegration": { - "type": "boolean", - "default": false, - "description": "Enable the dialect-native semantic layer integration. Applicable for Snowflake and Databricks.", - "example": false - }, - "enableDbSemanticLayerTopics": { - "type": "boolean", - "default": false, - "description": "Enable the dialect-native semantic layer topics. Applicable for Snowflake and Databricks.", - "example": false - }, - "externalOauthAudience": { - "type": "string", - "description": "External OAuth audience claim. Applicable for Snowflake." - }, - "externalOauthAuthorizationUrl": { - "type": "string", - "format": "uri", - "description": "External OAuth authorization URL (must be HTTPS). Applicable for Snowflake.", - "example": "https://oauth.example.com/authorize" - }, - "externalOauthTokenUrl": { - "type": "string", - "format": "uri", - "description": "External OAuth token URL (must be HTTPS). Applicable for Snowflake.", - "example": "https://oauth.example.com/token" - }, - "host": { - "type": "string", - "description": "The hostname or IP address of the database server. For Snowflake, provide only the account identifier.", - "example": "myaccount" - }, - "hostOverride": { - "type": "string", - "description": "Custom Snowflake host (when not using the account identifier). Mutually exclusive with `host`.", - "example": "myaccount.snowflakecomputing.com" - }, - "includeOtherCatalogs": { - "type": "string", - "description": "Comma-separated list of other catalogs/databases to include. Only applicable for databases that support multi-catalog queries.", - "example": "other_project1,other_project2" - }, - "includeSchemas": { - "type": "string", - "description": "Comma-separated list of schemas to include. Leave empty to include all schemas.", - "example": "public,analytics" - }, - "inferRelationshipsFromColumnNames": { - "type": "boolean", - "default": true, - "description": "Whether to infer relationships from column-name conventions during schema refresh. Defaults to true.", - "example": true - }, - "inferRelationshipsFromForeignKeys": { - "type": "boolean", - "default": false, - "description": "Whether to infer relationships from declared foreign keys during schema refresh. Currently honored for Postgres and Snowflake.", - "example": false - }, - "maxBillingBytes": { - "type": "string", - "description": "Maximum bytes that can be billed for a BigQuery query. Applicable for BigQuery only.", - "example": "1000000000" - }, - "name": { - "type": "string", - "description": "A descriptive name for the connection", - "example": "Production Warehouse" - }, - "oauthClientId": { - "type": "string", - "description": "OAuth client ID for admin schema refresh. Applicable for Snowflake and Databricks." - }, - "oauthClientSecretUnencrypted": { - "type": "string", - "description": "OAuth client secret for admin schema refresh. Applicable for Snowflake and Databricks." - }, - "offloadedSchemas": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "description": "Schemas whose tables should be queried via the offloaded engine. Accepts a comma-separated string or an array of schema names.", - "example": [ - "analytics_archive" - ] - }, - "passwordUnencrypted": { - "type": "string", - "description": "The password to authenticate with. For BigQuery, this must be the JSON service account key file content. For Snowflake with keypair authentication, this can be omitted." - }, - "port": { - "type": "integer", - "description": "The port number for the database connection. Not required for Snowflake, MotherDuck, BigQuery, Databricks, and Athena.", - "example": 5432 - }, - "privateKey": { - "type": "string", - "description": "An RSA key for keypair authentication. Omni will automatically add PEM headers if none are provided. Applicable for Snowflake only." - }, - "queryTimeoutSeconds": { - "type": "integer", - "maximum": 3600, - "description": "The timeout in seconds for queries. Maximum value is 3600 (1 hour). Only applicable for databases that support query timeouts.", - "example": 900 - }, - "queryTimezone": { - "type": "string", - "description": "The timezone to use for queries", - "example": "NONE" - }, - "region": { - "type": "string", - "description": "Required for BigQuery and Athena connections. For BigQuery, specify a region like \"us\". For Athena, specify an AWS region like \"us-east-1\".", - "example": "us-east-1" - }, - "scratchSchema": { - "type": "string", - "description": "Schema to use for data input (upload) tables. If not specified, a suitable default will be chosen.", - "example": "omni_scratch" - }, - "systemTimezone": { - "type": "string", - "description": "The timezone to use for the system", - "example": "UTC" - }, - "trustServerCertificate": { - "type": "boolean", - "default": false, - "description": "Whether to trust the server certificate. Applicable for MSSQL, Exasol, ClickHouse, Trino, and SAP HANA.", - "example": false - }, - "useMachineAuth": { - "type": "boolean", - "description": "Whether to authenticate using machine credentials (OAuth M2M). Applicable for Athena and Databricks.", - "example": false - }, - "username": { - "type": "string", - "description": "The username to authenticate with. For BigQuery, this is the client email from the service account.", - "example": "analytics_user" - }, - "warehouse": { - "type": "string", - "description": "Required for Snowflake (specify the warehouse) and Databricks (specify the HTTP path).", - "example": "COMPUTE_WH" - } - }, - "required": [ - "dialect", - "name", - "passwordUnencrypted" - ], - "description": "Request body for creating a database connection. Required fields: dialect, name, passwordUnencrypted. Additional fields may be required depending on the dialect.", - "title": "ConnectionsCreateBody" + "delete": { + "description": "Delete a dbt environment from a connection.", + "operationId": "connectionsDbtEnvironmentsDelete", + "summary": "Delete dbt environment", + "tags": [ + "Connections" + ], + "parameters": [ + { + "schema": { + "type": "string", + "format": "uuid", + "description": "Connection ID", + "example": "550e8400-e29b-41d4-a716-446655440000" + }, + "required": true, + "description": "Connection ID", + "name": "connectionId", + "in": "path" + }, + { + "schema": { + "type": "string", + "format": "uuid", + "description": "Environment ID", + "example": "247dc6dc-2a58-4688-9521-c5ed3e99c1e8" + }, + "required": true, + "description": "Environment ID", + "name": "environmentId", + "in": "path" + } + ], + "responses": { + "200": { + "description": "dbt environment deleted successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DbtEnvironmentDeleteResponse" + } } } + }, + "401": { + "description": "Authentication required" + }, + "403": { + "description": "Permission denied or connection does not support dbt" + }, + "404": { + "description": "Connection or environment not found" } - }, + } + } + }, + "/api/v1/connections/{connectionId}/schedules": { + "get": { + "operationId": "connectionsSchedulesList", + "summary": "List schema refresh schedules", + "tags": [ + "Connections" + ], + "parameters": [ + { + "schema": { + "type": "string", + "format": "uuid", + "description": "Connection ID", + "example": "550e8400-e29b-41d4-a716-446655440000" + }, + "required": true, + "description": "Connection ID", + "name": "connectionId", + "in": "path" + } + ], "responses": { - "201": { - "description": "Connection created successfully", + "200": { + "description": "List of schema refresh schedules", "content": { "application/json": { "schema": { "type": "object", "properties": { - "data": { - "type": "string", - "format": "uuid", - "description": "Created connection ID", - "example": "550e8400-e29b-41d4-a716-446655440000" - }, - "success": { - "type": "boolean", - "description": "Whether the operation succeeded", - "example": true + "schedules": { + "type": "array", + "items": { + "type": "object", + "properties": { + "connectionId": { + "type": "string", + "format": "uuid", + "description": "Connection ID this schedule belongs to", + "example": "550e8400-e29b-41d4-a716-446655440000" + }, + "createdAt": { + "type": "string", + "description": "Schedule creation timestamp (ISO 8601)", + "example": "2024-01-15T10:30:00Z" + }, + "description": { + "type": "string", + "description": "Human-readable schedule description", + "example": "Runs daily at 2:00 AM EST" + }, + "disabledAt": { + "type": [ + "string", + "null" + ], + "description": "Timestamp when schedule was disabled (ISO 8601)", + "example": null + }, + "hardRefresh": { + "type": "boolean", + "description": "When true, the scheduled refresh performs a hard refresh that fully discards and rebuilds the schema model. When false, it performs a soft refresh that merges newly generated views with the existing model.", + "example": false + }, + "schedule": { + "type": "string", + "description": "AWS EventBridge cron expression (6 fields: minute hour day-of-month month day-of-week year). See https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-cron-expressions.html", + "example": "0 2 * * ? *" + }, + "scheduleId": { + "type": "string", + "format": "uuid", + "description": "Unique schedule identifier", + "example": "550e8400-e29b-41d4-a716-446655440001" + }, + "timezone": { + "type": "string", + "description": "IANA timezone for schedule execution", + "example": "America/New_York" + }, + "updatedAt": { + "type": "string", + "description": "Schedule last update timestamp (ISO 8601)", + "example": "2024-01-15T10:30:00Z" + } + }, + "required": [ + "connectionId", + "createdAt", + "description", + "disabledAt", + "hardRefresh", + "schedule", + "scheduleId", + "timezone", + "updatedAt" + ], + "description": "Schema refresh schedule object", + "title": "ConnectionSchedule" + }, + "description": "List of schema refresh schedules" } }, "required": [ - "data", - "success" + "schedules" ], - "description": "Create connection response", - "title": "ConnectionsCreateResponse" + "description": "List schedules response", + "title": "ConnectionsSchedulesListResponse" } } } }, - "400": { - "description": "Invalid request body or dialect" - }, "401": { "description": "Authentication required" }, "403": { - "description": "Permission denied - admin role required" + "description": "Permission denied - connection admin role required" + }, + "404": { + "description": "Connection not found" } } - } - }, - "/api/v1/connections/{id}": { - "patch": { - "description": "Update connection settings including base role, environment user attributes, and credentials.\n\nCredential fields:\n- `passwordUnencrypted`: Update password (all dialects) or service account JSON (BigQuery)\n- `privateKey`: Add/rotate RSA keypair for Snowflake keypair authentication\n\nNote: Credentials are encrypted at rest and never returned in API responses.", - "operationId": "connectionsUpdate", - "summary": "Update connection", + }, + "post": { + "operationId": "connectionsSchedulesCreate", + "summary": "Create schema refresh schedule", "tags": [ "Connections" ], @@ -9368,7 +33042,7 @@ }, "required": true, "description": "Connection ID", - "name": "id", + "name": "connectionId", "in": "path" } ], @@ -9378,89 +33052,111 @@ "schema": { "type": "object", "properties": { - "baseRole": { - "type": "string", - "description": "Default role to assign to this connection", - "example": "QUERIER" - }, - "environmentUserAttribute": { - "type": [ - "object", - "null" - ], - "properties": { - "attributeName": { - "type": "string", - "description": "Name of the user attribute for environment selection", - "example": "region" - }, - "defaultValues": { - "type": [ - "array", - "null" - ], - "items": { - "type": "string" - }, - "description": "Default values for the user attribute", - "example": [ - "us-east", - "us-west" - ] - } - }, - "required": [ - "attributeName", - "defaultValues" - ], - "description": "User attribute settings for connection environments" + "hardRefresh": { + "type": "boolean", + "default": false, + "description": "When true, the scheduled refresh performs a hard refresh that fully discards and rebuilds the schema model. When false (the default), it performs a soft refresh that merges newly generated views with the existing model.", + "example": false }, - "passwordUnencrypted": { + "schedule": { "type": "string", - "description": "New password or service account key. For BigQuery, this must be the JSON service account key file content." + "description": "AWS EventBridge cron expression (6 fields: minute hour day-of-month month day-of-week year). See https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-cron-expressions.html", + "example": "0 2 * * ? *" }, - "privateKey": { + "timezone": { "type": "string", - "description": "RSA private key for keypair authentication (Snowflake only). Must be PEM-encoded PKCS#8 format, minimum 2048-bit." + "description": "IANA timezone for schedule execution", + "example": "America/New_York" } }, - "description": "Request body for updating connection attributes and credentials. At least one field must be provided.", - "title": "ConnectionsUpdateBody" + "required": [ + "schedule", + "timezone" + ], + "description": "Request body for creating a schema refresh schedule", + "title": "ConnectionsSchedulesCreateBody" } } } }, "responses": { - "200": { - "description": "Connection updated successfully", + "201": { + "description": "Schema refresh schedule created successfully", "content": { "application/json": { "schema": { "type": "object", "properties": { - "message": { + "connectionId": { + "type": "string", + "format": "uuid", + "description": "Connection ID this schedule belongs to", + "example": "550e8400-e29b-41d4-a716-446655440000" + }, + "createdAt": { + "type": "string", + "description": "Schedule creation timestamp (ISO 8601)", + "example": "2024-01-15T10:30:00Z" + }, + "description": { "type": "string", - "description": "Status message describing what was updated", - "example": "Updated connection default role." + "description": "Human-readable schedule description", + "example": "Runs daily at 2:00 AM EST" }, - "success": { + "disabledAt": { + "type": [ + "string", + "null" + ], + "description": "Timestamp when schedule was disabled (ISO 8601)", + "example": null + }, + "hardRefresh": { "type": "boolean", - "description": "Whether the operation succeeded", - "example": true + "description": "When true, the scheduled refresh performs a hard refresh that fully discards and rebuilds the schema model. When false, it performs a soft refresh that merges newly generated views with the existing model.", + "example": false + }, + "schedule": { + "type": "string", + "description": "AWS EventBridge cron expression (6 fields: minute hour day-of-month month day-of-week year). See https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-cron-expressions.html", + "example": "0 2 * * ? *" + }, + "scheduleId": { + "type": "string", + "format": "uuid", + "description": "Unique schedule identifier", + "example": "550e8400-e29b-41d4-a716-446655440001" + }, + "timezone": { + "type": "string", + "description": "IANA timezone for schedule execution", + "example": "America/New_York" + }, + "updatedAt": { + "type": "string", + "description": "Schedule last update timestamp (ISO 8601)", + "example": "2024-01-15T10:30:00Z" } }, "required": [ - "message", - "success" + "connectionId", + "createdAt", + "description", + "disabledAt", + "hardRefresh", + "schedule", + "scheduleId", + "timezone", + "updatedAt" ], - "description": "Update connection response", - "title": "ConnectionsUpdateResponse" + "description": "Created schedule response", + "title": "ConnectionsSchedulesCreateResponse" } } } }, "400": { - "description": "Invalid request body - at least one field must be provided" + "description": "Invalid cron expression or timezone" }, "401": { "description": "Authentication required" @@ -9474,10 +33170,10 @@ } } }, - "/api/v1/connections/{connectionId}/dbt": { + "/api/v1/connections/{connectionId}/schedules/{scheduleId}": { "get": { - "operationId": "connectionsDbtGet", - "summary": "Get dbt configuration", + "operationId": "connectionsSchedulesGet", + "summary": "Get schema refresh schedule", "tags": [ "Connections" ], @@ -9493,102 +33189,92 @@ "description": "Connection ID", "name": "connectionId", "in": "path" + }, + { + "schema": { + "type": "string", + "format": "uuid", + "description": "Schedule ID", + "example": "550e8400-e29b-41d4-a716-446655440001" + }, + "required": true, + "description": "Schedule ID", + "name": "scheduleId", + "in": "path" } ], "responses": { "200": { - "description": "dbt configuration for the connection", + "description": "Schema refresh schedule details", "content": { "application/json": { "schema": { - "anyOf": [ - { - "type": "object", - "properties": { - "autogenRelationships": { - "type": "boolean", - "description": "Whether relationships are auto-generated from dbt", - "example": true - }, - "branch": { - "type": "string", - "description": "Git branch name", - "example": "main" - }, - "dbtVersion": { - "type": "string", - "description": "dbt version being used", - "example": "Auto" - }, - "enableSemanticLayer": { - "type": "boolean", - "description": "Whether the dbt semantic layer integration is enabled", - "example": false - }, - "enableVirtualSchemas": { - "type": "boolean", - "description": "Whether virtual schemas are enabled", - "example": false - }, - "projectRootPath": { - "type": [ - "string", - "null" - ], - "description": "Path to dbt project root", - "example": "dbt_project" - }, - "sshUrl": { - "type": "string", - "description": "SSH URL for git repository", - "example": "git@github.com:org/repo.git" - }, - "supportsDbt": { - "type": "boolean", - "enum": [ - true - ], - "description": "Indicates dbt is supported and configured", - "example": true - } - }, - "required": [ - "autogenRelationships", - "branch", - "dbtVersion", - "enableSemanticLayer", - "enableVirtualSchemas", - "projectRootPath", - "sshUrl", - "supportsDbt" - ], - "description": "dbt repository configuration response", - "title": "DbtConfiguredResponse" + "type": "object", + "properties": { + "connectionId": { + "type": "string", + "format": "uuid", + "description": "Connection ID this schedule belongs to", + "example": "550e8400-e29b-41d4-a716-446655440000" }, - { - "type": "object", - "properties": { - "message": { - "type": "string", - "description": "Message explaining dbt status", - "example": "dbt not configured for this connection" - }, - "supportsDbt": { - "type": "boolean", - "description": "Whether the connection dialect supports dbt", - "example": true - } - }, - "required": [ - "message", - "supportsDbt" + "createdAt": { + "type": "string", + "description": "Schedule creation timestamp (ISO 8601)", + "example": "2024-01-15T10:30:00Z" + }, + "description": { + "type": "string", + "description": "Human-readable schedule description", + "example": "Runs daily at 2:00 AM EST" + }, + "disabledAt": { + "type": [ + "string", + "null" ], - "description": "Response when dbt is not configured", - "title": "DbtNotConfiguredResponse" + "description": "Timestamp when schedule was disabled (ISO 8601)", + "example": null + }, + "hardRefresh": { + "type": "boolean", + "description": "When true, the scheduled refresh performs a hard refresh that fully discards and rebuilds the schema model. When false, it performs a soft refresh that merges newly generated views with the existing model.", + "example": false + }, + "schedule": { + "type": "string", + "description": "AWS EventBridge cron expression (6 fields: minute hour day-of-month month day-of-week year). See https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-cron-expressions.html", + "example": "0 2 * * ? *" + }, + "scheduleId": { + "type": "string", + "format": "uuid", + "description": "Unique schedule identifier", + "example": "550e8400-e29b-41d4-a716-446655440001" + }, + "timezone": { + "type": "string", + "description": "IANA timezone for schedule execution", + "example": "America/New_York" + }, + "updatedAt": { + "type": "string", + "description": "Schedule last update timestamp (ISO 8601)", + "example": "2024-01-15T10:30:00Z" } + }, + "required": [ + "connectionId", + "createdAt", + "description", + "disabledAt", + "hardRefresh", + "schedule", + "scheduleId", + "timezone", + "updatedAt" ], - "description": "dbt configuration response", - "title": "ConnectionsDbtGetResponse" + "description": "Get schedule response", + "title": "ConnectionsSchedulesGetResponse" } } } @@ -9600,13 +33286,13 @@ "description": "Permission denied - connection admin role required" }, "404": { - "description": "Connection not found" + "description": "Connection or schedule not found" } } }, "put": { - "operationId": "connectionsDbtUpdate", - "summary": "Update dbt configuration", + "operationId": "connectionsSchedulesUpdate", + "summary": "Update schema refresh schedule", "tags": [ "Connections" ], @@ -9622,129 +33308,131 @@ "description": "Connection ID", "name": "connectionId", "in": "path" + }, + { + "schema": { + "type": "string", + "format": "uuid", + "description": "Schedule ID", + "example": "550e8400-e29b-41d4-a716-446655440001" + }, + "required": true, + "description": "Schedule ID", + "name": "scheduleId", + "in": "path" } ], "requestBody": { "content": { "application/json": { "schema": { - "type": "object", - "properties": { - "autogenRelationships": { - "type": "boolean", - "description": "Automatically generate relationships from dbt", - "example": true - }, - "branch": { - "type": "string", - "minLength": 1, - "description": "Git branch name", - "example": "main" - }, - "dbtVersion": { - "type": [ - "string", - "null" - ], - "description": "dbt version to use. Supported: Auto, 1.10, 1.11", - "example": "1.11" - }, - "enableSemanticLayer": { + "type": "object", + "properties": { + "hardRefresh": { "type": "boolean", "default": false, - "description": "Enable dbt semantic layer integration", - "example": false - }, - "enableVirtualSchemas": { - "type": "boolean", - "description": "Enable virtual schemas from dbt", + "description": "When true, the scheduled refresh performs a hard refresh that fully discards and rebuilds the schema model. When false (the default), it performs a soft refresh that merges newly generated views with the existing model.", "example": false }, - "projectRootPath": { - "anyOf": [ - { - "type": "string", - "pattern": "^(?!\\/)(?!.*\\.\\.)[\\w ./-]+$" - }, - { - "type": "string", - "enum": [ - "" - ] - }, - { - "type": [ - "object", - "null" - ], - "enum": [ - null - ] - }, - { - "type": "null" - } - ], - "default": null, - "description": "Path to dbt project root within repository", - "example": "dbt_project" - }, - "rotateKeys": { - "type": "boolean", - "default": false, - "description": "Rotate SSH deploy keys", - "example": false + "schedule": { + "type": "string", + "description": "AWS EventBridge cron expression (6 fields: minute hour day-of-month month day-of-week year). See https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-cron-expressions.html", + "example": "0 2 * * ? *" }, - "sshUrl": { + "timezone": { "type": "string", - "minLength": 1, - "description": "SSH URL for git repository", - "example": "git@github.com:org/repo.git" + "description": "IANA timezone for schedule execution", + "example": "America/New_York" } }, "required": [ - "autogenRelationships", - "branch", - "enableVirtualSchemas", - "sshUrl" + "schedule", + "timezone" ], - "description": "dbt repository configuration", - "title": "ConnectionsDbtUpdateBody" + "description": "Request body for updating a schema refresh schedule", + "title": "ConnectionsSchedulesUpdateBody" } } } }, "responses": { "200": { - "description": "dbt configuration updated successfully", + "description": "Schema refresh schedule updated successfully", "content": { "application/json": { "schema": { "type": "object", "properties": { - "message": { + "connectionId": { "type": "string", - "description": "Success message", - "example": "dbt configuration updated successfully" + "format": "uuid", + "description": "Connection ID this schedule belongs to", + "example": "550e8400-e29b-41d4-a716-446655440000" }, - "success": { + "createdAt": { + "type": "string", + "description": "Schedule creation timestamp (ISO 8601)", + "example": "2024-01-15T10:30:00Z" + }, + "description": { + "type": "string", + "description": "Human-readable schedule description", + "example": "Runs daily at 2:00 AM EST" + }, + "disabledAt": { + "type": [ + "string", + "null" + ], + "description": "Timestamp when schedule was disabled (ISO 8601)", + "example": null + }, + "hardRefresh": { "type": "boolean", - "description": "Whether the operation succeeded", - "example": true + "description": "When true, the scheduled refresh performs a hard refresh that fully discards and rebuilds the schema model. When false, it performs a soft refresh that merges newly generated views with the existing model.", + "example": false + }, + "schedule": { + "type": "string", + "description": "AWS EventBridge cron expression (6 fields: minute hour day-of-month month day-of-week year). See https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-cron-expressions.html", + "example": "0 2 * * ? *" + }, + "scheduleId": { + "type": "string", + "format": "uuid", + "description": "Unique schedule identifier", + "example": "550e8400-e29b-41d4-a716-446655440001" + }, + "timezone": { + "type": "string", + "description": "IANA timezone for schedule execution", + "example": "America/New_York" + }, + "updatedAt": { + "type": "string", + "description": "Schedule last update timestamp (ISO 8601)", + "example": "2024-01-15T10:30:00Z" } }, "required": [ - "message", - "success" + "connectionId", + "createdAt", + "description", + "disabledAt", + "hardRefresh", + "schedule", + "scheduleId", + "timezone", + "updatedAt" ], - "description": "dbt update response", - "title": "ConnectionsDbtUpdateResponse" + "description": "Updated schedule response", + "title": "ConnectionsSchedulesUpdateResponse" } } } }, "400": { - "description": "Invalid request body or validation error" + "description": "Invalid cron expression or timezone" }, "401": { "description": "Authentication required" @@ -9753,13 +33441,13 @@ "description": "Permission denied - connection admin role required" }, "404": { - "description": "Connection not found" + "description": "Connection or schedule not found" } } }, "delete": { - "operationId": "connectionsDbtDelete", - "summary": "Delete dbt configuration", + "operationId": "connectionsSchedulesDelete", + "summary": "Delete schema refresh schedule", "tags": [ "Connections" ], @@ -9775,21 +33463,28 @@ "description": "Connection ID", "name": "connectionId", "in": "path" + }, + { + "schema": { + "type": "string", + "format": "uuid", + "description": "Schedule ID", + "example": "550e8400-e29b-41d4-a716-446655440001" + }, + "required": true, + "description": "Schedule ID", + "name": "scheduleId", + "in": "path" } ], "responses": { "200": { - "description": "dbt configuration deleted successfully", + "description": "Schema refresh schedule deleted successfully", "content": { "application/json": { "schema": { "type": "object", "properties": { - "message": { - "type": "string", - "description": "Success message", - "example": "dbt repository unlinked successfully" - }, "success": { "type": "boolean", "description": "Whether the operation succeeded", @@ -9797,11 +33492,10 @@ } }, "required": [ - "message", "success" ], - "description": "dbt delete response", - "title": "ConnectionsDbtDeleteResponse" + "description": "Delete schedule response", + "title": "ConnectionsSchedulesDeleteResponse" } } } @@ -9813,96 +33507,78 @@ "description": "Permission denied - connection admin role required" }, "404": { - "description": "Connection not found or dbt not configured" + "description": "Connection or schedule not found" } } } }, - "/api/v1/connections/{connectionId}/dbt/environments": { + "/api/v1/connection-environments": { "get": { - "description": "List all dbt environments for a connection.", - "operationId": "connectionsDbtEnvironmentsList", - "summary": "List dbt environments", + "operationId": "connectionEnvironmentsList", + "summary": "List connection environments", "tags": [ "Connections" ], - "parameters": [ - { - "schema": { - "type": "string", - "format": "uuid", - "description": "Connection ID", - "example": "550e8400-e29b-41d4-a716-446655440000" - }, - "required": true, - "description": "Connection ID", - "name": "connectionId", - "in": "path" - }, - { - "schema": { - "type": "string", - "description": "Cursor for pagination (from previous response nextCursor)", - "example": "eyJpZCI6IjEyMzQ1In0" - }, - "required": false, - "description": "Cursor for pagination (from previous response nextCursor)", - "name": "cursor", - "in": "query" - }, - { - "schema": { - "type": "number", - "minimum": 1, - "maximum": 100, - "default": 20, - "description": "Number of results per page (1-100)", - "example": 20 - }, - "required": false, - "description": "Number of results per page (1-100)", - "name": "pageSize", - "in": "query" - }, - { - "schema": { - "type": "string", - "enum": [ - "asc", - "desc" - ], - "default": "desc", - "description": "Sort direction for results", - "example": "desc" - }, - "required": false, - "description": "Sort direction for results", - "name": "sortDirection", - "in": "query" - }, - { - "schema": { - "type": "string", - "enum": [ - "name" - ], - "default": "name", - "description": "Field to sort results by", - "example": "name" - }, - "required": false, - "description": "Field to sort results by", - "name": "sortField", - "in": "query" - } - ], "responses": { "200": { - "description": "List of dbt environments", + "description": "List of connection environments", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/DbtEnvironmentListResponse" + "type": "object", + "properties": { + "connectionEnvironments": { + "type": "array", + "items": { + "type": "object", + "properties": { + "baseConnectionId": { + "type": "string", + "format": "uuid", + "description": "ID of the base connection", + "example": "550e8400-e29b-41d4-a716-446655440000" + }, + "connectionId": { + "type": "string", + "format": "uuid", + "description": "ID of the environment connection", + "example": "550e8400-e29b-41d4-a716-446655440002" + }, + "id": { + "type": "string", + "format": "uuid", + "description": "Unique connection environment identifier", + "example": "550e8400-e29b-41d4-a716-446655440001" + }, + "userAttributeValues": { + "type": "array", + "items": { + "type": "string" + }, + "description": "User attribute values for this environment", + "example": [ + "us-east", + "production" + ] + } + }, + "required": [ + "baseConnectionId", + "connectionId", + "id", + "userAttributeValues" + ], + "description": "Connection environment object", + "title": "ConnectionEnvironment" + }, + "description": "List of connection environments" + } + }, + "required": [ + "connectionEnvironments" + ], + "description": "List connection environments response", + "title": "ConnectionsEnvironmentsListResponse" } } } @@ -9911,83 +33587,134 @@ "description": "Authentication required" }, "403": { - "description": "Permission denied or connection does not support dbt" - }, - "404": { - "description": "Connection not found" + "description": "Permission denied - admin role required" } } }, "post": { - "description": "Create a new dbt environment for a connection.", - "operationId": "connectionsDbtEnvironmentsCreate", - "summary": "Create dbt environment", + "operationId": "connectionEnvironmentsCreate", + "summary": "Create connection environments", "tags": [ "Connections" ], - "parameters": [ - { - "schema": { - "type": "string", - "format": "uuid", - "description": "Connection ID", - "example": "550e8400-e29b-41d4-a716-446655440000" - }, - "required": true, - "description": "Connection ID", - "name": "connectionId", - "in": "path" - } - ], "requestBody": { - "required": true, "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/DbtEnvironmentCreateBody" + "type": "object", + "properties": { + "baseConnectionId": { + "type": "string", + "format": "uuid", + "description": "ID of the base connection", + "example": "550e8400-e29b-41d4-a716-446655440000" + }, + "environmentConnectionIds": { + "type": "array", + "items": { + "type": "string", + "format": "uuid" + }, + "description": "IDs of connections to use as environments", + "example": [ + "550e8400-e29b-41d4-a716-446655440002", + "550e8400-e29b-41d4-a716-446655440003" + ] + } + }, + "required": [ + "baseConnectionId", + "environmentConnectionIds" + ], + "description": "Request body for creating connection environments", + "title": "ConnectionsEnvironmentsCreateBody" } } } }, "responses": { "201": { - "description": "dbt environment created successfully", + "description": "Connection environments created successfully", "content": { "application/json": { "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/DbtEnvironmentItem" - }, - { - "description": "Created dbt environment", - "title": "DbtEnvironmentCreateResponse" + "type": "object", + "properties": { + "connectionEnvironments": { + "type": "array", + "items": { + "type": "object", + "properties": { + "baseConnectionId": { + "type": "string", + "format": "uuid", + "description": "ID of the base connection", + "example": "550e8400-e29b-41d4-a716-446655440000" + }, + "connectionId": { + "type": "string", + "format": "uuid", + "description": "ID of the environment connection", + "example": "550e8400-e29b-41d4-a716-446655440002" + }, + "id": { + "type": "string", + "format": "uuid", + "description": "Unique connection environment identifier", + "example": "550e8400-e29b-41d4-a716-446655440001" + }, + "userAttributeValues": { + "type": "array", + "items": { + "type": "string" + }, + "description": "User attribute values for this environment", + "example": [ + "us-east", + "production" + ] + } + }, + "required": [ + "baseConnectionId", + "connectionId", + "id", + "userAttributeValues" + ], + "description": "Connection environment object", + "title": "ConnectionEnvironment" + }, + "description": "Created connection environments" } - ] + }, + "required": [ + "connectionEnvironments" + ], + "description": "Create connection environments response", + "title": "ConnectionsEnvironmentsCreateResponse" } } } }, "400": { - "description": "Invalid request body" + "description": "Invalid request body or connection IDs" }, "401": { "description": "Authentication required" }, "403": { - "description": "Permission denied or connection does not support dbt" + "description": "Permission denied - admin role required" }, "404": { - "description": "Connection not found" + "description": "Base connection or environment connection not found" } } } }, - "/api/v1/connections/{connectionId}/dbt/environments/{environmentId}": { + "/api/v1/connection-environments/{id}": { "put": { - "description": "Update an existing dbt environment for a connection.", - "operationId": "connectionsDbtEnvironmentsUpdate", - "summary": "Update dbt environment", + "operationId": "connectionEnvironmentsUpdate", + "summary": "Update connection environment", "tags": [ "Connections" ], @@ -9996,52 +33723,61 @@ "schema": { "type": "string", "format": "uuid", - "description": "Connection ID", - "example": "550e8400-e29b-41d4-a716-446655440000" - }, - "required": true, - "description": "Connection ID", - "name": "connectionId", - "in": "path" - }, - { - "schema": { - "type": "string", - "format": "uuid", - "description": "Environment ID", - "example": "247dc6dc-2a58-4688-9521-c5ed3e99c1e8" + "description": "Connection environment ID", + "example": "550e8400-e29b-41d4-a716-446655440001" }, "required": true, - "description": "Environment ID", - "name": "environmentId", + "description": "Connection environment ID", + "name": "id", "in": "path" } ], "requestBody": { - "required": true, "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/DbtEnvironmentUpdateBody" + "type": "object", + "properties": { + "userAttributeValues": { + "type": "array", + "items": { + "type": "string" + }, + "description": "User attribute values for this environment", + "example": [ + "us-east", + "production" + ] + } + }, + "required": [ + "userAttributeValues" + ], + "description": "Request body for updating a connection environment", + "title": "ConnectionsEnvironmentsUpdateBody" } } } }, "responses": { "200": { - "description": "dbt environment updated successfully", + "description": "Connection environment updated successfully", "content": { "application/json": { "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/DbtEnvironmentItem" - }, - { - "description": "Updated dbt environment", - "title": "DbtEnvironmentUpdateResponse" + "type": "object", + "properties": { + "success": { + "type": "boolean", + "description": "Whether the operation succeeded", + "example": true } - ] + }, + "required": [ + "success" + ], + "description": "Update connection environment response", + "title": "ConnectionsEnvironmentsUpdateResponse" } } } @@ -10053,53 +33789,52 @@ "description": "Authentication required" }, "403": { - "description": "Permission denied or connection does not support dbt" + "description": "Permission denied - admin role required" }, "404": { - "description": "Connection or environment not found" + "description": "Connection environment not found" } - } - }, - "delete": { - "description": "Delete a dbt environment from a connection.", - "operationId": "connectionsDbtEnvironmentsDelete", - "summary": "Delete dbt environment", - "tags": [ - "Connections" - ], - "parameters": [ - { - "schema": { - "type": "string", - "format": "uuid", - "description": "Connection ID", - "example": "550e8400-e29b-41d4-a716-446655440000" - }, - "required": true, - "description": "Connection ID", - "name": "connectionId", - "in": "path" - }, + } + }, + "delete": { + "operationId": "connectionEnvironmentsDelete", + "summary": "Delete connection environment", + "tags": [ + "Connections" + ], + "parameters": [ { "schema": { "type": "string", "format": "uuid", - "description": "Environment ID", - "example": "247dc6dc-2a58-4688-9521-c5ed3e99c1e8" + "description": "Connection environment ID", + "example": "550e8400-e29b-41d4-a716-446655440001" }, "required": true, - "description": "Environment ID", - "name": "environmentId", + "description": "Connection environment ID", + "name": "id", "in": "path" } ], "responses": { "200": { - "description": "dbt environment deleted successfully", + "description": "Connection environment deleted successfully", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/DbtEnvironmentDeleteResponse" + "type": "object", + "properties": { + "success": { + "type": "boolean", + "description": "Whether the operation succeeded", + "example": true + } + }, + "required": [ + "success" + ], + "description": "Delete connection environment response", + "title": "ConnectionsEnvironmentsDeleteResponse" } } } @@ -10108,361 +33843,388 @@ "description": "Authentication required" }, "403": { - "description": "Permission denied or connection does not support dbt" + "description": "Permission denied - admin role required" }, "404": { - "description": "Connection or environment not found" + "description": "Connection environment not found" } } } }, - "/api/v1/connections/{connectionId}/schedules": { + "/api/v1/content": { "get": { - "operationId": "connectionsSchedulesList", - "summary": "List schema refresh schedules", + "operationId": "contentList", + "summary": "List content", "tags": [ - "Connections" + "Content" ], "parameters": [ + { + "schema": { + "type": "string", + "description": "Cursor for pagination (from previous response nextCursor)", + "example": "eyJpZCI6IjEyMzQ1In0" + }, + "required": false, + "description": "Cursor for pagination (from previous response nextCursor)", + "name": "cursor", + "in": "query" + }, + { + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 100, + "default": 20, + "description": "Number of results per page (1-100, integer)", + "example": 20 + }, + "required": false, + "description": "Number of results per page (1-100, integer)", + "name": "pageSize", + "in": "query" + }, { "schema": { "type": "string", "format": "uuid", - "description": "Connection ID", - "example": "550e8400-e29b-41d4-a716-446655440000" + "description": "Filter by creator user ID" }, - "required": true, - "description": "Connection ID", - "name": "connectionId", - "in": "path" + "required": false, + "description": "Filter by creator user ID", + "name": "creatorId", + "in": "query" + }, + { + "schema": { + "type": "string", + "format": "uuid", + "description": "Filter by folder ID (cannot be used with path)" + }, + "required": false, + "description": "Filter by folder ID (cannot be used with path)", + "name": "folderId", + "in": "query" + }, + { + "schema": { + "type": "string", + "description": "Comma-separated list of fields to include (e.g., _count,labels)" + }, + "required": false, + "description": "Comma-separated list of fields to include (e.g., _count,labels)", + "name": "include", + "in": "query" + }, + { + "schema": { + "type": "string", + "description": "Filter by folder path (cannot be used with folderId)", + "example": "/reports/sales" + }, + "required": false, + "description": "Filter by folder path (cannot be used with folderId)", + "name": "path", + "in": "query" + }, + { + "schema": { + "type": "string", + "enum": [ + "organization", + "restricted" + ], + "description": "Filter by share scope", + "example": "organization" + }, + "required": false, + "description": "Filter by share scope", + "name": "scope", + "in": "query" + }, + { + "schema": { + "type": "string", + "enum": [ + "asc", + "desc" + ], + "description": "Sort direction", + "example": "asc" + }, + "required": false, + "description": "Sort direction", + "name": "sortDirection", + "in": "query" + }, + { + "schema": { + "type": "string", + "enum": [ + "name", + "favorites" + ], + "description": "Field to sort by", + "example": "name" + }, + "required": false, + "description": "Field to sort by", + "name": "sortField", + "in": "query" } ], "responses": { "200": { - "description": "List of schema refresh schedules", + "description": "List of content (documents and folders)", "content": { "application/json": { "schema": { - "type": "object", - "properties": { - "schedules": { - "type": "array", - "items": { - "type": "object", - "properties": { - "connectionId": { - "type": "string", - "format": "uuid", - "description": "Connection ID this schedule belongs to", - "example": "550e8400-e29b-41d4-a716-446655440000" - }, - "createdAt": { - "type": "string", - "description": "Schedule creation timestamp (ISO 8601)", - "example": "2024-01-15T10:30:00Z" - }, - "description": { - "type": "string", - "description": "Human-readable schedule description", - "example": "Runs daily at 2:00 AM EST" - }, - "disabledAt": { - "type": [ - "string", - "null" - ], - "description": "Timestamp when schedule was disabled (ISO 8601)", - "example": null - }, - "schedule": { - "type": "string", - "description": "AWS EventBridge cron expression (6 fields: minute hour day-of-month month day-of-week year). See https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-cron-expressions.html", - "example": "0 2 * * ? *" - }, - "scheduleId": { - "type": "string", - "format": "uuid", - "description": "Unique schedule identifier", - "example": "550e8400-e29b-41d4-a716-446655440001" - }, - "timezone": { - "type": "string", - "description": "IANA timezone for schedule execution", - "example": "America/New_York" - }, - "updatedAt": { - "type": "string", - "description": "Schedule last update timestamp (ISO 8601)", - "example": "2024-01-15T10:30:00Z" - } - }, - "required": [ - "connectionId", - "createdAt", - "description", - "disabledAt", - "schedule", - "scheduleId", - "timezone", - "updatedAt" - ], - "description": "Schema refresh schedule object", - "title": "ConnectionSchedule" - }, - "description": "List of schema refresh schedules" - } - }, - "required": [ - "schedules" - ], - "description": "List schedules response", - "title": "ConnectionsSchedulesListResponse" + "$ref": "#/components/schemas/ContentListResponse" } } } }, + "400": { + "description": "Invalid query parameters (cannot use both folderId and path)" + }, "401": { "description": "Authentication required" }, - "403": { - "description": "Permission denied - connection admin role required" - }, "404": { - "description": "Connection not found" + "description": "Folder not found (when filtering by path)" } } - }, + } + }, + "/api/v1/dashboards/{identifier}/download": { "post": { - "operationId": "connectionsSchedulesCreate", - "summary": "Create schema refresh schedule", + "operationId": "dashboardsDownload", + "summary": "Initiate dashboard download", "tags": [ - "Connections" + "Dashboards" ], "parameters": [ + { + "schema": { + "type": "string", + "description": "Dashboard identifier (short ID or UUID)", + "example": "12db1a0a" + }, + "required": true, + "description": "Dashboard identifier (short ID or UUID)", + "name": "identifier", + "in": "path" + }, { "schema": { "type": "string", "format": "uuid", - "description": "Connection ID", - "example": "550e8400-e29b-41d4-a716-446655440000" + "description": "Target user membership ID (for org-scoped API keys)" }, - "required": true, - "description": "Connection ID", - "name": "connectionId", - "in": "path" + "required": false, + "description": "Target user membership ID (for org-scoped API keys)", + "name": "userId", + "in": "query" } ], "requestBody": { "content": { "application/json": { "schema": { - "type": "object", - "properties": { - "schedule": { - "type": "string", - "description": "AWS EventBridge cron expression (6 fields: minute hour day-of-month month day-of-week year). See https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-cron-expressions.html", - "example": "0 2 * * ? *" - }, - "timezone": { - "type": "string", - "description": "IANA timezone for schedule execution", - "example": "America/New_York" - } - }, - "required": [ - "schedule", - "timezone" - ], - "description": "Request body for creating a schema refresh schedule", - "title": "ConnectionsSchedulesCreateBody" + "$ref": "#/components/schemas/DashboardsDownloadBody" } } } }, "responses": { - "201": { - "description": "Schema refresh schedule created successfully", + "200": { + "description": "Download job initiated successfully", "content": { "application/json": { "schema": { - "type": "object", - "properties": { - "connectionId": { - "type": "string", - "format": "uuid", - "description": "Connection ID this schedule belongs to", - "example": "550e8400-e29b-41d4-a716-446655440000" - }, - "createdAt": { - "type": "string", - "description": "Schedule creation timestamp (ISO 8601)", - "example": "2024-01-15T10:30:00Z" - }, - "description": { - "type": "string", - "description": "Human-readable schedule description", - "example": "Runs daily at 2:00 AM EST" - }, - "disabledAt": { - "type": [ - "string", - "null" - ], - "description": "Timestamp when schedule was disabled (ISO 8601)", - "example": null - }, - "schedule": { - "type": "string", - "description": "AWS EventBridge cron expression (6 fields: minute hour day-of-month month day-of-week year). See https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-cron-expressions.html", - "example": "0 2 * * ? *" - }, - "scheduleId": { - "type": "string", - "format": "uuid", - "description": "Unique schedule identifier", - "example": "550e8400-e29b-41d4-a716-446655440001" - }, - "timezone": { - "type": "string", - "description": "IANA timezone for schedule execution", - "example": "America/New_York" - }, - "updatedAt": { - "type": "string", - "description": "Schedule last update timestamp (ISO 8601)", - "example": "2024-01-15T10:30:00Z" - } - }, - "required": [ - "connectionId", - "createdAt", - "description", - "disabledAt", - "schedule", - "scheduleId", - "timezone", - "updatedAt" - ], - "description": "Created schedule response", - "title": "ConnectionsSchedulesCreateResponse" + "$ref": "#/components/schemas/DashboardsDownloadResponse" } } } }, "400": { - "description": "Invalid cron expression or timezone" + "description": "Invalid request body or filter configuration" }, "401": { "description": "Authentication required" }, "403": { - "description": "Permission denied - connection admin role required" + "description": "Permission denied - cannot download this dashboard" }, "404": { - "description": "Connection not found" + "description": "Dashboard not found" + }, + "409": { + "description": "Download already in progress for this dashboard" + }, + "500": { + "description": "Failed to initiate download" } } } }, - "/api/v1/connections/{connectionId}/schedules/{scheduleId}": { + "/api/v1/dashboards/{identifier}/download/{jobId}": { "get": { - "operationId": "connectionsSchedulesGet", - "summary": "Get schema refresh schedule", + "operationId": "dashboardsDownloadFile", + "summary": "Get download file", "tags": [ - "Connections" + "Dashboards" ], "parameters": [ + { + "schema": { + "type": "string", + "description": "Dashboard identifier (short ID or UUID)", + "example": "12db1a0a" + }, + "required": true, + "description": "Dashboard identifier (short ID or UUID)", + "name": "identifier", + "in": "path" + }, + { + "schema": { + "type": "string", + "description": "Download job ID (UUID)", + "example": "123e4567-e89b-12d3-a456-426614174000" + }, + "required": true, + "description": "Download job ID (UUID)", + "name": "jobId", + "in": "path" + }, { "schema": { "type": "string", "format": "uuid", - "description": "Connection ID", - "example": "550e8400-e29b-41d4-a716-446655440000" + "description": "Target user membership ID (for org-scoped API keys)" + }, + "required": false, + "description": "Target user membership ID (for org-scoped API keys)", + "name": "userId", + "in": "query" + } + ], + "responses": { + "200": { + "description": "File ready - binary content streamed" + }, + "202": { + "description": "Download job still in progress" + }, + "401": { + "description": "Authentication required" + }, + "404": { + "description": "Dashboard or download job not found" + }, + "410": { + "description": "Download job failed" + }, + "500": { + "description": "Failed to retrieve download artifact" + } + } + } + }, + "/api/v1/dashboards/{identifier}/download/{jobId}/status": { + "get": { + "operationId": "dashboardsDownloadStatus", + "summary": "Get download job status", + "tags": [ + "Dashboards" + ], + "parameters": [ + { + "schema": { + "type": "string", + "description": "Dashboard identifier (short ID or UUID)", + "example": "12db1a0a" }, "required": true, - "description": "Connection ID", - "name": "connectionId", + "description": "Dashboard identifier (short ID or UUID)", + "name": "identifier", + "in": "path" + }, + { + "schema": { + "type": "string", + "description": "Download job ID (UUID)", + "example": "123e4567-e89b-12d3-a456-426614174000" + }, + "required": true, + "description": "Download job ID (UUID)", + "name": "jobId", "in": "path" }, { "schema": { "type": "string", "format": "uuid", - "description": "Schedule ID", - "example": "550e8400-e29b-41d4-a716-446655440001" + "description": "Target user membership ID (for org-scoped API keys)" + }, + "required": false, + "description": "Target user membership ID (for org-scoped API keys)", + "name": "userId", + "in": "query" + } + ], + "responses": { + "200": { + "description": "Download job status" + }, + "401": { + "description": "Authentication required" + }, + "404": { + "description": "Dashboard or download job not found" + } + } + } + }, + "/api/v1/dashboards/{identifier}/filters": { + "get": { + "operationId": "dashboardsGetFilters", + "summary": "Get dashboard filters", + "tags": [ + "Dashboards" + ], + "parameters": [ + { + "schema": { + "type": "string", + "description": "Dashboard identifier (short ID or UUID)", + "example": "12db1a0a" }, "required": true, - "description": "Schedule ID", - "name": "scheduleId", + "description": "Dashboard identifier (short ID or UUID)", + "name": "identifier", "in": "path" + }, + { + "schema": { + "type": "string", + "format": "uuid", + "description": "Target user membership ID (for org-scoped API keys)" + }, + "required": false, + "description": "Target user membership ID (for org-scoped API keys)", + "name": "userId", + "in": "query" } ], "responses": { "200": { - "description": "Schema refresh schedule details", + "description": "Dashboard filter and control configuration", "content": { "application/json": { "schema": { - "type": "object", - "properties": { - "connectionId": { - "type": "string", - "format": "uuid", - "description": "Connection ID this schedule belongs to", - "example": "550e8400-e29b-41d4-a716-446655440000" - }, - "createdAt": { - "type": "string", - "description": "Schedule creation timestamp (ISO 8601)", - "example": "2024-01-15T10:30:00Z" - }, - "description": { - "type": "string", - "description": "Human-readable schedule description", - "example": "Runs daily at 2:00 AM EST" - }, - "disabledAt": { - "type": [ - "string", - "null" - ], - "description": "Timestamp when schedule was disabled (ISO 8601)", - "example": null - }, - "schedule": { - "type": "string", - "description": "AWS EventBridge cron expression (6 fields: minute hour day-of-month month day-of-week year). See https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-cron-expressions.html", - "example": "0 2 * * ? *" - }, - "scheduleId": { - "type": "string", - "format": "uuid", - "description": "Unique schedule identifier", - "example": "550e8400-e29b-41d4-a716-446655440001" - }, - "timezone": { - "type": "string", - "description": "IANA timezone for schedule execution", - "example": "America/New_York" - }, - "updatedAt": { - "type": "string", - "description": "Schedule last update timestamp (ISO 8601)", - "example": "2024-01-15T10:30:00Z" - } - }, - "required": [ - "connectionId", - "createdAt", - "description", - "disabledAt", - "schedule", - "scheduleId", - "timezone", - "updatedAt" - ], - "description": "Get schedule response", - "title": "ConnectionsSchedulesGetResponse" + "$ref": "#/components/schemas/DashboardFiltersResponse" } } } @@ -10471,440 +34233,378 @@ "description": "Authentication required" }, "403": { - "description": "Permission denied - connection admin role required" + "description": "Permission denied - VIEWER role required" }, "404": { - "description": "Connection or schedule not found" + "description": "Dashboard not found" } } }, - "put": { - "operationId": "connectionsSchedulesUpdate", - "summary": "Update schema refresh schedule", + "patch": { + "operationId": "dashboardsUpdateFilters", + "summary": "Update dashboard filters", "tags": [ - "Connections" + "Dashboards" ], "parameters": [ { "schema": { "type": "string", - "format": "uuid", - "description": "Connection ID", - "example": "550e8400-e29b-41d4-a716-446655440000" + "description": "Dashboard identifier (short ID or UUID)", + "example": "12db1a0a" }, "required": true, - "description": "Connection ID", - "name": "connectionId", + "description": "Dashboard identifier (short ID or UUID)", + "name": "identifier", "in": "path" }, { "schema": { "type": "string", "format": "uuid", - "description": "Schedule ID", - "example": "550e8400-e29b-41d4-a716-446655440001" + "description": "Target user membership ID (for org-scoped API keys)" }, - "required": true, - "description": "Schedule ID", - "name": "scheduleId", - "in": "path" + "required": false, + "description": "Target user membership ID (for org-scoped API keys)", + "name": "userId", + "in": "query" } ], "requestBody": { "content": { "application/json": { "schema": { - "type": "object", - "properties": { - "schedule": { - "type": "string", - "description": "AWS EventBridge cron expression (6 fields: minute hour day-of-month month day-of-week year). See https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-cron-expressions.html", - "example": "0 2 * * ? *" - }, - "timezone": { - "type": "string", - "description": "IANA timezone for schedule execution", - "example": "America/New_York" - } - }, - "required": [ - "schedule", - "timezone" - ], - "description": "Request body for updating a schema refresh schedule", - "title": "ConnectionsSchedulesUpdateBody" + "$ref": "#/components/schemas/DashboardsUpdateFiltersBody" } } } }, "responses": { "200": { - "description": "Schema refresh schedule updated successfully", + "description": "Filters updated successfully", "content": { "application/json": { "schema": { - "type": "object", - "properties": { - "connectionId": { - "type": "string", - "format": "uuid", - "description": "Connection ID this schedule belongs to", - "example": "550e8400-e29b-41d4-a716-446655440000" - }, - "createdAt": { - "type": "string", - "description": "Schedule creation timestamp (ISO 8601)", - "example": "2024-01-15T10:30:00Z" - }, - "description": { - "type": "string", - "description": "Human-readable schedule description", - "example": "Runs daily at 2:00 AM EST" - }, - "disabledAt": { - "type": [ - "string", - "null" - ], - "description": "Timestamp when schedule was disabled (ISO 8601)", - "example": null - }, - "schedule": { - "type": "string", - "description": "AWS EventBridge cron expression (6 fields: minute hour day-of-month month day-of-week year). See https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-cron-expressions.html", - "example": "0 2 * * ? *" - }, - "scheduleId": { - "type": "string", - "format": "uuid", - "description": "Unique schedule identifier", - "example": "550e8400-e29b-41d4-a716-446655440001" - }, - "timezone": { - "type": "string", - "description": "IANA timezone for schedule execution", - "example": "America/New_York" - }, - "updatedAt": { - "type": "string", - "description": "Schedule last update timestamp (ISO 8601)", - "example": "2024-01-15T10:30:00Z" - } - }, - "required": [ - "connectionId", - "createdAt", - "description", - "disabledAt", - "schedule", - "scheduleId", - "timezone", - "updatedAt" - ], - "description": "Updated schedule response", - "title": "ConnectionsSchedulesUpdateResponse" + "$ref": "#/components/schemas/DashboardFiltersResponse" } } } }, "400": { - "description": "Invalid cron expression or timezone" + "description": "Invalid request body - must include at least one filter, control, or filterOrder" }, "401": { "description": "Authentication required" }, - "403": { - "description": "Permission denied - connection admin role required" + "403": { + "description": "Permission denied - EDITOR role required" + }, + "404": { + "description": "Dashboard not found or document does not have a dashboard" + }, + "409": { + "description": "Conflict - draft already exists. Set clearExistingDraft to true to proceed." + } + } + } + }, + "/api/v1/documents": { + "get": { + "operationId": "documentsList", + "summary": "List documents", + "tags": [ + "Documents" + ], + "parameters": [ + { + "schema": { + "type": "string", + "format": "uuid", + "description": "Filter by creator membership ID" + }, + "required": false, + "description": "Filter by creator membership ID", + "name": "creatorId", + "in": "query" + }, + { + "schema": { + "type": "string", + "description": "Cursor for pagination" + }, + "required": false, + "description": "Cursor for pagination", + "name": "cursor", + "in": "query" + }, + { + "schema": { + "type": "string", + "format": "uuid", + "description": "Filter by folder ID" + }, + "required": false, + "description": "Filter by folder ID", + "name": "folderId", + "in": "query" + }, + { + "schema": { + "type": "string", + "description": "Comma-separated list of additional fields to include: _count, labels, includeDeleted, onlyFavorites, onlySharedWithMe. onlySharedWithMe requires userId or user-scoped key and cannot be combined with onlyFavorites or folderId.", + "example": "_count,labels" + }, + "required": false, + "description": "Comma-separated list of additional fields to include: _count, labels, includeDeleted, onlyFavorites, onlySharedWithMe. onlySharedWithMe requires userId or user-scoped key and cannot be combined with onlyFavorites or folderId.", + "name": "include", + "in": "query" + }, + { + "schema": { + "type": "string", + "description": "Comma-separated list of label names to filter by", + "example": "verified,important" + }, + "required": false, + "description": "Comma-separated list of label names to filter by", + "name": "labels", + "in": "query" + }, + { + "schema": { + "type": "integer", + "exclusiveMinimum": 0, + "default": 50, + "description": "Number of records per page" + }, + "required": false, + "description": "Number of records per page", + "name": "pageSize", + "in": "query" + }, + { + "schema": { + "type": "string", + "enum": [ + "asc", + "desc" + ], + "default": "asc", + "description": "Sort direction" + }, + "required": false, + "description": "Sort direction", + "name": "sortDirection", + "in": "query" }, - "404": { - "description": "Connection or schedule not found" - } - } - }, - "delete": { - "operationId": "connectionsSchedulesDelete", - "summary": "Delete schema refresh schedule", - "tags": [ - "Connections" - ], - "parameters": [ { "schema": { "type": "string", - "format": "uuid", - "description": "Connection ID", - "example": "550e8400-e29b-41d4-a716-446655440000" + "enum": [ + "name", + "favorites", + "updatedAt", + "visits" + ], + "default": "name", + "description": "Field to sort by" }, - "required": true, - "description": "Connection ID", - "name": "connectionId", - "in": "path" + "required": false, + "description": "Field to sort by", + "name": "sortField", + "in": "query" }, { "schema": { "type": "string", "format": "uuid", - "description": "Schedule ID", - "example": "550e8400-e29b-41d4-a716-446655440001" + "description": "Filter documents visible to this membership ID" }, - "required": true, - "description": "Schedule ID", - "name": "scheduleId", - "in": "path" + "required": false, + "description": "Filter documents visible to this membership ID", + "name": "userId", + "in": "query" } ], "responses": { "200": { - "description": "Schema refresh schedule deleted successfully", + "description": "Paginated list of documents", "content": { "application/json": { "schema": { - "type": "object", - "properties": { - "success": { - "type": "boolean", - "description": "Whether the operation succeeded", - "example": true - } - }, - "required": [ - "success" - ], - "description": "Delete schedule response", - "title": "ConnectionsSchedulesDeleteResponse" + "$ref": "#/components/schemas/DocumentsListResponse" + } + } + } + }, + "401": { + "description": "Authentication required" + } + } + }, + "post": { + "operationId": "documentsCreate", + "summary": "Create document", + "tags": [ + "Documents" + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DocumentsCreateBody" + } + } + } + }, + "responses": { + "201": { + "description": "Document created successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DocumentsCreateResponse" } } } }, + "400": { + "description": "Invalid request body" + }, "401": { "description": "Authentication required" }, "403": { - "description": "Permission denied - connection admin role required" + "description": "Permission denied" }, "404": { - "description": "Connection or schedule not found" + "description": "Model or branch not found" } } } }, - "/api/v1/connection-environments": { + "/api/v1/documents/{identifier}": { "get": { - "operationId": "connectionEnvironmentsList", - "summary": "List connection environments", + "description": "Retrieves a document's configuration in a format compatible with PUT for round-trip editing. GET a document, modify the response, and PUT it back to update. Only dashboard documents are supported; analysis documents return 400.", + "operationId": "documentsGet", + "summary": "Get document", "tags": [ - "Connections" + "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" + } ], "responses": { "200": { - "description": "List of connection environments", + "description": "Document details", "content": { "application/json": { "schema": { - "type": "object", - "properties": { - "connectionEnvironments": { - "type": "array", - "items": { - "type": "object", - "properties": { - "baseConnectionId": { - "type": "string", - "format": "uuid", - "description": "ID of the base connection", - "example": "550e8400-e29b-41d4-a716-446655440000" - }, - "connectionId": { - "type": "string", - "format": "uuid", - "description": "ID of the environment connection", - "example": "550e8400-e29b-41d4-a716-446655440002" - }, - "id": { - "type": "string", - "format": "uuid", - "description": "Unique connection environment identifier", - "example": "550e8400-e29b-41d4-a716-446655440001" - }, - "userAttributeValues": { - "type": "array", - "items": { - "type": "string" - }, - "description": "User attribute values for this environment", - "example": [ - "us-east", - "production" - ] - } - }, - "required": [ - "baseConnectionId", - "connectionId", - "id", - "userAttributeValues" - ], - "description": "Connection environment object", - "title": "ConnectionEnvironment" - }, - "description": "List of connection environments" - } - }, - "required": [ - "connectionEnvironments" - ], - "description": "List connection environments response", - "title": "ConnectionsEnvironmentsListResponse" + "$ref": "#/components/schemas/DocumentsGetResponse" } } } }, + "400": { + "description": "Analysis documents are not supported" + }, "401": { "description": "Authentication required" }, "403": { - "description": "Permission denied - admin role required" + "description": "Insufficient permissions to view the document" + }, + "404": { + "description": "Document not found" } } }, - "post": { - "operationId": "connectionEnvironmentsCreate", - "summary": "Create connection environments", + "put": { + "deprecated": true, + "description": "**Deprecated** — use `PATCH /api/v2/documents/{identifier}/draft` (and the related `/draft` routes). Removal scheduled per the `Sunset` response header.\n\nUpdates a document with the specified identifier. This endpoint performs a full resource replacement — all required fields must be provided and existing query presentations are replaced entirely. Only dashboard documents are supported; analysis documents and documents without an associated dashboard return 400. For published documents, the update goes through a draft/publish workflow automatically; if a draft already exists, the request returns 409 unless `clearExistingDraft` is set to `true`.", + "operationId": "documentsPut", + "summary": "Replace document (full replacement)", "tags": [ - "Connections" + "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": { - "type": "object", - "properties": { - "baseConnectionId": { - "type": "string", - "format": "uuid", - "description": "ID of the base connection", - "example": "550e8400-e29b-41d4-a716-446655440000" - }, - "environmentConnectionIds": { - "type": "array", - "items": { - "type": "string", - "format": "uuid" - }, - "description": "IDs of connections to use as environments", - "example": [ - "550e8400-e29b-41d4-a716-446655440002", - "550e8400-e29b-41d4-a716-446655440003" - ] - } - }, - "required": [ - "baseConnectionId", - "environmentConnectionIds" - ], - "description": "Request body for creating connection environments", - "title": "ConnectionsEnvironmentsCreateBody" + "$ref": "#/components/schemas/DocumentsPutBody" } } } }, "responses": { - "201": { - "description": "Connection environments created successfully", + "200": { + "description": "Document replaced successfully", "content": { "application/json": { "schema": { - "type": "object", - "properties": { - "connectionEnvironments": { - "type": "array", - "items": { - "type": "object", - "properties": { - "baseConnectionId": { - "type": "string", - "format": "uuid", - "description": "ID of the base connection", - "example": "550e8400-e29b-41d4-a716-446655440000" - }, - "connectionId": { - "type": "string", - "format": "uuid", - "description": "ID of the environment connection", - "example": "550e8400-e29b-41d4-a716-446655440002" - }, - "id": { - "type": "string", - "format": "uuid", - "description": "Unique connection environment identifier", - "example": "550e8400-e29b-41d4-a716-446655440001" - }, - "userAttributeValues": { - "type": "array", - "items": { - "type": "string" - }, - "description": "User attribute values for this environment", - "example": [ - "us-east", - "production" - ] - } - }, - "required": [ - "baseConnectionId", - "connectionId", - "id", - "userAttributeValues" - ], - "description": "Connection environment object", - "title": "ConnectionEnvironment" - }, - "description": "Created connection environments" - } - }, - "required": [ - "connectionEnvironments" - ], - "description": "Create connection environments response", - "title": "ConnectionsEnvironmentsCreateResponse" + "$ref": "#/components/schemas/DocumentsPutResponse" } } } }, "400": { - "description": "Invalid request body or connection IDs" + "description": "Invalid request body, missing required fields, or validation error (also returned for analysis documents and documents without an associated dashboard)" }, "401": { "description": "Authentication required" }, "403": { - "description": "Permission denied - admin role required" + "description": "Insufficient permissions to update the document" }, "404": { - "description": "Base connection or environment connection not found" + "description": "Document not found" + }, + "409": { + "description": "Draft already exists - set clearExistingDraft to true to discard it and proceed" } } - } - }, - "/api/v1/connection-environments/{id}": { - "put": { - "operationId": "connectionEnvironmentsUpdate", - "summary": "Update connection environment", + }, + "patch": { + "deprecated": true, + "description": "**Deprecated** — use `PATCH /api/v2/documents/{identifier}/draft` (and the related `/draft` routes). Removal scheduled per the `Sunset` response header.\n\nUpdates a document's name, description, and/or identifier. This is a partial update — only provided fields are modified, and at least one of `name`, `description`, or `identifier` must be supplied. When `identifier` is changed, the previous identifier is retained in the document identifier history and continues to redirect. For published documents, the update goes through a draft/publish workflow automatically.", + "operationId": "documentsUpdate", + "summary": "Rename document", "tags": [ - "Connections" + "Documents" ], "parameters": [ { "schema": { "type": "string", - "format": "uuid", - "description": "Connection environment ID", - "example": "550e8400-e29b-41d4-a716-446655440001" + "description": "Document identifier (either document ID or identifier slug)", + "example": "abc123" }, "required": true, - "description": "Connection environment ID", - "name": "id", + "description": "Document identifier (either document ID or identifier slug)", + "name": "identifier", "in": "path" } ], @@ -10912,105 +34612,65 @@ "content": { "application/json": { "schema": { - "type": "object", - "properties": { - "userAttributeValues": { - "type": "array", - "items": { - "type": "string" - }, - "description": "User attribute values for this environment", - "example": [ - "us-east", - "production" - ] - } - }, - "required": [ - "userAttributeValues" - ], - "description": "Request body for updating a connection environment", - "title": "ConnectionsEnvironmentsUpdateBody" + "$ref": "#/components/schemas/DocumentsUpdateBody" } } } }, "responses": { "200": { - "description": "Connection environment updated successfully", + "description": "Document updated successfully", "content": { "application/json": { "schema": { - "type": "object", - "properties": { - "success": { - "type": "boolean", - "description": "Whether the operation succeeded", - "example": true - } - }, - "required": [ - "success" - ], - "description": "Update connection environment response", - "title": "ConnectionsEnvironmentsUpdateResponse" + "$ref": "#/components/schemas/DocumentsUpdateResponse" } } } }, "400": { - "description": "Invalid request body" + "description": "Invalid request body or validation error (e.g. missing name/description/identifier, name too long, identifier already in use)" }, "401": { "description": "Authentication required" }, "403": { - "description": "Permission denied - admin role required" + "description": "Permission denied - EDITOR role required" }, "404": { - "description": "Connection environment not found" + "description": "Document not found" + }, + "409": { + "description": "Draft already exists - set clearExistingDraft to true to discard it and proceed" } } }, "delete": { - "operationId": "connectionEnvironmentsDelete", - "summary": "Delete connection environment", + "operationId": "documentsDelete", + "summary": "Delete document", "tags": [ - "Connections" + "Documents" ], "parameters": [ { "schema": { "type": "string", - "format": "uuid", - "description": "Connection environment ID", - "example": "550e8400-e29b-41d4-a716-446655440001" + "description": "Document identifier (either document ID or identifier slug)", + "example": "abc123" }, "required": true, - "description": "Connection environment ID", - "name": "id", + "description": "Document identifier (either document ID or identifier slug)", + "name": "identifier", "in": "path" } ], "responses": { "200": { - "description": "Connection environment deleted successfully", + "description": "Document deleted successfully", "content": { "application/json": { "schema": { - "type": "object", - "properties": { - "success": { - "type": "boolean", - "description": "Whether the operation succeeded", - "example": true - } - }, - "required": [ - "success" - ], - "description": "Delete connection environment response", - "title": "ConnectionsEnvironmentsDeleteResponse" + "$ref": "#/components/schemas/SuccessResponse" } } } @@ -11019,628 +34679,594 @@ "description": "Authentication required" }, "403": { - "description": "Permission denied - admin role required" + "description": "Permission denied - MANAGER role required" }, "404": { - "description": "Connection environment not found" + "description": "Document not found" } } } }, - "/api/v1/content": { + "/api/v1/documents/{identifier}/queries": { "get": { - "operationId": "contentList", - "summary": "List content", + "operationId": "documentsGetQueries", + "summary": "List document queries", "tags": [ - "Content" + "Documents" ], "parameters": [ { "schema": { "type": "string", - "description": "Cursor for pagination (from previous response nextCursor)", - "example": "eyJpZCI6IjEyMzQ1In0" - }, - "required": false, - "description": "Cursor for pagination (from previous response nextCursor)", - "name": "cursor", - "in": "query" - }, - { - "schema": { - "type": "number", - "minimum": 1, - "maximum": 100, - "default": 20, - "description": "Number of results per page (1-100)", - "example": 20 - }, - "required": false, - "description": "Number of results per page (1-100)", - "name": "pageSize", - "in": "query" - }, - { - "schema": { - "type": "string", - "format": "uuid", - "description": "Filter by creator user ID" - }, - "required": false, - "description": "Filter by creator user ID", - "name": "creatorId", - "in": "query" - }, - { - "schema": { - "type": "string", - "format": "uuid", - "description": "Filter by folder ID (cannot be used with path)" - }, - "required": false, - "description": "Filter by folder ID (cannot be used with path)", - "name": "folderId", - "in": "query" - }, - { - "schema": { - "type": "string", - "description": "Comma-separated list of fields to include (e.g., _count,labels)" - }, - "required": false, - "description": "Comma-separated list of fields to include (e.g., _count,labels)", - "name": "include", - "in": "query" - }, - { - "schema": { - "type": "string", - "description": "Filter by folder path (cannot be used with folderId)", - "example": "/reports/sales" + "description": "Document identifier (either document ID or identifier slug)", + "example": "abc123" }, - "required": false, - "description": "Filter by folder path (cannot be used with folderId)", - "name": "path", - "in": "query" + "required": true, + "description": "Document identifier (either document ID or identifier slug)", + "name": "identifier", + "in": "path" + } + ], + "responses": { + "200": { + "description": "List of queries in the document", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DocumentsGetQueriesResponse" + } + } + } }, - { - "schema": { - "type": "string", - "enum": [ - "organization", - "restricted" - ], - "description": "Filter by share scope", - "example": "organization" - }, - "required": false, - "description": "Filter by share scope", - "name": "scope", - "in": "query" + "401": { + "description": "Authentication required" }, - { - "schema": { - "type": "string", - "enum": [ - "asc", - "desc" - ], - "description": "Sort direction", - "example": "asc" - }, - "required": false, - "description": "Sort direction", - "name": "sortDirection", - "in": "query" + "403": { + "description": "Permission denied" }, + "404": { + "description": "Document not found" + } + } + } + }, + "/api/v1/documents/{identifier}/move": { + "put": { + "operationId": "documentsMove", + "summary": "Move document", + "tags": [ + "Documents" + ], + "parameters": [ { "schema": { "type": "string", - "enum": [ - "name", - "favorites" - ], - "description": "Field to sort by", - "example": "name" + "description": "Document identifier (either document ID or identifier slug)", + "example": "abc123" }, - "required": false, - "description": "Field to sort by", - "name": "sortField", - "in": "query" + "required": true, + "description": "Document identifier (either document ID or identifier slug)", + "name": "identifier", + "in": "path" } ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DocumentsMoveBody" + } + } + } + }, "responses": { "200": { - "description": "List of content (documents and folders)", + "description": "Document moved successfully", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ContentListResponse" + "$ref": "#/components/schemas/SuccessResponse" } } } }, "400": { - "description": "Invalid query parameters (cannot use both folderId and path)" + "description": "Invalid folder path or scope" }, "401": { "description": "Authentication required" }, + "403": { + "description": "Permission denied - MANAGER role required" + }, "404": { - "description": "Folder not found (when filtering by path)" + "description": "Document or folder not found" } } } }, - "/api/v1/dashboards/{identifier}/download": { - "post": { - "operationId": "dashboardsDownload", - "summary": "Initiate dashboard download", + "/api/v1/documents/{identifier}/permissions": { + "get": { + "operationId": "documentsGetPermissions", + "summary": "Get document permissions", "tags": [ - "Dashboards" + "Documents" ], "parameters": [ { "schema": { "type": "string", - "description": "Dashboard identifier (short ID or UUID)", - "example": "12db1a0a" + "description": "Document identifier (either document ID or identifier slug)", + "example": "abc123" }, "required": true, - "description": "Dashboard identifier (short ID or UUID)", + "description": "Document identifier (either document ID or identifier slug)", "name": "identifier", "in": "path" }, { "schema": { "type": "string", - "description": "Target user membership ID (for org-scoped API keys)" + "format": "uuid", + "description": "User membership ID to check permissions for" }, - "required": false, - "description": "Target user membership ID (for org-scoped API keys)", + "required": true, + "description": "User membership ID to check permissions for", "name": "userId", "in": "query" } ], + "responses": { + "200": { + "description": "User permissions for the document", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DocumentsGetPermissionsResponse" + } + } + } + }, + "401": { + "description": "Authentication required" + }, + "403": { + "description": "Permission denied" + }, + "404": { + "description": "Document or user not found" + } + } + }, + "put": { + "operationId": "documentsUpdatePermissionSettings", + "summary": "Update document permission settings", + "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/DashboardsDownloadBody" + "$ref": "#/components/schemas/DocumentsUpdatePermissionSettingsBody" } } } }, "responses": { "200": { - "description": "Download job initiated successfully", + "description": "Permission settings updated successfully", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/DashboardsDownloadResponse" + "$ref": "#/components/schemas/SuccessResponse" } } } }, "400": { - "description": "Invalid request body or filter configuration" + "description": "Invalid request body" }, "401": { "description": "Authentication required" }, "403": { - "description": "Permission denied - cannot download this dashboard" + "description": "Permission denied - MANAGER role required" }, "404": { - "description": "Dashboard not found" - }, - "409": { - "description": "Download already in progress for this dashboard" - }, - "500": { - "description": "Failed to initiate download" + "description": "Document not found" } } - } - }, - "/api/v1/dashboards/{identifier}/download/{jobId}": { - "get": { - "operationId": "dashboardsDownloadFile", - "summary": "Get download file", + }, + "post": { + "operationId": "documentsAddPermits", + "summary": "Add document permits", "tags": [ - "Dashboards" + "Documents" ], "parameters": [ { "schema": { "type": "string", - "description": "Dashboard identifier (short ID or UUID)", - "example": "12db1a0a" + "description": "Document identifier (either document ID or identifier slug)", + "example": "abc123" }, "required": true, - "description": "Dashboard identifier (short ID or UUID)", + "description": "Document identifier (either document ID or identifier slug)", "name": "identifier", "in": "path" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DocumentsAddPermitsBody" + } + } + } + }, + "responses": { + "200": { + "description": "Permissions added successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SuccessResponse" + } + } + } + }, + "400": { + "description": "Invalid request body - userIds or userGroupIds required" + }, + "401": { + "description": "Authentication required" + }, + "403": { + "description": "Permission denied - MANAGER role required" }, + "404": { + "description": "Document not found" + } + } + }, + "patch": { + "operationId": "documentsUpdatePermits", + "summary": "Update document permits", + "tags": [ + "Documents" + ], + "parameters": [ { "schema": { "type": "string", - "description": "Download job ID (UUID)", - "example": "123e4567-e89b-12d3-a456-426614174000" + "description": "Document identifier (either document ID or identifier slug)", + "example": "abc123" }, "required": true, - "description": "Download job ID (UUID)", - "name": "jobId", + "description": "Document identifier (either document ID or identifier slug)", + "name": "identifier", "in": "path" - }, - { - "schema": { - "type": "string", - "description": "Target user membership ID (for org-scoped API keys)" - }, - "required": false, - "description": "Target user membership ID (for org-scoped API keys)", - "name": "userId", - "in": "query" } ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DocumentsUpdatePermitsBody" + } + } + } + }, "responses": { "200": { - "description": "File ready - binary content streamed" + "description": "Permissions updated successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SuccessResponse" + } + } + } }, - "202": { - "description": "Download job still in progress" + "400": { + "description": "Invalid request body - userIds or userGroupIds required" }, "401": { "description": "Authentication required" }, - "404": { - "description": "Dashboard or download job not found" - }, - "410": { - "description": "Download job failed" + "403": { + "description": "Permission denied - MANAGER role required" }, - "500": { - "description": "Failed to retrieve download artifact" + "404": { + "description": "Document not found" } } - } - }, - "/api/v1/dashboards/{identifier}/download/{jobId}/status": { - "get": { - "operationId": "dashboardsDownloadStatus", - "summary": "Get download job status", + }, + "delete": { + "operationId": "documentsRevokePermits", + "summary": "Revoke document permits", "tags": [ - "Dashboards" + "Documents" ], "parameters": [ { "schema": { "type": "string", - "description": "Dashboard identifier (short ID or UUID)", - "example": "12db1a0a" + "description": "Document identifier (either document ID or identifier slug)", + "example": "abc123" }, "required": true, - "description": "Dashboard identifier (short ID or UUID)", + "description": "Document identifier (either document ID or identifier slug)", "name": "identifier", "in": "path" - }, - { - "schema": { - "type": "string", - "description": "Download job ID (UUID)", - "example": "123e4567-e89b-12d3-a456-426614174000" - }, - "required": true, - "description": "Download job ID (UUID)", - "name": "jobId", - "in": "path" - }, - { - "schema": { - "type": "string", - "description": "Target user membership ID (for org-scoped API keys)" - }, - "required": false, - "description": "Target user membership ID (for org-scoped API keys)", - "name": "userId", - "in": "query" } ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DocumentsRevokePermitsBody" + } + } + } + }, "responses": { "200": { - "description": "Download job status" + "description": "Permissions revoked successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SuccessResponse" + } + } + } + }, + "400": { + "description": "Invalid request body - userIds or userGroupIds required" }, "401": { "description": "Authentication required" }, + "403": { + "description": "Permission denied - MANAGER role required" + }, "404": { - "description": "Dashboard or download job not found" + "description": "Document not found" } } } }, - "/api/v1/dashboards/{identifier}/filters": { - "get": { - "operationId": "dashboardsGetFilters", - "summary": "Get dashboard filters", + "/api/v1/documents/{identifier}/draft": { + "post": { + "operationId": "documentsCreateDraft", + "summary": "Create document draft", "tags": [ - "Dashboards" + "Documents" ], "parameters": [ { "schema": { "type": "string", - "description": "Dashboard identifier (short ID or UUID)", - "example": "12db1a0a" + "description": "Document identifier (either document ID or identifier slug)", + "example": "abc123" }, "required": true, - "description": "Dashboard identifier (short ID or UUID)", + "description": "Document identifier (either document ID or identifier slug)", "name": "identifier", "in": "path" - }, - { - "schema": { - "type": "string", - "description": "Target user membership ID (for org-scoped API keys)" - }, - "required": false, - "description": "Target user membership ID (for org-scoped API keys)", - "name": "userId", - "in": "query" } ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DocumentsCreateDraftBody" + } + } + } + }, "responses": { "200": { - "description": "Dashboard filter and control configuration", + "description": "Draft created or existing draft returned", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/DashboardFiltersResponse" + "$ref": "#/components/schemas/DocumentsCreateDraftResponse" } } } }, + "400": { + "description": "Document is not eligible for publishing workflow" + }, "401": { "description": "Authentication required" }, "403": { - "description": "Permission denied - VIEWER role required" + "description": "Permission denied - EDITOR role required" }, "404": { - "description": "Dashboard not found" + "description": "Document or branch not found" } } }, - "patch": { - "operationId": "dashboardsUpdateFilters", - "summary": "Update dashboard filters", + "delete": { + "operationId": "documentsDiscardDraft", + "summary": "Discard document draft", "tags": [ - "Dashboards" + "Documents" ], "parameters": [ { "schema": { "type": "string", - "description": "Dashboard identifier (short ID or UUID)", - "example": "12db1a0a" + "description": "Document identifier (either document ID or identifier slug)", + "example": "abc123" }, "required": true, - "description": "Dashboard identifier (short ID or UUID)", + "description": "Document identifier (either document ID or identifier slug)", "name": "identifier", "in": "path" - }, - { - "schema": { - "type": "string", - "description": "Target user membership ID (for org-scoped API keys)" - }, - "required": false, - "description": "Target user membership ID (for org-scoped API keys)", - "name": "userId", - "in": "query" } ], "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/DashboardsUpdateFiltersBody" + "$ref": "#/components/schemas/DocumentsDiscardDraftBody" } } } }, "responses": { "200": { - "description": "Filters updated successfully", + "description": "Draft discarded successfully", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/DashboardFiltersResponse" + "$ref": "#/components/schemas/DocumentsDiscardDraftResponse" } } } }, - "400": { - "description": "Invalid request body - must include at least one filter, control, or filterOrder" - }, "401": { "description": "Authentication required" }, "403": { - "description": "Permission denied - EDITOR role required" + "description": "Permission denied" }, "404": { - "description": "Dashboard not found or document does not have a dashboard" - }, - "409": { - "description": "Conflict - draft already exists. Set clearExistingDraft to true to proceed." + "description": "Document or draft not found" } } } }, - "/api/v1/documents": { + "/api/v1/documents/{identifier}/drafts": { "get": { - "operationId": "documentsList", - "summary": "List documents", + "description": "Lists drafts for a document with branch context. By default only active drafts are returned; pass `include=archived` to also include soft-deleted drafts (retained ~7 days). Results are sorted by `createdAt` descending.", + "operationId": "documentsListDrafts", + "summary": "List document drafts", "tags": [ "Documents" ], - "parameters": [ - { - "schema": { - "type": "string", - "format": "uuid", - "description": "Filter by creator membership ID" - }, - "required": false, - "description": "Filter by creator membership ID", - "name": "creatorId", - "in": "query" - }, - { - "schema": { - "type": "string", - "description": "Cursor for pagination" - }, - "required": false, - "description": "Cursor for pagination", - "name": "cursor", - "in": "query" - }, - { - "schema": { - "type": "string", - "format": "uuid", - "description": "Filter by folder ID" - }, - "required": false, - "description": "Filter by folder ID", - "name": "folderId", - "in": "query" - }, - { - "schema": { - "type": "string", - "description": "Comma-separated list of additional fields to include: _count, labels, includeDeleted, onlyFavorites, onlySharedWithMe. onlySharedWithMe requires userId or user-scoped key and cannot be combined with onlyFavorites or folderId.", - "example": "_count,labels" - }, - "required": false, - "description": "Comma-separated list of additional fields to include: _count, labels, includeDeleted, onlyFavorites, onlySharedWithMe. onlySharedWithMe requires userId or user-scoped key and cannot be combined with onlyFavorites or folderId.", - "name": "include", - "in": "query" - }, - { - "schema": { - "type": "string", - "description": "Comma-separated list of label names to filter by", - "example": "verified,important" - }, - "required": false, - "description": "Comma-separated list of label names to filter by", - "name": "labels", - "in": "query" - }, - { - "schema": { - "type": "integer", - "exclusiveMinimum": 0, - "default": 50, - "description": "Number of records per page" - }, - "required": false, - "description": "Number of records per page", - "name": "pageSize", - "in": "query" - }, - { - "schema": { - "type": "string", - "enum": [ - "asc", - "desc" - ], - "default": "asc", - "description": "Sort direction" - }, - "required": false, - "description": "Sort direction", - "name": "sortDirection", - "in": "query" - }, + "parameters": [ { "schema": { "type": "string", - "enum": [ - "name", - "favorites", - "updatedAt", - "visits" - ], - "default": "name", - "description": "Field to sort by" + "description": "Document identifier (either document ID or identifier slug)", + "example": "abc123" }, - "required": false, - "description": "Field to sort by", - "name": "sortField", - "in": "query" + "required": true, + "description": "Document identifier (either document ID or identifier slug)", + "name": "identifier", + "in": "path" }, { "schema": { "type": "string", - "format": "uuid", - "description": "Filter documents visible to this membership ID" + "description": "Comma-separated list of additional drafts to include. Only \"archived\" is recognized — when present, soft-deleted drafts (retained ~7 days) are returned alongside active drafts.", + "example": "archived" }, "required": false, - "description": "Filter documents visible to this membership ID", - "name": "userId", + "description": "Comma-separated list of additional drafts to include. Only \"archived\" is recognized — when present, soft-deleted drafts (retained ~7 days) are returned alongside active drafts.", + "name": "include", "in": "query" } ], "responses": { "200": { - "description": "Paginated list of documents", + "description": "List of drafts for the document", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/DocumentsListResponse" + "$ref": "#/components/schemas/DocumentsListDraftsResponse" } } } }, + "400": { + "description": "Invalid query parameters" + }, "401": { "description": "Authentication required" + }, + "403": { + "description": "Insufficient permissions to view the document" + }, + "404": { + "description": "Document not found" } } - }, + } + }, + "/api/v1/documents/{identifier}/duplicate": { "post": { - "operationId": "documentsCreate", - "summary": "Create document", + "operationId": "documentsDuplicate", + "summary": "Duplicate document", "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" + }, + { + "schema": { + "type": "string", + "format": "uuid", + "description": "Target user membership ID (for org-scoped API keys)" + }, + "required": false, + "description": "Target user membership ID (for org-scoped API keys)", + "name": "userId", + "in": "query" + } + ], "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/DocumentsCreateBody" + "$ref": "#/components/schemas/DocumentsDuplicateBody" } } } }, "responses": { "201": { - "description": "Document created successfully", + "description": "Document duplicated successfully", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/DocumentsCreateResponse" + "$ref": "#/components/schemas/DocumentsDuplicateResponse" } } } }, "400": { - "description": "Invalid request body" + "description": "Invalid name or folder path" }, "401": { "description": "Authentication required" @@ -11649,16 +35275,15 @@ "description": "Permission denied" }, "404": { - "description": "Model or branch not found" + "description": "Document or folder not found" } } } }, - "/api/v1/documents/{identifier}": { - "get": { - "description": "Retrieves a document's configuration in a format compatible with PUT for round-trip editing. GET a document, modify the response, and PUT it back to update. Only dashboard documents are supported; analysis documents return 400.", - "operationId": "documentsGet", - "summary": "Get document", + "/api/v1/documents/{identifier}/favorite": { + "put": { + "operationId": "documentsAddFavorite", + "summary": "Add document to favorites", "tags": [ "Documents" ], @@ -11673,37 +35298,37 @@ "description": "Document identifier (either document ID or identifier slug)", "name": "identifier", "in": "path" + }, + { + "schema": { + "type": "string", + "format": "uuid", + "description": "Target user membership ID (for org-scoped API keys)" + }, + "required": false, + "description": "Target user membership ID (for org-scoped API keys)", + "name": "userId", + "in": "query" } ], "responses": { - "200": { - "description": "Document details", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DocumentsGetResponse" - } - } - } - }, - "400": { - "description": "Analysis documents are not supported" + "204": { + "description": "Favorite added successfully" }, "401": { "description": "Authentication required" }, "403": { - "description": "Insufficient permissions to view the document" + "description": "Permission denied" }, "404": { "description": "Document not found" } } }, - "put": { - "description": "Updates a document with the specified identifier. This endpoint performs a full resource replacement — all required fields must be provided and existing query presentations are replaced entirely. Only dashboard documents are supported; analysis documents and documents without an associated dashboard return 400. For published documents, the update goes through a draft/publish workflow automatically; if a draft already exists, the request returns 409 unless `clearExistingDraft` is set to `true`.", - "operationId": "documentsPut", - "summary": "Replace document (full replacement)", + "delete": { + "operationId": "documentsRemoveFavorite", + "summary": "Remove document from favorites", "tags": [ "Documents" ], @@ -11718,49 +35343,39 @@ "description": "Document identifier (either document ID or identifier slug)", "name": "identifier", "in": "path" + }, + { + "schema": { + "type": "string", + "format": "uuid", + "description": "Target user membership ID (for org-scoped API keys)" + }, + "required": false, + "description": "Target user membership ID (for org-scoped API keys)", + "name": "userId", + "in": "query" } ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DocumentsPutBody" - } - } - } - }, "responses": { - "200": { - "description": "Document replaced successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DocumentsPutResponse" - } - } - } - }, - "400": { - "description": "Invalid request body, missing required fields, or validation error (also returned for analysis documents and documents without an associated dashboard)" + "204": { + "description": "Favorite removed successfully" }, "401": { "description": "Authentication required" }, "403": { - "description": "Insufficient permissions to update the document" + "description": "Permission denied" }, "404": { "description": "Document not found" - }, - "409": { - "description": "Draft already exists - set clearExistingDraft to true to discard it and proceed" } } - }, + } + }, + "/api/v1/documents/{identifier}/labels": { "patch": { - "description": "Updates a document's name, description, and/or identifier. This is a partial update — only provided fields are modified, and at least one of `name`, `description`, or `identifier` must be supplied. When `identifier` is changed, the previous identifier is retained in the document identifier history and continues to redirect. For published documents, the update goes through a draft/publish workflow automatically.", - "operationId": "documentsUpdate", - "summary": "Rename document", + "operationId": "documentsBulkUpdateLabels", + "summary": "Bulk update document labels", "tags": [ "Documents" ], @@ -11775,48 +35390,58 @@ "description": "Document identifier (either document ID or identifier slug)", "name": "identifier", "in": "path" + }, + { + "schema": { + "type": "string", + "format": "uuid", + "description": "Target user membership ID (for org-scoped API keys)" + }, + "required": false, + "description": "Target user membership ID (for org-scoped API keys)", + "name": "userId", + "in": "query" } ], "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/DocumentsUpdateBody" + "$ref": "#/components/schemas/DocumentsBulkUpdateLabelsBody" } } } }, "responses": { "200": { - "description": "Document updated successfully", + "description": "Labels updated successfully", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/DocumentsUpdateResponse" + "$ref": "#/components/schemas/DocumentsBulkUpdateLabelsResponse" } } } }, "400": { - "description": "Invalid request body or validation error (e.g. missing name/description/identifier, name too long, identifier already in use)" + "description": "Invalid request - at least one label must be specified" }, "401": { "description": "Authentication required" }, "403": { - "description": "Permission denied - EDITOR role required" + "description": "Permission denied" }, "404": { "description": "Document not found" - }, - "409": { - "description": "Draft already exists - set clearExistingDraft to true to discard it and proceed" } } - }, - "delete": { - "operationId": "documentsDelete", - "summary": "Delete document", + } + }, + "/api/v1/documents/{identifier}/labels/{labelName}": { + "put": { + "operationId": "documentsAddLabel", + "summary": "Add label to document", "tags": [ "Documents" ], @@ -11824,42 +35449,55 @@ { "schema": { "type": "string", - "description": "Document identifier (either document ID or identifier slug)", + "description": "Document identifier", "example": "abc123" }, "required": true, - "description": "Document identifier (either document ID or identifier slug)", + "description": "Document identifier", "name": "identifier", "in": "path" + }, + { + "schema": { + "type": "string", + "description": "Label name", + "example": "verified" + }, + "required": true, + "description": "Label name", + "name": "labelName", + "in": "path" + }, + { + "schema": { + "type": "string", + "format": "uuid", + "description": "Target user membership ID (for org-scoped API keys)" + }, + "required": false, + "description": "Target user membership ID (for org-scoped API keys)", + "name": "userId", + "in": "query" } ], "responses": { - "200": { - "description": "Document deleted successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SuccessResponse" - } - } - } + "204": { + "description": "Label added successfully" }, "401": { "description": "Authentication required" }, "403": { - "description": "Permission denied - MANAGER role required" + "description": "Permission denied" }, "404": { - "description": "Document not found" + "description": "Document or label not found" } } - } - }, - "/api/v1/documents/{identifier}/queries": { - "get": { - "operationId": "documentsGetQueries", - "summary": "List document queries", + }, + "delete": { + "operationId": "documentsRemoveLabel", + "summary": "Remove label from document", "tags": [ "Documents" ], @@ -11867,25 +35505,40 @@ { "schema": { "type": "string", - "description": "Document identifier (either document ID or identifier slug)", - "example": "abc123" + "description": "Document identifier", + "example": "abc123" + }, + "required": true, + "description": "Document identifier", + "name": "identifier", + "in": "path" + }, + { + "schema": { + "type": "string", + "description": "Label name", + "example": "verified" }, "required": true, - "description": "Document identifier (either document ID or identifier slug)", - "name": "identifier", + "description": "Label name", + "name": "labelName", "in": "path" + }, + { + "schema": { + "type": "string", + "format": "uuid", + "description": "Target user membership ID (for org-scoped API keys)" + }, + "required": false, + "description": "Target user membership ID (for org-scoped API keys)", + "name": "userId", + "in": "query" } ], "responses": { - "200": { - "description": "List of queries in the document", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DocumentsGetQueriesResponse" - } - } - } + "204": { + "description": "Label removed successfully" }, "401": { "description": "Authentication required" @@ -11899,10 +35552,10 @@ } } }, - "/api/v1/documents/{identifier}/move": { - "post": { - "operationId": "documentsMove", - "summary": "Move document", + "/api/v1/documents/{identifier}/transfer-ownership": { + "put": { + "operationId": "documentsTransferOwnership", + "summary": "Transfer document ownership", "tags": [ "Documents" ], @@ -11923,14 +35576,14 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/DocumentsMoveBody" + "$ref": "#/components/schemas/DocumentsTransferOwnershipBody" } } } }, "responses": { "200": { - "description": "Document moved successfully", + "description": "Ownership transferred successfully", "content": { "application/json": { "schema": { @@ -11940,24 +35593,24 @@ } }, "400": { - "description": "Invalid folder path or scope" + "description": "Invalid user ID" }, "401": { "description": "Authentication required" }, "403": { - "description": "Permission denied - MANAGER role required" + "description": "Permission denied - MANAGER role or owner required" }, "404": { - "description": "Document or folder not found" + "description": "Document or user not found" } } } }, - "/api/v1/documents/{identifier}/permissions": { + "/api/v1/documents/{identifier}/access-list": { "get": { - "operationId": "documentsGetPermissions", - "summary": "Get document permissions", + "operationId": "documentsAccessList", + "summary": "List document access principals", "tags": [ "Documents" ], @@ -11976,22 +35629,90 @@ { "schema": { "type": "string", - "format": "uuid", - "description": "User membership ID to check permissions for" + "description": "Cursor for pagination (from previous response nextCursor)", + "example": "eyJpZCI6IjEyMzQ1In0" }, - "required": true, - "description": "User membership ID to check permissions for", - "name": "userId", + "required": false, + "description": "Cursor for pagination (from previous response nextCursor)", + "name": "cursor", + "in": "query" + }, + { + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 100, + "default": 20, + "description": "Number of results per page (1-100, integer)", + "example": 20 + }, + "required": false, + "description": "Number of results per page (1-100, integer)", + "name": "pageSize", + "in": "query" + }, + { + "schema": { + "type": "string", + "enum": [ + "asc", + "desc" + ], + "default": "asc", + "description": "Sort direction (default: asc)", + "example": "desc" + }, + "required": false, + "description": "Sort direction (default: asc)", + "name": "sortDirection", + "in": "query" + }, + { + "schema": { + "type": "string", + "description": "Field to sort results by" + }, + "required": false, + "description": "Field to sort results by", + "name": "sortField", + "in": "query" + }, + { + "schema": { + "type": "string", + "enum": [ + "direct", + "folder" + ], + "description": "Filter by access source: direct or folder" + }, + "required": false, + "description": "Filter by access source: direct or folder", + "name": "accessSource", + "in": "query" + }, + { + "schema": { + "type": "string", + "enum": [ + "user", + "userGroup" + ], + "description": "Filter by principal type: user or userGroup" + }, + "required": false, + "description": "Filter by principal type: user or userGroup", + "name": "type", "in": "query" } ], "responses": { "200": { - "description": "User permissions for the document", + "description": "List of users and groups with access", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/DocumentsGetPermissionsResponse" + "$ref": "#/components/schemas/DocumentsAccessListResponse" } } } @@ -12000,16 +35721,19 @@ "description": "Authentication required" }, "403": { - "description": "Permission denied" + "description": "Permission denied - VIEWER role required" }, "404": { - "description": "Document or user not found" + "description": "Document not found" } } - }, - "put": { - "operationId": "documentsUpdatePermissionSettings", - "summary": "Update document permission settings", + } + }, + "/api/v1/documents/{identifier}/favorites": { + "get": { + "description": "Lists users who have favorited the document, paginated and sorted by favoritedAt. Document-centric counterpart to GET /api/v1/documents?include=onlyFavorites: useful for migration scripts that need to preserve favorites when replacing documents, without iterating every user in the organization.", + "operationId": "documentsListFavorites", + "summary": "List users who favorited the document", "tags": [ "Documents" ], @@ -12024,98 +35748,127 @@ "description": "Document identifier (either document ID or identifier slug)", "name": "identifier", "in": "path" + }, + { + "schema": { + "type": "string", + "description": "Cursor for pagination (from previous response nextCursor)", + "example": "eyJpZCI6IjEyMzQ1In0" + }, + "required": false, + "description": "Cursor for pagination (from previous response nextCursor)", + "name": "cursor", + "in": "query" + }, + { + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 100, + "default": 20, + "description": "Number of results per page (1-100, integer)", + "example": 20 + }, + "required": false, + "description": "Number of results per page (1-100, integer)", + "name": "pageSize", + "in": "query" + }, + { + "schema": { + "type": "string", + "enum": [ + "asc", + "desc" + ], + "default": "asc", + "description": "Sort direction by favoritedAt (default: asc — oldest first)", + "example": "desc" + }, + "required": false, + "description": "Sort direction by favoritedAt (default: asc — oldest first)", + "name": "sortDirection", + "in": "query" } ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DocumentsUpdatePermissionSettingsBody" - } - } - } - }, "responses": { "200": { - "description": "Permission settings updated successfully", + "description": "Paginated list of users who favorited the document", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SuccessResponse" + "$ref": "#/components/schemas/DocumentsListFavoritesResponse" } } } }, "400": { - "description": "Invalid request body" + "description": "Invalid query parameters" }, "401": { "description": "Authentication required" }, "403": { - "description": "Permission denied - MANAGER role required" + "description": "Permission denied — caller lacks MANAGER on the document, or used a user-scoped (personal access token) API key (org-scoped only)" }, "404": { "description": "Document not found" } } - }, + } + }, + "/api/v2/documents": { "post": { - "operationId": "documentsAddPermits", - "summary": "Add document permits", + "description": "Create a brand-new document and publish it live. Accepts creation metadata (`modelId`, `name`, optional `identifier` / `description` / `folderId`) plus the same content slice as the PATCH body — `queryPresentations`, `controls`, `settings`, `containers`. The server mints internal tile identifiers, so callers omit `miniUuid`. Tiles in `queryPresentations` are merged by key over the single empty seed tile at key `\"1\"`; write to `\"1\"` (or send it as `null`) to replace the seed.\n\nWhen `containers` is omitted, every dashboard-eligible tile is auto-placed in a default layout. When `containers` is present, it fully defines the layout — tiles it does not reference are stored but not rendered.\n\nThe new document is published live before the response returns. As a first publish of brand-new content it is not subject to the org’s `requirePullRequestToPublish` policy (which gates edits to existing content).", + "operationId": "documentsV2Create", + "summary": "Create document", "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": { + "required": true, "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/DocumentsAddPermitsBody" + "$ref": "#/components/schemas/DocumentsV2CreateBody" } } } }, "responses": { - "200": { - "description": "Permissions added successfully", + "201": { + "description": "Document created and published successfully.", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SuccessResponse" + "$ref": "#/components/schemas/DocumentsV2CreateResponse" } } } }, "400": { - "description": "Invalid request body - userIds or userGroupIds required" + "description": "Invalid request body or schema validation error (e.g. unknown top-level field, name too long, query presentation cap exceeded), or the `identifier` is already in use." }, "401": { - "description": "Authentication required" + "description": "Authentication required." }, "403": { - "description": "Permission denied - MANAGER role required" + "description": "Insufficient permissions to create a document on this model." }, "404": { - "description": "Document not found" + "description": "Base model or branch not found." + }, + "405": { + "description": "Method not allowed." } } - }, - "patch": { - "operationId": "documentsUpdatePermits", - "summary": "Update document permits", + } + }, + "/api/v2/documents/{identifier}": { + "get": { + "description": "Read the document's current draft state (or the published state if no draft exists). Returns the full `DocumentsV2ReadResponse` shape.\n\nThe response is structured so a caller can take it verbatim and submit it as the body of the draft PATCH routes. Tiles in `queryPresentations.data` are keyed by a stable record key (e.g. `\"1\"`, `\"2\"`) — the server uses that key to identify existing tiles for updates, so callers do not need to track or send any other identifier. Control IDs and container `instanceKey` / `referenceKey` values also round-trip unchanged.", + "operationId": "documentsV2Get", + "summary": "Read document state", "tags": [ "Documents" ], @@ -12123,52 +35876,46 @@ { "schema": { "type": "string", - "description": "Document identifier (either document ID or identifier slug)", + "description": "Document identifier — either the URL slug (e.g. `abc123`) or the canonical workbook UUID.", "example": "abc123" }, "required": true, - "description": "Document identifier (either document ID or identifier slug)", + "description": "Document identifier — either the URL slug (e.g. `abc123`) or the canonical workbook UUID.", "name": "identifier", "in": "path" } ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DocumentsUpdatePermitsBody" - } - } - } - }, "responses": { "200": { - "description": "Permissions updated successfully", + "description": "Document state. A workbook-only document (no dashboard layout yet) returns only the workbook-scoped fields (`name`, `description`, `queryPresentations`); the dashboard-scoped `containers`, `controls`, and `settings` are omitted until a layout exists.", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SuccessResponse" + "$ref": "#/components/schemas/DocumentsV2ReadResponse" } } } }, - "400": { - "description": "Invalid request body - userIds or userGroupIds required" - }, "401": { - "description": "Authentication required" + "description": "Authentication required." }, "403": { - "description": "Permission denied - MANAGER role required" + "description": "Insufficient permissions to read the document." }, "404": { - "description": "Document not found" + "description": "Document not found." + }, + "422": { + "description": "The document cannot be read as a dashboard: a classic-layout dashboard (upgrade to the advanced layout first) or an app document." } } - }, - "delete": { - "operationId": "documentsRevokePermits", - "summary": "Revoke document permits", + } + }, + "/api/v2/documents/{identifier}/draft": { + "patch": { + "description": "Create a new draft on the published document and apply the patch. No auto-publish — the response includes the new `draftIdentifier` for follow-up calls.\n\nPass an optional `branchId` to attach the draft to a branch; omit it for a draft on the main (unpublished) workspace.", + "operationId": "documentsV2PatchDraft", + "summary": "Create draft and patch document", "tags": [ "Documents" ], @@ -12176,11 +35923,11 @@ { "schema": { "type": "string", - "description": "Document identifier (either document ID or identifier slug)", + "description": "Document identifier — either the URL slug (e.g. `abc123`) or the canonical workbook UUID.", "example": "abc123" }, "required": true, - "description": "Document identifier (either document ID or identifier slug)", + "description": "Document identifier — either the URL slug (e.g. `abc123`) or the canonical workbook UUID.", "name": "identifier", "in": "path" } @@ -12189,41 +35936,51 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/DocumentsRevokePermitsBody" + "$ref": "#/components/schemas/DocumentsV2CreateDraftBody" } } } }, "responses": { "200": { - "description": "Permissions revoked successfully", + "description": "Draft created and patch applied successfully.", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SuccessResponse" + "$ref": "#/components/schemas/DocumentsV2PatchDraftResponse" } } } }, "400": { - "description": "Invalid request body - userIds or userGroupIds required" + "description": "Invalid request body or schema validation error (e.g. unknown top-level field, name too long, query presentation cap exceeded)." }, "401": { - "description": "Authentication required" + "description": "Authentication required." }, "403": { - "description": "Permission denied - MANAGER role required" + "description": "Insufficient permissions to update the document." }, "404": { - "description": "Document not found" + "description": "Document or branch not found." + }, + "405": { + "description": "Method not allowed." + }, + "409": { + "description": "The target is not a published document (drafts only attach to published documents), or a concurrent request just created the layout for this document — retry." + }, + "422": { + "description": "The document cannot satisfy the patch: a classic-layout dashboard (upgrade to the advanced layout first), an app document, or a workbook-only document patched without a `containers` payload (or with an empty one)." } } } }, - "/api/v1/documents/{identifier}/draft": { - "post": { - "operationId": "documentsCreateDraft", - "summary": "Create document draft", + "/api/v2/documents/{identifier}/draft/{draftIdentifier}": { + "get": { + "description": "Read the named draft's state. Returns the full `DocumentsV2ReadResponse` shape — same as the live-state read endpoint.\n\nThe response is structured so a caller can take it verbatim and submit it as the body of the draft PATCH routes. Tiles in `queryPresentations.data` are keyed by a stable record key (e.g. `\"1\"`, `\"2\"`) — the server uses that key to identify existing tiles for updates, so callers do not need to track or send any other identifier. Control IDs and container `instanceKey` / `referenceKey` values also round-trip unchanged.", + "operationId": "documentsV2GetDraft", + "summary": "Read draft state", "tags": [ "Documents" ], @@ -12231,52 +35988,55 @@ { "schema": { "type": "string", - "description": "Document identifier (either document ID or identifier slug)", + "description": "Draft workbook identifier (see `POST /api/v1/documents/{identifier}/draft`).", + "example": "def456" + }, + "required": true, + "description": "Draft workbook identifier (see `POST /api/v1/documents/{identifier}/draft`).", + "name": "draftIdentifier", + "in": "path" + }, + { + "schema": { + "type": "string", + "description": "Published document identifier.", "example": "abc123" }, "required": true, - "description": "Document identifier (either document ID or identifier slug)", + "description": "Published document identifier.", "name": "identifier", "in": "path" } ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DocumentsCreateDraftBody" - } - } - } - }, "responses": { "200": { - "description": "Draft created or existing draft returned", + "description": "Draft state.", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/DocumentsCreateDraftResponse" + "$ref": "#/components/schemas/DocumentsV2ReadResponse" } } } }, - "400": { - "description": "Document is not eligible for publishing workflow" - }, "401": { - "description": "Authentication required" + "description": "Authentication required." }, "403": { - "description": "Permission denied - EDITOR role required" + "description": "Insufficient permissions to read the draft." }, "404": { - "description": "Document or branch not found" + "description": "Document or draft not found." + }, + "422": { + "description": "The draft cannot be read as a dashboard: a classic-layout dashboard (upgrade to the advanced layout first) or an app document." } } }, - "delete": { - "operationId": "documentsDiscardDraft", - "summary": "Discard document draft", + "patch": { + "description": "Apply the patch to an existing draft addressed by `draftIdentifier`. Pure apply — no draft creation, no publish.", + "operationId": "documentsV2PatchDraftByIdentifier", + "summary": "Patch draft", "tags": [ "Documents" ], @@ -12284,11 +36044,22 @@ { "schema": { "type": "string", - "description": "Document identifier (either document ID or identifier slug)", + "description": "Draft workbook identifier (see `POST /api/v1/documents/{identifier}/draft`).", + "example": "def456" + }, + "required": true, + "description": "Draft workbook identifier (see `POST /api/v1/documents/{identifier}/draft`).", + "name": "draftIdentifier", + "in": "path" + }, + { + "schema": { + "type": "string", + "description": "Published document identifier.", "example": "abc123" }, "required": true, - "description": "Document identifier (either document ID or identifier slug)", + "description": "Published document identifier.", "name": "identifier", "in": "path" } @@ -12297,38 +36068,51 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/DocumentsDiscardDraftBody" + "$ref": "#/components/schemas/DocumentsV2PatchDraftBody" } } } }, "responses": { "200": { - "description": "Draft discarded successfully", + "description": "Patch applied to draft successfully.", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/DocumentsDiscardDraftResponse" + "$ref": "#/components/schemas/DocumentsV2PatchDraftResponse" } } } }, + "400": { + "description": "Invalid request body or schema validation error (e.g. unknown top-level field, name too long, query presentation cap exceeded)." + }, "401": { - "description": "Authentication required" + "description": "Authentication required." }, "403": { - "description": "Permission denied" + "description": "Insufficient permissions to update the draft." }, "404": { - "description": "Document or draft not found" + "description": "Document or draft not found." + }, + "405": { + "description": "Method not allowed." + }, + "409": { + "description": "The target is not a published document (drafts only attach to published documents), or a concurrent request just created the layout for this document — retry." + }, + "422": { + "description": "The draft cannot satisfy the patch: a classic-layout dashboard (upgrade to the advanced layout first), an app document, or a workbook-only draft patched without a `containers` payload (or with an empty one)." } } } }, - "/api/v1/documents/{identifier}/duplicate": { + "/api/v2/documents/{identifier}/draft/publish": { "post": { - "operationId": "documentsDuplicate", - "summary": "Duplicate document", + "description": "Publish the document's current main (non-branch) draft, promoting it to the published version. No request body — the draft is consumed, so the response echoes the now-published document metadata.\n\nOnly the main draft is publishable here; a branch-attached draft is published by merging its branch (`POST /api/v1/models/{modelId}/branch/{branchName}/merge`), so a document with no main draft returns 404. Documents that require a pull request to publish return 400.", + "operationId": "documentsV2PublishDraft", + "summary": "Publish draft", "tags": [ "Documents" ], @@ -12336,545 +36120,1048 @@ { "schema": { "type": "string", - "description": "Document identifier (either document ID or identifier slug)", + "description": "Document identifier — either the URL slug (e.g. `abc123`) or the canonical workbook UUID.", "example": "abc123" }, "required": true, - "description": "Document identifier (either document ID or identifier slug)", + "description": "Document identifier — either the URL slug (e.g. `abc123`) or the canonical workbook UUID.", "name": "identifier", "in": "path" + } + ], + "responses": { + "200": { + "description": "Draft published successfully.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DocumentsV2PublishDraftResponse" + } + } + } }, - { - "schema": { - "type": "string", - "format": "uuid", - "description": "Target user membership ID (for org-scoped API keys)" - }, - "required": false, - "description": "Target user membership ID (for org-scoped API keys)", - "name": "userId", - "in": "query" + "400": { + "description": "The document requires a pull request to publish (response detail: \"Can't publish because this document can only be edited through a branch\")." + }, + "401": { + "description": "Authentication required." + }, + "403": { + "description": "Insufficient permissions to publish the draft." + }, + "404": { + "description": "Document not found, or it has no main draft to publish (a branch-attached draft is published by merging its branch)." + }, + "405": { + "description": "Method not allowed." + }, + "409": { + "description": "The target is not a published document." } + } + } + }, + "/api/v1/embed/sso/generate-session": { + "post": { + "operationId": "embedSsoGenerateSession", + "summary": "Generate embedded SSO session", + "tags": [ + "Embed" ], "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/DocumentsDuplicateBody" + "$ref": "#/components/schemas/EmbedSsoGenerateSessionBody" } } } }, "responses": { - "201": { - "description": "Document duplicated successfully", + "200": { + "description": "Session token generated", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/DocumentsDuplicateResponse" + "$ref": "#/components/schemas/EmbedSsoGenerateSessionResponse" } } } }, "400": { - "description": "Invalid name or folder path" + "description": "Invalid request body" }, "401": { - "description": "Authentication required" + "description": "Authentication required (API key with embed scope)" }, "403": { - "description": "Permission denied" - }, - "404": { - "description": "Document or folder not found" + "description": "Permission denied - embed not enabled" } } } }, - "/api/v1/documents/{identifier}/favorite": { - "put": { - "operationId": "documentsAddFavorite", - "summary": "Add document to favorites", + "/api/v1/ai/eval/prompt-sets": { + "get": { + "description": "List eval prompt sets, sorted alphabetically by name. When `model_ids` is omitted, returns prompt sets for every shared model the caller can access. Requires at least the Querier role on each requested model.", + "operationId": "aiEvalPromptSetsList", + "summary": "List eval prompt sets", "tags": [ - "Documents" + "AI Eval" ], "parameters": [ { "schema": { "type": "string", - "description": "Document identifier (either document ID or identifier slug)", - "example": "abc123" + "enum": [ + "true", + "false" + ], + "description": "When `true`, returns archived prompt sets instead of active ones. Defaults to `false`.", + "example": "false" }, - "required": true, - "description": "Document identifier (either document ID or identifier slug)", - "name": "identifier", - "in": "path" + "required": false, + "description": "When `true`, returns archived prompt sets instead of active ones. Defaults to `false`.", + "name": "archived", + "in": "query" }, { "schema": { - "type": "string", - "format": "uuid", - "description": "Target user membership ID (for org-scoped API keys)" + "type": "array", + "items": { + "type": "string", + "format": "uuid" + }, + "description": "Optional list of model IDs to filter prompt sets by. When omitted, returns prompt sets for every model the caller can access. Supply multiple times to filter by more than one model (e.g., `?model_ids=A&model_ids=B`)." }, "required": false, - "description": "Target user membership ID (for org-scoped API keys)", - "name": "userId", + "description": "Optional list of model IDs to filter prompt sets by. When omitted, returns prompt sets for every model the caller can access. Supply multiple times to filter by more than one model (e.g., `?model_ids=A&model_ids=B`).", + "name": "model_ids", "in": "query" } ], "responses": { - "204": { - "description": "Favorite added successfully" + "200": { + "description": "List of prompt sets, sorted alphabetically by name.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalPromptSetsListResponse" + } + } + } + }, + "400": { + "description": "Invalid query params (e.g. `model_ids` contains a non-UUID, or `archived` is not `true`/`false`).", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError400" + } + } + } }, "401": { - "description": "Authentication required" + "description": "Missing or invalid API key.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError401" + } + } + } }, "403": { - "description": "Permission denied" + "description": "Insufficient permissions. The caller must have at least the Querier role on each requested model.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError403" + } + } + } }, "404": { - "description": "Document not found" + "description": "No eval-accessible models for this caller.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError404" + } + } + } + } + } + }, + "post": { + "description": "Create a new eval prompt set bound to a shared model. Initial prompts can be supplied; additional prompts can be added later via PATCH.", + "operationId": "aiEvalPromptSetsCreate", + "summary": "Create an eval prompt set", + "tags": [ + "AI Eval" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalPromptSetsCreateBody" + } + } + } + }, + "responses": { + "201": { + "description": "Prompt set created successfully.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalPromptSetsCreateResponse" + } + } + } + }, + "400": { + "description": "Invalid request body.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError400" + } + } + } + }, + "401": { + "description": "Missing or invalid API key.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError401" + } + } + } + }, + "403": { + "description": "Insufficient permissions. The caller must have at least the Querier role on the model.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError403" + } + } + } } } - }, - "delete": { - "operationId": "documentsRemoveFavorite", - "summary": "Remove document from favorites", + } + }, + "/api/v1/ai/eval/prompt-sets/{promptSetId}": { + "get": { + "description": "Get a single prompt set with all of its prompts.", + "operationId": "aiEvalPromptSetsGet", + "summary": "Get an eval prompt set", "tags": [ - "Documents" + "AI Eval" ], "parameters": [ { "schema": { "type": "string", - "description": "Document identifier (either document ID or identifier slug)", - "example": "abc123" + "format": "uuid", + "description": "The unique identifier of the eval prompt set.", + "example": "550e8400-e29b-41d4-a716-446655440000" }, "required": true, - "description": "Document identifier (either document ID or identifier slug)", - "name": "identifier", + "description": "The unique identifier of the eval prompt set.", + "name": "promptSetId", "in": "path" - }, - { - "schema": { - "type": "string", - "format": "uuid", - "description": "Target user membership ID (for org-scoped API keys)" - }, - "required": false, - "description": "Target user membership ID (for org-scoped API keys)", - "name": "userId", - "in": "query" } ], "responses": { - "204": { - "description": "Favorite removed successfully" + "200": { + "description": "Prompt set details.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalPromptSetsGetResponse" + } + } + } + }, + "400": { + "description": "Invalid `promptSetId` — must be a UUID.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError400" + } + } + } }, "401": { - "description": "Authentication required" + "description": "Missing or invalid API key.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError401" + } + } + } }, "403": { - "description": "Permission denied" + "description": "Insufficient permissions.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError403" + } + } + } }, "404": { - "description": "Document not found" + "description": "Prompt set not found.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError404" + } + } + } } } - } - }, - "/api/v1/documents/{identifier}/labels": { + }, "patch": { - "operationId": "documentsBulkUpdateLabels", - "summary": "Bulk update document labels", + "description": "Update a prompt set's name, description, and/or prompts. When `prompts` is supplied, it fully replaces the existing list — existing prompts omitted from the list are deleted, entries without an `id` are created, and entries with a matching `id` are updated in place.", + "operationId": "aiEvalPromptSetsUpdate", + "summary": "Update an eval prompt set", "tags": [ - "Documents" + "AI Eval" ], "parameters": [ { "schema": { "type": "string", - "description": "Document identifier (either document ID or identifier slug)", - "example": "abc123" + "format": "uuid", + "description": "The unique identifier of the eval prompt set.", + "example": "550e8400-e29b-41d4-a716-446655440000" }, "required": true, - "description": "Document identifier (either document ID or identifier slug)", - "name": "identifier", + "description": "The unique identifier of the eval prompt set.", + "name": "promptSetId", "in": "path" - }, - { - "schema": { - "type": "string", - "format": "uuid", - "description": "Target user membership ID (for org-scoped API keys)" - }, - "required": false, - "description": "Target user membership ID (for org-scoped API keys)", - "name": "userId", - "in": "query" } ], "requestBody": { + "required": true, "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/DocumentsBulkUpdateLabelsBody" + "$ref": "#/components/schemas/EvalPromptSetsUpdateBody" } } } }, "responses": { "200": { - "description": "Labels updated successfully", + "description": "Prompt set updated successfully.", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/DocumentsBulkUpdateLabelsResponse" + "$ref": "#/components/schemas/EvalPromptSetsUpdateResponse" } } } }, "400": { - "description": "Invalid request - at least one label must be specified" + "description": "Invalid request body.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError400" + } + } + } }, "401": { - "description": "Authentication required" + "description": "Missing or invalid API key.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError401" + } + } + } }, "403": { - "description": "Permission denied" + "description": "Insufficient permissions.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError403" + } + } + } }, "404": { - "description": "Document not found" + "description": "Prompt set not found.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError404" + } + } + } + }, + "422": { + "description": "A `prompts[].id` in the request does not belong to this prompt set.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError422" + } + } + } } } - } - }, - "/api/v1/documents/{identifier}/labels/{labelName}": { - "put": { - "operationId": "documentsAddLabel", - "summary": "Add label to document", + }, + "delete": { + "description": "Archive (soft-delete) a prompt set. As part of the archive, Omni attempts to cancel every in-flight agentic job associated with the set; the returned `cancelled_job_count` reports how many were cancelled. The archive is committed before run cancellations start. Cancellation is best-effort — the database cancel is authoritative, but the Redis stop-signal that halts a running worker can lag. If the archive itself or a whole run-cancellation fails, the endpoint returns 500, but the prompt set is already archived. The call is idempotent — retrying drains any remaining runs.", + "operationId": "aiEvalPromptSetsArchive", + "summary": "Archive an eval prompt set", "tags": [ - "Documents" + "AI Eval" ], "parameters": [ { "schema": { "type": "string", - "description": "Document identifier", - "example": "abc123" + "format": "uuid", + "description": "The unique identifier of the eval prompt set.", + "example": "550e8400-e29b-41d4-a716-446655440000" }, "required": true, - "description": "Document identifier", - "name": "identifier", + "description": "The unique identifier of the eval prompt set.", + "name": "promptSetId", "in": "path" + } + ], + "responses": { + "200": { + "description": "Prompt set archived successfully.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalPromptSetsDeleteResponse" + } + } + } }, - { - "schema": { - "type": "string", - "description": "Label name", - "example": "verified" - }, - "required": true, - "description": "Label name", - "name": "labelName", - "in": "path" + "400": { + "description": "Invalid `promptSetId` — must be a UUID.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError400" + } + } + } + }, + "401": { + "description": "Missing or invalid API key.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError401" + } + } + } + }, + "403": { + "description": "Insufficient permissions.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError403" + } + } + } + }, + "404": { + "description": "Prompt set not found.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError404" + } + } + } }, + "500": { + "description": "Archive committed but a run-cancellation failed; the set is already archived — safe to retry.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError500" + } + } + } + } + } + } + }, + "/api/v1/ai/eval/prompt-sets/{promptSetId}/unarchive": { + "post": { + "description": "Restore an archived prompt set.", + "operationId": "aiEvalPromptSetsUnarchive", + "summary": "Restore an archived eval prompt set", + "tags": [ + "AI Eval" + ], + "parameters": [ { "schema": { "type": "string", "format": "uuid", - "description": "Target user membership ID (for org-scoped API keys)" + "description": "The unique identifier of the eval prompt set.", + "example": "550e8400-e29b-41d4-a716-446655440000" }, - "required": false, - "description": "Target user membership ID (for org-scoped API keys)", - "name": "userId", - "in": "query" + "required": true, + "description": "The unique identifier of the eval prompt set.", + "name": "promptSetId", + "in": "path" } ], "responses": { - "204": { - "description": "Label added successfully" + "200": { + "description": "Prompt set restored successfully.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalPromptSetsUnarchiveResponse" + } + } + } + }, + "400": { + "description": "Invalid `promptSetId` — must be a UUID.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError400" + } + } + } }, "401": { - "description": "Authentication required" + "description": "Missing or invalid API key.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError401" + } + } + } }, "403": { - "description": "Permission denied" + "description": "Insufficient permissions.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError403" + } + } + } }, "404": { - "description": "Document or label not found" + "description": "Prompt set not found.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError404" + } + } + } } } - }, - "delete": { - "operationId": "documentsRemoveLabel", - "summary": "Remove label from document", + } + }, + "/api/v1/ai/eval/runs": { + "get": { + "description": "List runs for a prompt set, newest first, filtered to runs whose model the caller can access. The `prompt_set_id` query parameter is required.", + "operationId": "aiEvalRunsList", + "summary": "List eval runs", "tags": [ - "Documents" + "AI Eval" ], "parameters": [ { "schema": { "type": "string", - "description": "Document identifier", - "example": "abc123" - }, - "required": true, - "description": "Document identifier", - "name": "identifier", - "in": "path" - }, - { - "schema": { - "type": "string", - "description": "Label name", - "example": "verified" + "enum": [ + "true", + "false" + ], + "description": "When `true`, returns archived runs instead of active ones. Defaults to `false`.", + "example": "false" }, - "required": true, - "description": "Label name", - "name": "labelName", - "in": "path" + "required": false, + "description": "When `true`, returns archived runs instead of active ones. Defaults to `false`.", + "name": "archived", + "in": "query" }, { "schema": { "type": "string", "format": "uuid", - "description": "Target user membership ID (for org-scoped API keys)" + "description": "Required — the prompt set whose runs should be listed.", + "example": "550e8400-e29b-41d4-a716-446655440000" }, - "required": false, - "description": "Target user membership ID (for org-scoped API keys)", - "name": "userId", + "required": true, + "description": "Required — the prompt set whose runs should be listed.", + "name": "prompt_set_id", "in": "query" } ], "responses": { - "204": { - "description": "Label removed successfully" + "200": { + "description": "List of runs for the prompt set.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalRunsListResponse" + } + } + } + }, + "400": { + "description": "Missing or invalid `prompt_set_id`.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError400" + } + } + } }, "401": { - "description": "Authentication required" + "description": "Missing or invalid API key.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError401" + } + } + } }, "403": { - "description": "Permission denied" + "description": "Insufficient permissions.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError403" + } + } + } }, "404": { - "description": "Document not found" + "description": "Prompt set not found.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError404" + } + } + } } } - } - }, - "/api/v1/documents/{identifier}/transfer-ownership": { - "put": { - "operationId": "documentsTransferOwnership", - "summary": "Transfer document ownership", + }, + "post": { + "description": "Create and start a new run against an existing prompt set. The run enqueues one agentic job per prompt and begins executing immediately. Returns the newly created run with its initial per-prompt result rows.", + "operationId": "aiEvalRunsCreate", + "summary": "Start an eval run", "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" - } + "AI Eval" ], "requestBody": { + "required": true, "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/DocumentsTransferOwnershipBody" + "$ref": "#/components/schemas/EvalRunsCreateBody" } } } }, "responses": { - "200": { - "description": "Ownership transferred successfully", + "201": { + "description": "Run created and jobs enqueued.", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SuccessResponse" + "$ref": "#/components/schemas/EvalRunsCreateResponse" } } } }, "400": { - "description": "Invalid user ID" + "description": "Invalid request body.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError400" + } + } + } }, "401": { - "description": "Authentication required" + "description": "Missing or invalid API key.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError401" + } + } + } }, "403": { - "description": "Permission denied - MANAGER role or owner required" + "description": "Insufficient permissions. The caller must have at least the Querier role on the prompt set's model.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError403" + } + } + } }, "404": { - "description": "Document or user not found" + "description": "The prompt set was not found, or `run_config.branch_id` does not match an existing branch in the organization.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError404" + } + } + } + }, + "422": { + "description": "`run_config.branch_id` does not belong to the prompt set's model.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError422" + } + } + } + }, + "429": { + "description": "Per-user active-run cap reached.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError429" + } + } + } + }, + "500": { + "description": "Run created and jobs enqueued, but it could not be re-read for the response. The run exists — list runs for the prompt set to find it rather than retrying, since a retry starts a duplicate run.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError500" + } + } + } + }, + "503": { + "description": "AI eval is paused for this organization.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError503" + } + } + } } } } }, - "/api/v1/documents/{identifier}/access-list": { + "/api/v1/ai/eval/runs/{runId}": { "get": { - "operationId": "documentsAccessList", - "summary": "List document access principals", + "description": "Get an eval run with every per-prompt result row, including the underlying agentic job state and any scoring data.", + "operationId": "aiEvalRunsGet", + "summary": "Get an eval run", "tags": [ - "Documents" + "AI Eval" ], "parameters": [ { "schema": { "type": "string", - "description": "Document identifier (either document ID or identifier slug)", - "example": "abc123" + "format": "uuid", + "description": "The unique identifier of the eval run.", + "example": "660e8400-e29b-41d4-a716-446655440001" }, "required": true, - "description": "Document identifier (either document ID or identifier slug)", - "name": "identifier", + "description": "The unique identifier of the eval run.", + "name": "runId", "in": "path" + } + ], + "responses": { + "200": { + "description": "Run detail.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalRunsGetResponse" + } + } + } }, - { - "schema": { - "type": "string", - "description": "Cursor for pagination (from previous response nextCursor)", - "example": "eyJpZCI6IjEyMzQ1In0" - }, - "required": false, - "description": "Cursor for pagination (from previous response nextCursor)", - "name": "cursor", - "in": "query" - }, - { - "schema": { - "type": "number", - "minimum": 1, - "maximum": 100, - "default": 20, - "description": "Number of results per page (1-100)", - "example": 20 - }, - "required": false, - "description": "Number of results per page (1-100)", - "name": "pageSize", - "in": "query" + "401": { + "description": "Missing or invalid API key.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError401" + } + } + } }, - { - "schema": { - "type": "string", - "enum": [ - "asc", - "desc" - ], - "default": "asc", - "description": "Sort direction (default: asc)", - "example": "desc" - }, - "required": false, - "description": "Sort direction (default: asc)", - "name": "sortDirection", - "in": "query" + "403": { + "description": "Insufficient permissions.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError403" + } + } + } }, + "404": { + "description": "Run not found.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError404" + } + } + } + } + } + }, + "delete": { + "description": "Archive (soft-delete) an eval run. Any non-terminal per-prompt agentic jobs are cancelled as part of the archive (best-effort), and a still-RUNNING run is flipped to CANCELLED before archival. The call is idempotent; archiving an already-terminal or already-archived run is a no-op.", + "operationId": "aiEvalRunsArchive", + "summary": "Archive an eval run", + "tags": [ + "AI Eval" + ], + "parameters": [ { "schema": { "type": "string", - "description": "Field to sort results by" + "format": "uuid", + "description": "The unique identifier of the eval run.", + "example": "660e8400-e29b-41d4-a716-446655440001" }, - "required": false, - "description": "Field to sort results by", - "name": "sortField", - "in": "query" + "required": true, + "description": "The unique identifier of the eval run.", + "name": "runId", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Run archived successfully.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalRunsDeleteResponse" + } + } + } }, - { - "schema": { - "type": "string", - "enum": [ - "direct", - "folder" - ], - "description": "Filter by access source: direct or folder" - }, - "required": false, - "description": "Filter by access source: direct or folder", - "name": "accessSource", - "in": "query" + "401": { + "description": "Missing or invalid API key.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError401" + } + } + } + }, + "403": { + "description": "Insufficient permissions.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError403" + } + } + } }, + "404": { + "description": "Run not found.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError404" + } + } + } + }, + "500": { + "description": "A still-running run may already be flipped to CANCELLED and archived even though the rest of the cascade failed — safe to retry.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError500" + } + } + } + } + } + } + }, + "/api/v1/ai/eval/runs/{runId}/cancel": { + "post": { + "description": "Cancel an in-flight eval run. Any non-terminal per-prompt jobs are cancelled and the run is archived — the response returns the updated run inline (`status: CANCELLED`, `is_archived: true`); use `/unarchive` to surface it in the default `archived=false` list again.", + "operationId": "aiEvalRunsCancel", + "summary": "Cancel an eval run", + "tags": [ + "AI Eval" + ], + "parameters": [ { "schema": { "type": "string", - "enum": [ - "user", - "userGroup" - ], - "description": "Filter by principal type: user or userGroup" + "format": "uuid", + "description": "The unique identifier of the eval run.", + "example": "660e8400-e29b-41d4-a716-446655440001" }, - "required": false, - "description": "Filter by principal type: user or userGroup", - "name": "type", - "in": "query" + "required": true, + "description": "The unique identifier of the eval run.", + "name": "runId", + "in": "path" } ], "responses": { "200": { - "description": "List of users and groups with access", + "description": "Cancellation processed.", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/DocumentsAccessListResponse" + "$ref": "#/components/schemas/EvalRunsCancelResponse" } } } }, "401": { - "description": "Authentication required" + "description": "Missing or invalid API key.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError401" + } + } + } }, "403": { - "description": "Permission denied - VIEWER role required" + "description": "Insufficient permissions.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError403" + } + } + } }, "404": { - "description": "Document not found" + "description": "Run not found.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError404" + } + } + } + }, + "500": { + "description": "The run was cancelled and archived, but could not be re-read for the response — safe to retry.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError500" + } + } + } } } } }, - "/api/v1/embed/sso/generate-session": { + "/api/v1/ai/eval/runs/{runId}/unarchive": { "post": { - "operationId": "embedSsoGenerateSession", - "summary": "Generate embedded SSO session", + "description": "Restore an archived eval run.", + "operationId": "aiEvalRunsUnarchive", + "summary": "Restore an archived eval run", "tags": [ - "Embed" + "AI Eval" ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/EmbedSsoGenerateSessionBody" - } - } + "parameters": [ + { + "schema": { + "type": "string", + "format": "uuid", + "description": "The unique identifier of the eval run.", + "example": "660e8400-e29b-41d4-a716-446655440001" + }, + "required": true, + "description": "The unique identifier of the eval run.", + "name": "runId", + "in": "path" } - }, + ], "responses": { "200": { - "description": "Session token generated", + "description": "Run restored successfully.", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/EmbedSsoGenerateSessionResponse" + "$ref": "#/components/schemas/EvalRunsUnarchiveResponse" } } } }, - "400": { - "description": "Invalid request body" - }, "401": { - "description": "Authentication required (API key with embed scope)" + "description": "Missing or invalid API key.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError401" + } + } + } }, "403": { - "description": "Permission denied - embed not enabled" + "description": "Insufficient permissions.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError403" + } + } + } + }, + "404": { + "description": "Run not found.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalApiError404" + } + } + } } } } @@ -13437,6 +37724,7 @@ { "schema": { "type": "string", + "format": "uuid", "description": "Target user membership ID (for org-scoped API keys)" }, "required": false, @@ -13540,6 +37828,7 @@ { "schema": { "type": "string", + "format": "uuid", "description": "Target user membership ID (for org-scoped API keys)" }, "required": false, @@ -13606,6 +37895,7 @@ { "schema": { "type": "string", + "format": "uuid", "description": "Target user membership ID (for org-scoped API keys)" }, "required": false, @@ -14811,6 +39101,43 @@ "description": "Branch ID for branch-based schema refresh. Required when branch-based schema refresh is enabled for the connection. Must not be provided when branch-based schema refresh is not enabled.", "name": "branch_id", "in": "query" + }, + { + "schema": { + "type": "string", + "enum": [ + "true", + "false" + ], + "description": "When true (the default), performs a hard refresh that fully discards and rebuilds the schema model. When false, performs a soft refresh that merges newly generated views with the existing model. Must be set to false when `schemas` or `tables` filters are provided.", + "example": "false" + }, + "required": false, + "description": "When true (the default), performs a hard refresh that fully discards and rebuilds the schema model. When false, performs a soft refresh that merges newly generated views with the existing model. Must be set to false when `schemas` or `tables` filters are provided.", + "name": "hard_refresh", + "in": "query" + }, + { + "schema": { + "type": "string", + "description": "Optional comma-separated list of schemas to refresh selectively. Only the listed schemas are reloaded; the rest of the schema model is preserved. Requires `hard_refresh=false`.", + "example": "public,analytics" + }, + "required": false, + "description": "Optional comma-separated list of schemas to refresh selectively. Only the listed schemas are reloaded; the rest of the schema model is preserved. Requires `hard_refresh=false`.", + "name": "schemas", + "in": "query" + }, + { + "schema": { + "type": "string", + "description": "Optional comma-separated list of tables to refresh selectively. Only the listed tables are reloaded; the rest of the schema model is preserved. Requires `hard_refresh=false`.", + "example": "public.orders,public.customers" + }, + "required": false, + "description": "Optional comma-separated list of tables to refresh selectively. Only the listed tables are reloaded; the rest of the schema model is preserved. Requires `hard_refresh=false`.", + "name": "tables", + "in": "query" } ], "responses": { @@ -14825,7 +39152,7 @@ } }, "400": { - "description": "Bad request - branch_id required when branch-based schema refresh is enabled, or branch_id not allowed when it is not enabled" + "description": "Bad request - branch_id required when branch-based schema refresh is enabled, branch_id not allowed when it is not enabled, or hard refresh requested with selective schemas/tables filters" }, "401": { "description": "Authentication required" @@ -15050,15 +39377,15 @@ }, { "schema": { - "type": "number", + "type": "integer", "minimum": 1, "maximum": 100, "default": 20, - "description": "Number of results per page (1-100)", + "description": "Number of results per page (1-100, integer)", "example": 20 }, "required": false, - "description": "Number of results per page (1-100)", + "description": "Number of results per page (1-100, integer)", "name": "pageSize", "in": "query" }, @@ -15688,6 +40015,17 @@ "name": "content_filter_mode", "in": "query" }, + { + "schema": { + "type": "string", + "format": "uuid", + "description": "Filter to documents created by this user (user ID). Unknown IDs return 400." + }, + "required": false, + "description": "Filter to documents created by this user (user ID). Unknown IDs return 400.", + "name": "creator_id", + "in": "query" + }, { "schema": { "type": "string", @@ -15805,6 +40143,7 @@ { "schema": { "type": "string", + "format": "uuid", "description": "Target user membership ID (for org-scoped API keys)" }, "required": false, @@ -15897,7 +40236,7 @@ "extension", "staged", "merged", - "history" + "fully-resolved" ], "default": "combined", "description": "IDE mode for YAML operations" @@ -16084,7 +40423,7 @@ "extension", "staged", "merged", - "history" + "fully-resolved" ], "default": "combined", "description": "IDE mode for YAML operations" @@ -16124,6 +40463,51 @@ } } }, + "/api/v1/models/{modelId}/ai-agent-actions": { + "get": { + "description": "Returns the AI agent actions configured for this model — a unified list of sample queries and skills suitable for surfacing as suggested prompts above an AI prompt input. Sample queries come from both `model.sample_queries` and each topic's `sample_queries`; skills come from `model.skills` and each topic's `skills`, deduped by id with topic skills overriding model skills. Each entry's `prompt` is ready to submit verbatim to `POST /api/v1/ai/jobs`.", + "operationId": "modelAiAgentActions", + "summary": "Get model AI agent actions", + "tags": [ + "Models" + ], + "parameters": [ + { + "schema": { + "type": "string", + "format": "uuid", + "description": "Model UUID", + "example": "123e4567-e89b-12d3-a456-426614174000" + }, + "required": true, + "description": "Model UUID", + "name": "modelId", + "in": "path" + } + ], + "responses": { + "200": { + "description": "AI agent actions in display order.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AiAgentActionsResponse" + } + } + } + }, + "401": { + "description": "Missing or invalid API key." + }, + "403": { + "description": "Caller cannot read the model." + }, + "404": { + "description": "Model not found." + } + } + } + }, "/api/v1/query/run": { "post": { "operationId": "queryRun", @@ -16131,6 +40515,19 @@ "tags": [ "Query" ], + "parameters": [ + { + "schema": { + "type": "string", + "format": "uuid", + "description": "Target user membership ID (for org-scoped API keys)" + }, + "required": false, + "description": "Target user membership ID (for org-scoped API keys)", + "name": "userId", + "in": "query" + } + ], "requestBody": { "content": { "application/json": { @@ -16248,15 +40645,15 @@ }, { "schema": { - "type": "number", + "type": "integer", "minimum": 1, "maximum": 100, "default": 20, - "description": "Number of results per page (1-100)", + "description": "Number of results per page (1-100, integer)", "example": 20 }, "required": false, - "description": "Number of results per page (1-100)", + "description": "Number of results per page (1-100, integer)", "name": "pageSize", "in": "query" }, @@ -17118,7 +41515,7 @@ "description": "Schedule not found" }, "409": { - "description": "Another execution is in progress for this schedule" + "description": "Schedule cannot be triggered (paused, system-disabled, or another execution is in progress)" } } } @@ -18026,15 +42423,15 @@ }, { "schema": { - "type": "number", + "type": "integer", "minimum": 1, "maximum": 100, "default": 20, - "description": "Number of results per page (1-100)", + "description": "Number of results per page (1-100, integer)", "example": 20 }, "required": false, - "description": "Number of results per page (1-100)", + "description": "Number of results per page (1-100, integer)", "name": "pageSize", "in": "query" }, diff --git a/internal/openapi/body_shorthand.go b/internal/openapi/body_shorthand.go index 99b7b77..1cf1b55 100644 --- a/internal/openapi/body_shorthand.go +++ b/internal/openapi/body_shorthand.go @@ -202,6 +202,44 @@ var bodyShorthands = map[string]*BodyShorthand{ ExampleShort: `omni models git-sync --commit-message "Update schema"`, ExampleJSON: `omni models git-sync --body '{"commitMessage":"Update schema"}'`, }, + + // v2 documents. Metadata fields are promoted to flags; the heavy nested + // content (containers / controls / queryPresentations / settings) stays + // on --body/stdin. Because a v2-get response is a valid draft PATCH body, + // content round-trips cleanly: v2-get > doc.json, edit, then + // v2-patch-draft --body - < doc.json and v2-publish-draft . + "documentsV2Create": { + Args: []ArgMapping{ + {Name: "model-id", FieldPath: "modelId", Description: "UUID of the model the document is built on", Transform: "string"}, + {Name: "name", FieldPath: "name", Description: "name for the new document", Transform: "string"}, + }, + Flags: []FlagMapping{ + {FlagName: "identifier", FieldPath: "identifier", Description: "identifier for the new document (server-minted if omitted)"}, + {FlagName: "description", FieldPath: "description", Description: "document description"}, + {FlagName: "folder-id", FieldPath: "folderId", Description: "destination folder ID (omit for the root folder)"}, + }, + ExampleShort: `omni documents v2-create 770e8400-e29b-41d4-a716-446655440002 "Q3 Revenue"`, + ExampleJSON: `omni documents v2-create --body '{"modelId":"770e8400-...","name":"Q3 Revenue"}'`, + }, + "documentsV2PatchDraft": { + Flags: []FlagMapping{ + {FlagName: "name", FieldPath: "name", Description: "document name"}, + {FlagName: "description", FieldPath: "description", Description: "document description"}, + {FlagName: "summary", FieldPath: "summary", Description: "what this patch changes; written to the history audit trail"}, + {FlagName: "branch-id", FieldPath: "branchId", Description: "branch the new draft is created on (omit for the main workspace)"}, + }, + ExampleShort: `omni documents v2-patch-draft --name "WIP title"`, + ExampleJSON: `omni documents v2-patch-draft --body '{"name":"WIP title"}'`, + }, + "documentsV2PatchDraftByIdentifier": { + Flags: []FlagMapping{ + {FlagName: "name", FieldPath: "name", Description: "document name"}, + {FlagName: "description", FieldPath: "description", Description: "document description"}, + {FlagName: "summary", FieldPath: "summary", Description: "what this patch changes; written to the history audit trail"}, + }, + ExampleShort: `omni documents v2-patch-draft-by-identifier --name "Edited"`, + ExampleJSON: `omni documents v2-patch-draft-by-identifier --body '{"name":"Edited"}'`, + }, } // GetBodyShorthand returns the shorthand for an operation, or nil if none exists. @@ -239,8 +277,19 @@ func applyBodyShorthand(cmd *cobra.Command, op *operationInfo, sh *BodyShorthand rawBody = jsonBodyFlag } - // If --body/--json-body is provided, use existing behavior + // If --body/--json-body is provided, use existing behavior — but + // reject explicitly-set shorthand flags rather than silently + // dropping them from the request. if rawBody != "" { + var conflicting []string + for _, f := range sh.Flags { + if cmd.Flags().Changed(f.FlagName) { + conflicting = append(conflicting, "--"+f.FlagName) + } + } + if len(conflicting) > 0 { + return fmt.Errorf("%s cannot be combined with --body; include the field(s) in the JSON body instead", strings.Join(conflicting, ", ")) + } return originalRunE(cmd, args) } @@ -323,16 +372,14 @@ func assembleBody(sh *BodyShorthand, args []string, pathParamCount int, cmd *cob } for _, fm := range sh.Flags { + val, _ := cmd.Flags().GetString(fm.FlagName) + if val == "" { + continue + } if fm.IsBool { - val, _ := cmd.Flags().GetString(fm.FlagName) - if val != "" { - body[fm.FieldPath] = (val == "true") - } + body[fm.FieldPath] = (val == "true") } else { - val, _ := cmd.Flags().GetString(fm.FlagName) - if val != "" { - body[fm.FieldPath] = val - } + body[fm.FieldPath] = val } } diff --git a/internal/openapi/body_shorthand_test.go b/internal/openapi/body_shorthand_test.go index dbae591..05fde74 100644 --- a/internal/openapi/body_shorthand_test.go +++ b/internal/openapi/body_shorthand_test.go @@ -534,6 +534,104 @@ func TestShorthand_ModelsGitSync_FlagsOnly(t *testing.T) { } } +func TestShorthand_DocumentsV2Create(t *testing.T) { + var captured APIRequest + exec := func(req APIRequest) error { captured = req; return nil } + + op := &operationInfo{ + Tag: "Documents", + OperationID: "documentsV2Create", + Method: "POST", + Path: "/api/v2/documents", + HasBody: true, + } + + cmd := buildCommand(op, exec) + cmd.SetArgs([]string{"770e8400-e29b-41d4-a716-446655440002", "Q3 Revenue", "--folder-id", "f-1", "--identifier", "q3-rev"}) + if err := cmd.Execute(); err != nil { + t.Fatalf("Execute: %v", err) + } + + var body map[string]interface{} + if err := json.Unmarshal(captured.Body, &body); err != nil { + t.Fatalf("unmarshal body: %v", err) + } + if body["modelId"] != "770e8400-e29b-41d4-a716-446655440002" { + t.Errorf("modelId = %v, want the positional model ID", body["modelId"]) + } + if body["name"] != "Q3 Revenue" { + t.Errorf("name = %v, want 'Q3 Revenue'", body["name"]) + } + if body["folderId"] != "f-1" { + t.Errorf("folderId = %v, want f-1", body["folderId"]) + } + if body["identifier"] != "q3-rev" { + t.Errorf("identifier = %v, want q3-rev", body["identifier"]) + } +} + +func TestShorthand_DocumentsV2PatchDraft(t *testing.T) { + var captured APIRequest + exec := func(req APIRequest) error { captured = req; return nil } + + op := &operationInfo{ + Tag: "Documents", + OperationID: "documentsV2PatchDraft", + Method: "PATCH", + Path: "/api/v2/documents/{identifier}/draft", + PathParams: []paramInfo{{Name: "identifier", In: "path"}}, + HasBody: true, + } + + cmd := buildCommand(op, exec) + cmd.SetArgs([]string{"abc123", "--name", "WIP", "--branch-id", "b-1"}) + if err := cmd.Execute(); err != nil { + t.Fatalf("Execute: %v", err) + } + + var body map[string]interface{} + json.Unmarshal(captured.Body, &body) + if body["name"] != "WIP" { + t.Errorf("name = %v, want WIP", body["name"]) + } + if body["branchId"] != "b-1" { + t.Errorf("branchId = %v, want b-1", body["branchId"]) + } +} + +func TestShorthand_DocumentsV2PatchDraftByIdentifier(t *testing.T) { + var captured APIRequest + exec := func(req APIRequest) error { captured = req; return nil } + + op := &operationInfo{ + Tag: "Documents", + OperationID: "documentsV2PatchDraftByIdentifier", + Method: "PATCH", + Path: "/api/v2/documents/{identifier}/draft/{draftIdentifier}", + PathParams: []paramInfo{{Name: "identifier", In: "path"}, {Name: "draftIdentifier", In: "path"}}, + HasBody: true, + } + + cmd := buildCommand(op, exec) + cmd.SetArgs([]string{"abc123", "draft456", "--name", "Edited"}) + if err := cmd.Execute(); err != nil { + t.Fatalf("Execute: %v", err) + } + + if !strings.Contains(captured.Path, "abc123") || !strings.Contains(captured.Path, "draft456") { + t.Errorf("path = %q, expected to contain both identifiers", captured.Path) + } + + var body map[string]interface{} + json.Unmarshal(captured.Body, &body) + if body["name"] != "Edited" { + t.Errorf("name = %v, want Edited", body["name"]) + } + if _, exists := body["draftIdentifier"]; exists { + t.Error("path param draftIdentifier should not appear in body") + } +} + // --------------------------------------------------------------------------- // Fallback / alias tests // @@ -614,6 +712,60 @@ func TestShorthand_BothBodyFlagsError(t *testing.T) { } } +// Combining a promoted shorthand flag with --body is an error: the raw body +// is sent verbatim, so a silently-dropped flag (e.g. --branch-id) would +// produce a request the user didn't intend. +func TestShorthand_BodyWithShorthandFlagErrors(t *testing.T) { + exec := func(req APIRequest) error { return nil } + + op := &operationInfo{ + Tag: "Documents", + OperationID: "documentsV2PatchDraft", + Method: "PATCH", + Path: "/api/v2/documents/{identifier}/draft", + PathParams: []paramInfo{{Name: "identifier", In: "path"}}, + HasBody: true, + } + + cmd := buildCommand(op, exec) + cmd.SilenceUsage = true + cmd.SilenceErrors = true + cmd.SetArgs([]string{"doc-123", "--branch-id", "b-1", "--body", `{"name":"x"}`}) + err := cmd.Execute() + if err == nil { + t.Fatal("expected error when --branch-id is combined with --body") + } + if !strings.Contains(err.Error(), "--branch-id") { + t.Errorf("error = %q, want it to name --branch-id", err.Error()) + } +} + +// The conflict check also covers the hidden --json-body alias. +func TestShorthand_JsonBodyWithShorthandFlagErrors(t *testing.T) { + exec := func(req APIRequest) error { return nil } + + op := &operationInfo{ + Tag: "Documents", + OperationID: "documentsV2PatchDraft", + Method: "PATCH", + Path: "/api/v2/documents/{identifier}/draft", + PathParams: []paramInfo{{Name: "identifier", In: "path"}}, + HasBody: true, + } + + cmd := buildCommand(op, exec) + cmd.SilenceUsage = true + cmd.SilenceErrors = true + cmd.SetArgs([]string{"doc-123", "--summary", "s", "--json-body", `{"name":"x"}`}) + err := cmd.Execute() + if err == nil { + t.Fatal("expected error when --summary is combined with --json-body") + } + if !strings.Contains(err.Error(), "--summary") { + t.Errorf("error = %q, want it to name --summary", err.Error()) + } +} + // Verify that --body still works for operations with a shorthand when // the user provides path params + --body but no shorthand positional arg. func TestShorthand_BodyWithPathParams(t *testing.T) { @@ -722,8 +874,8 @@ func TestShorthand_RegistryNotEmpty(t *testing.T) { if len(bodyShorthands) == 0 { t.Fatal("bodyShorthands registry is empty") } - if len(bodyShorthands) != 16 { - t.Errorf("expected 16 shorthand entries, got %d", len(bodyShorthands)) + if len(bodyShorthands) != 19 { + t.Errorf("expected 19 shorthand entries, got %d", len(bodyShorthands)) } } diff --git a/internal/openapi/generate.go b/internal/openapi/generate.go index deaa1f7..2eb218b 100644 --- a/internal/openapi/generate.go +++ b/internal/openapi/generate.go @@ -147,6 +147,13 @@ func extractOperations(pathStr string, item *v3.PathItem, groups map[string][]*o } } + // Positional args follow the URL shape, not the spec's parameters + // array — some endpoints declare path params out of path order. + sort.SliceStable(info.PathParams, func(i, j int) bool { + return strings.Index(pathStr, "{"+info.PathParams[i].Name+"}") < + strings.Index(pathStr, "{"+info.PathParams[j].Name+"}") + }) + // Check for request body if op.RequestBody != nil { info.HasBody = true diff --git a/internal/openapi/generate_test.go b/internal/openapi/generate_test.go index 262d607..c0b8f2d 100644 --- a/internal/openapi/generate_test.go +++ b/internal/openapi/generate_test.go @@ -228,6 +228,54 @@ func TestGenerateCommandsFromSpec(t *testing.T) { } } +// Some endpoints declare path params in the spec's parameters array in a +// different order than they appear in the URL (e.g. the v2 document draft +// routes list draftIdentifier before identifier). Positional args must follow +// the URL shape, so a generated command's arg order matches the path template +// regardless of declaration order. +func TestGenerateCommands_PathParamsFollowPathOrder(t *testing.T) { + spec := `{ + "openapi": "3.1.0", + "info": {"title": "test", "version": "1.0"}, + "paths": { + "/api/v1/things/{outerId}/items/{innerId}": { + "get": { + "operationId": "testGetItem", + "tags": ["test"], + "parameters": [ + {"name": "innerId", "in": "path", "required": true, "schema": {"type": "string"}}, + {"name": "outerId", "in": "path", "required": true, "schema": {"type": "string"}} + ], + "responses": {"200": {"description": "ok"}} + } + } + } + }` + + var captured APIRequest + exec := func(req APIRequest) error { captured = req; return nil } + cmds, err := GenerateCommands([]byte(spec), exec) + if err != nil { + t.Fatalf("GenerateCommands: %v", err) + } + if len(cmds) != 1 || len(cmds[0].Commands()) != 1 { + t.Fatalf("expected 1 tag group with 1 subcommand, got %v", cmds) + } + + sub := cmds[0].Commands()[0] + if sub.Use != "get-item " { + t.Errorf("Use = %q, want %q", sub.Use, "get-item ") + } + + // Positional args in path order must substitute into the matching slots. + if err := sub.RunE(sub, []string{"outer-val", "inner-val"}); err != nil { + t.Fatalf("RunE: %v", err) + } + if captured.Path != "/api/v1/things/outer-val/items/inner-val" { + t.Errorf("path = %q, want %q", captured.Path, "/api/v1/things/outer-val/items/inner-val") + } +} + // --------------------------------------------------------------------------- // Command behavior tests //