openapi: 3.1.0 info: title: Flax API version: "1.0.0" description: > Programmatic REST API for Flax (ADR-0040/0041). Authenticate with a service-account API token (`flax_pat_...`) sent as a Bearer token. Every request is authorized by the token's scopes (`read` / `write`) and the service account's team memberships and row-level security — the API grants no privilege beyond what the account itself has. license: name: Proprietary servers: - url: https://flax-analytics.com description: Your Flax host. Replace with your deployment's origin. tags: - name: Queries description: Compile and run semantic-model queries. - name: Sheets description: Spreadsheet workbooks built on query results. - name: Charts description: Saved visualizations. - name: Dashboards description: Laid-out collections of charts with shared filters. - name: Connections description: Configured warehouse connections. - name: Models description: Semantic projects and their models. - name: Schedules description: Recurring deliveries of dashboards, charts, and datasets. - name: Datasets description: Reusable, governed sources promoted from a query or a sheet selection. - name: Introspection description: Auto-generate a semantic layer from a warehouse schema. - name: Joins description: Declared joins on a git-less semantic layer. - name: Sharing description: Explicit view/edit grants on charts, sheets, and dashboards. - name: Teams description: Teams and their members (for scoping and sharing). - name: Agents description: Scheduled, evidence-grounded LLM agents and their runs. - name: Actions description: Trigger→effect automations and their runs. - name: Identity description: The calling token's identity, org, and scopes. - name: Admin description: Organization members, service accounts, and embed tokens. security: - bearerAuth: [] paths: /api/query: post: tags: [Queries] summary: Run a query description: Compile a semantic-model query to dialect-correct SQL, run it in the warehouse, and return rows. Requires the `read` scope. operationId: runQuery requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/QueryRequest" responses: "200": description: Query results. content: application/json: schema: $ref: "#/components/schemas/QueryResult" "400": { $ref: "#/components/responses/BadRequest" } "401": { $ref: "#/components/responses/Unauthorized" } /api/query/batch: post: tags: [Queries] summary: Run multiple queries description: Run several queries in one round-trip. Requires the `read` scope. operationId: runQueryBatch requestBody: required: true content: application/json: schema: type: object properties: queries: type: array items: { $ref: "#/components/schemas/QueryRequest" } required: [queries] responses: "200": description: One result per query, in request order. content: application/json: schema: type: object properties: results: type: array items: { $ref: "#/components/schemas/QueryResult" } "401": { $ref: "#/components/responses/Unauthorized" } /api/query/detail: post: tags: [Queries] summary: Inspect a compiled query description: Return the compiled SQL and query plan for a query without running it. Requires the `read` scope. operationId: queryDetail requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/QueryRequest" responses: "200": description: Compiled SQL and metadata. content: application/json: schema: type: object properties: sql: { type: string } dialect: { type: string } "401": { $ref: "#/components/responses/Unauthorized" } /api/sheets: get: tags: [Sheets] summary: List sheets operationId: listSheets responses: "200": description: The sheets the account can read. content: application/json: schema: type: array items: { $ref: "#/components/schemas/Sheet" } "401": { $ref: "#/components/responses/Unauthorized" } post: tags: [Sheets] summary: Create a sheet description: Requires the `write` scope. operationId: createSheet requestBody: required: true content: application/json: schema: { $ref: "#/components/schemas/SheetCreate" } responses: "201": description: The created sheet. content: application/json: schema: { $ref: "#/components/schemas/Sheet" } "401": { $ref: "#/components/responses/Unauthorized" } /api/sheets/{sheetId}: get: tags: [Sheets] summary: Get a sheet operationId: getSheet parameters: - $ref: "#/components/parameters/SheetId" responses: "200": description: The sheet. content: application/json: schema: { $ref: "#/components/schemas/Sheet" } "404": { $ref: "#/components/responses/NotFound" } /api/charts: get: tags: [Charts] summary: List charts operationId: listCharts responses: "200": description: The charts the account can read. content: application/json: schema: type: array items: { $ref: "#/components/schemas/Chart" } post: tags: [Charts] summary: Create a chart description: Requires the `write` scope. operationId: createChart requestBody: required: true content: application/json: schema: { $ref: "#/components/schemas/ChartCreate" } responses: "201": description: The created chart. content: application/json: schema: { $ref: "#/components/schemas/Chart" } /api/charts/{chartId}: get: tags: [Charts] summary: Get a chart operationId: getChart parameters: - $ref: "#/components/parameters/ChartId" responses: "200": description: The chart. content: application/json: schema: { $ref: "#/components/schemas/Chart" } "404": { $ref: "#/components/responses/NotFound" } patch: tags: [Charts] summary: Update a chart description: Requires the `write` scope. operationId: updateChart parameters: - $ref: "#/components/parameters/ChartId" requestBody: required: true content: application/json: schema: { $ref: "#/components/schemas/ChartCreate" } responses: "200": description: The updated chart. content: application/json: schema: { $ref: "#/components/schemas/Chart" } /api/dashboards: get: tags: [Dashboards] summary: List dashboards operationId: listDashboards responses: "200": description: The dashboards the account can read. content: application/json: schema: type: array items: { $ref: "#/components/schemas/Dashboard" } post: tags: [Dashboards] summary: Create a dashboard description: Requires the `write` scope. operationId: createDashboard requestBody: required: true content: application/json: schema: { $ref: "#/components/schemas/DashboardCreate" } responses: "201": description: The created dashboard. content: application/json: schema: { $ref: "#/components/schemas/Dashboard" } /api/dashboards/{dashboardId}: get: tags: [Dashboards] summary: Get a dashboard operationId: getDashboard parameters: - $ref: "#/components/parameters/DashboardId" responses: "200": description: The dashboard. content: application/json: schema: { $ref: "#/components/schemas/Dashboard" } "404": { $ref: "#/components/responses/NotFound" } /api/dashboards/{dashboardId}/layout: put: tags: [Dashboards] summary: Set dashboard layout description: Replace a dashboard's tile layout. Requires the `write` scope. operationId: setDashboardLayout parameters: - $ref: "#/components/parameters/DashboardId" requestBody: required: true content: application/json: schema: type: object properties: tiles: type: array items: { $ref: "#/components/schemas/DashboardTile" } required: [tiles] responses: "200": description: The updated dashboard. content: application/json: schema: { $ref: "#/components/schemas/Dashboard" } /api/connections: get: tags: [Connections] summary: List connections operationId: listConnections responses: "200": description: The warehouse connections the account can read. content: application/json: schema: type: array items: { $ref: "#/components/schemas/Connection" } post: tags: [Connections] summary: Create a connection description: Requires the `write` scope and an org-admin service account. Secrets in `fields` are write-only. operationId: createConnection requestBody: required: true content: application/json: schema: { $ref: "#/components/schemas/ConnectionCreate" } responses: "201": description: The created connection (secrets are never returned). content: application/json: schema: { $ref: "#/components/schemas/Connection" } /api/connections/{connectionId}: get: tags: [Connections] summary: Get a connection operationId: getConnection parameters: - $ref: "#/components/parameters/ConnectionId" responses: "200": description: The connection (secrets are never returned). content: application/json: schema: { $ref: "#/components/schemas/Connection" } "404": { $ref: "#/components/responses/NotFound" } /api/projects: get: tags: [Models] summary: List semantic projects operationId: listProjects responses: "200": description: The semantic projects the account can read. content: application/json: schema: type: array items: { $ref: "#/components/schemas/Project" } post: tags: [Models] summary: Create a semantic project description: Requires the `write` scope and an org-admin service account. Leave the git fields empty for a git-less layer built via introspection or declared joins. operationId: createProject requestBody: required: true content: application/json: schema: { $ref: "#/components/schemas/ProjectCreate" } responses: "201": description: The created project. content: application/json: schema: { $ref: "#/components/schemas/Project" } /api/projects/{projectId}/schemas: get: tags: [Introspection] summary: List warehouse schemas description: The schemas available on the project's connection. Requires an org-admin service account. operationId: listSchemas parameters: - $ref: "#/components/parameters/ProjectId" responses: "200": description: The available schema names. content: application/json: schema: type: object properties: schemas: { type: array, items: { type: string } } /api/projects/{projectId}/introspect/preview: post: tags: [Introspection] summary: Preview an auto-generated semantic graph description: >- Generates a candidate graph (models, dimensions, measures) from the warehouse schema WITHOUT saving, plus notes (e.g. text/integer columns detected as dates). Review it, then apply with the confirm endpoint. Requires the `write` scope and an org-admin service account. operationId: introspectPreview parameters: - $ref: "#/components/parameters/ProjectId" requestBody: content: application/json: schema: { $ref: "#/components/schemas/IntrospectRequest" } responses: "200": description: The candidate graph and a generation report. content: application/json: schema: type: object properties: graph: { type: object, description: The generated semantic graph. } report: { type: object, description: Models generated, skipped columns, and notes. } /api/projects/{projectId}/introspect: post: tags: [Introspection] summary: Apply an auto-generated semantic graph description: Persists the reviewed graph so its models become queryable. Requires the `write` scope and an org-admin service account. operationId: introspectConfirm parameters: - $ref: "#/components/parameters/ProjectId" requestBody: content: application/json: schema: { $ref: "#/components/schemas/IntrospectRequest" } responses: "200": description: The sync result. /api/projects/{projectId}/joins: post: tags: [Joins] summary: Declare a join description: >- Adds a join to a git-less layer so a target model's fields become reachable from a base model (as `target.field`). Requires the `write` scope and an org-admin service account. operationId: addJoin parameters: - $ref: "#/components/parameters/ProjectId" requestBody: required: true content: application/json: schema: { $ref: "#/components/schemas/JoinCreate" } responses: "200": description: The updated project graph. /api/projects/{projectId}/models: get: tags: [Models] summary: List models in a project operationId: listModels parameters: - $ref: "#/components/parameters/ProjectId" responses: "200": description: The models (with their dimensions and measures). content: application/json: schema: type: array items: { $ref: "#/components/schemas/Model" } /api/schedules: get: tags: [Schedules] summary: List schedules operationId: listSchedules responses: "200": description: The scheduled deliveries the account can read. content: application/json: schema: type: array items: { $ref: "#/components/schemas/Schedule" } post: tags: [Schedules] summary: Create a schedule description: Requires the `write` scope. operationId: createSchedule requestBody: required: true content: application/json: schema: { $ref: "#/components/schemas/ScheduleCreate" } responses: "201": description: The created schedule. content: application/json: schema: { $ref: "#/components/schemas/Schedule" } /api/schedules/{scheduleId}: get: tags: [Schedules] summary: Get a schedule operationId: getSchedule parameters: - $ref: "#/components/parameters/ScheduleId" responses: "200": description: The schedule. content: application/json: schema: { $ref: "#/components/schemas/Schedule" } "404": { $ref: "#/components/responses/NotFound" } put: tags: [Schedules] summary: Update a schedule description: Requires the `write` scope. Replaces the schedule's fields and resource set. operationId: updateSchedule parameters: - $ref: "#/components/parameters/ScheduleId" requestBody: required: true content: application/json: schema: { $ref: "#/components/schemas/ScheduleCreate" } responses: "204": description: Updated. delete: tags: [Schedules] summary: Delete a schedule description: Requires the `write` scope. operationId: deleteSchedule parameters: - $ref: "#/components/parameters/ScheduleId" responses: "204": description: Deleted. /api/actions: get: tags: [Actions] summary: List actions operationId: listActions responses: "200": description: The actions the account can read. content: application/json: schema: type: array items: { $ref: "#/components/schemas/Action" } /api/actions/{actionId}/runs: get: tags: [Actions] summary: List action runs operationId: listActionRuns parameters: - $ref: "#/components/parameters/ActionId" responses: "200": description: The run history for the action. content: application/json: schema: type: array items: { $ref: "#/components/schemas/ActionRun" } post: tags: [Actions] summary: Trigger an action run description: Requires the `write` scope. operationId: runAction parameters: - $ref: "#/components/parameters/ActionId" responses: "202": description: The run was accepted. content: application/json: schema: { $ref: "#/components/schemas/ActionRun" } /api/orgs/{orgId}/members: get: tags: [Admin] summary: List organization members operationId: listMembers parameters: - $ref: "#/components/parameters/OrgId" responses: "200": description: The members of the organization. content: application/json: schema: type: array items: { $ref: "#/components/schemas/Member" } /api/orgs/{orgId}/service-accounts: get: tags: [Admin] summary: List service accounts operationId: listServiceAccounts parameters: - $ref: "#/components/parameters/OrgId" responses: "200": description: The organization's service accounts. content: application/json: schema: type: array items: { $ref: "#/components/schemas/ServiceAccount" } post: tags: [Admin] summary: Create a service account description: Org-admin only. The API token is returned once at creation. operationId: createServiceAccount parameters: - $ref: "#/components/parameters/OrgId" requestBody: required: true content: application/json: schema: type: object properties: name: { type: string } scopes: type: array items: { type: string, enum: [read, write] } required: [name, scopes] responses: "201": description: The service account and its one-time token. content: application/json: schema: type: object properties: serviceAccount: { $ref: "#/components/schemas/ServiceAccount" } token: { type: string, description: "The `flax_pat_...` token — shown only once." } /api/orgs/{orgId}/embed-tokens: post: tags: [Admin] summary: Mint an embed token description: Org-admin only. Mints a token scoped to one chart or dashboard for embedding. operationId: createEmbedToken parameters: - $ref: "#/components/parameters/OrgId" requestBody: required: true content: application/json: schema: type: object properties: resourceType: { type: string, enum: [chart, dashboard] } resourceId: { type: string } required: [resourceType, resourceId] responses: "201": description: The embed token (shown once). content: application/json: schema: type: object properties: token: { type: string } /api/whoami: get: tags: [Identity] summary: Identify the calling token description: The token's user, org (tenant), org role, seat, scopes, and team memberships. PAT-accessible (unlike /api/me). operationId: whoami responses: "200": description: The caller's identity. content: application/json: schema: { $ref: "#/components/schemas/WhoAmI" } /api/schedules/{scheduleId}/run: post: tags: [Schedules] summary: Run a schedule now description: Fires the delivery immediately (a manual test send) without changing its cadence. Requires the `write` scope; the owner, or an org admin / team lead for a scoped delivery. operationId: runSchedule parameters: - $ref: "#/components/parameters/ScheduleId" responses: "200": description: Delivered. /api/datasets: get: tags: [Datasets] summary: List datasets operationId: listDatasets responses: "200": description: The datasets the account can read. content: application/json: schema: type: array items: { $ref: "#/components/schemas/Dataset" } /api/datasets/{datasetId}: get: tags: [Datasets] summary: Get a dataset operationId: getDataset parameters: - $ref: "#/components/parameters/DatasetId" responses: "200": description: The dataset. content: application/json: schema: { $ref: "#/components/schemas/Dataset" } "404": { $ref: "#/components/responses/NotFound" } delete: tags: [Datasets] summary: Delete a dataset description: Requires the `manage` scope. Blocked with 409 while a chart still references it. operationId: deleteDataset parameters: - $ref: "#/components/parameters/DatasetId" responses: "204": description: Deleted. "409": description: The dataset is still in use by a chart. content: application/json: schema: { $ref: "#/components/schemas/Error" } /api/datasets/{datasetId}/usage: get: tags: [Datasets] summary: Dataset usage (lineage) description: The charts and dashboards that reference this dataset. operationId: datasetUsage parameters: - $ref: "#/components/parameters/DatasetId" responses: "200": description: The lineage. /api/projects/{projectId}/datasets: get: tags: [Datasets] summary: List a project's datasets operationId: listProjectDatasets parameters: - $ref: "#/components/parameters/ProjectId" responses: "200": description: The datasets in the project. content: application/json: schema: type: array items: { $ref: "#/components/schemas/Dataset" } post: tags: [Datasets] summary: Create a dataset description: Requires the `write` scope. `kind` is `live` (a recompiled query in `definition`) or `snapshot` (frozen values in `snapshotCsv`). operationId: createDataset parameters: - $ref: "#/components/parameters/ProjectId" requestBody: required: true content: application/json: schema: { $ref: "#/components/schemas/DatasetCreate" } responses: "201": description: The created dataset. content: application/json: schema: { $ref: "#/components/schemas/Dataset" } /api/grants: get: tags: [Sharing] summary: List grants on a resource operationId: listGrants parameters: - { name: resourceType, in: query, required: true, schema: { type: string, enum: [chart, sheet, dashboard] } } - { name: resourceId, in: query, required: true, schema: { type: string } } responses: "200": description: The grants on the resource. content: application/json: schema: type: object properties: grants: { type: array, items: { $ref: "#/components/schemas/Grant" } } post: tags: [Sharing] summary: Create a grant description: >- Share a chart/sheet/dashboard with a team or a person. Requires the `write` scope and org-admin or the owning team's lead. For a dashboard, set `cascadeChartsPermission` to also grant its underlying charts (else the recipient sees empty tiles). operationId: createGrant requestBody: required: true content: application/json: schema: { $ref: "#/components/schemas/GrantCreate" } responses: "201": description: The created grant (plus a cascade summary for dashboards). /api/grants/{grantId}: delete: tags: [Sharing] summary: Revoke a grant description: Requires the `manage` scope. operationId: deleteGrant parameters: - $ref: "#/components/parameters/GrantId" - { name: resourceType, in: query, required: true, schema: { type: string } } - { name: resourceId, in: query, required: true, schema: { type: string } } responses: "200": description: Revoked. /api/orgs/{orgId}/teams: get: tags: [Teams] summary: List teams operationId: listTeams parameters: - $ref: "#/components/parameters/OrgId" responses: "200": description: The org's teams. content: application/json: schema: type: object properties: teams: { type: array, items: { $ref: "#/components/schemas/Team" } } /api/agents: get: tags: [Agents] summary: List agents operationId: listAgents responses: "200": description: The org's scheduled AI agents. content: application/json: schema: type: array items: { $ref: "#/components/schemas/Agent" } post: tags: [Agents] summary: Create an agent description: Requires the `write` scope and an org-admin service account. Each run spends LLM tokens against the org budget. operationId: createAgent requestBody: required: true content: application/json: schema: { $ref: "#/components/schemas/AgentCreate" } responses: "201": description: The created agent. content: application/json: schema: { $ref: "#/components/schemas/Agent" } /api/agents/{agentId}: get: tags: [Agents] summary: Get an agent operationId: getAgent parameters: - $ref: "#/components/parameters/AgentId" responses: "200": description: The agent. content: application/json: schema: { $ref: "#/components/schemas/Agent" } "404": { $ref: "#/components/responses/NotFound" } put: tags: [Agents] summary: Update an agent description: Requires the `write` scope. operationId: updateAgent parameters: - $ref: "#/components/parameters/AgentId" requestBody: required: true content: application/json: schema: { $ref: "#/components/schemas/AgentCreate" } responses: "200": description: The updated agent. content: application/json: schema: { $ref: "#/components/schemas/Agent" } delete: tags: [Agents] summary: Delete an agent description: Requires the `manage` scope. Removes the agent and its run history. operationId: deleteAgent parameters: - $ref: "#/components/parameters/AgentId" responses: "204": description: Deleted. /api/agents/{agentId}/active: patch: tags: [Agents] summary: Pause or resume an agent description: Requires the `write` scope. operationId: setAgentActive parameters: - $ref: "#/components/parameters/AgentId" requestBody: required: true content: application/json: schema: type: object properties: { active: { type: boolean } } required: [active] responses: "204": description: Updated. /api/agents/{agentId}/run: post: tags: [Agents] summary: Run an agent now description: Runs the agent asynchronously and returns a runId. Requires the `write` scope. Spends LLM tokens against the org budget. operationId: runAgent parameters: - $ref: "#/components/parameters/AgentId" responses: "202": description: The run was queued. content: application/json: schema: type: object properties: { runId: { type: string } } /api/agents/{agentId}/runs: get: tags: [Agents] summary: List an agent's runs operationId: listAgentRuns parameters: - $ref: "#/components/parameters/AgentId" responses: "200": description: The agent's recent runs and outputs. content: application/json: schema: type: array items: { $ref: "#/components/schemas/AgentRun" } components: securitySchemes: bearerAuth: type: http scheme: bearer bearerFormat: flax_pat description: "A service-account API token, e.g. `Authorization: Bearer flax_pat_...`." parameters: SheetId: name: sheetId in: path required: true schema: { type: string } ChartId: name: chartId in: path required: true schema: { type: string } DashboardId: name: dashboardId in: path required: true schema: { type: string } ConnectionId: name: connectionId in: path required: true schema: { type: string } ProjectId: name: projectId in: path required: true schema: { type: string } ScheduleId: name: scheduleId in: path required: true schema: { type: string } ActionId: name: actionId in: path required: true schema: { type: string } OrgId: name: orgId in: path required: true schema: { type: string } DatasetId: name: datasetId in: path required: true schema: { type: string } GrantId: name: grantId in: path required: true schema: { type: string } AgentId: name: agentId in: path required: true schema: { type: string } responses: BadRequest: description: The request was invalid. content: application/json: schema: { $ref: "#/components/schemas/Error" } Unauthorized: description: Missing or invalid token, or insufficient scope. content: application/json: schema: { $ref: "#/components/schemas/Error" } NotFound: description: The resource does not exist or is not visible to the account. content: application/json: schema: { $ref: "#/components/schemas/Error" } schemas: Error: type: object description: The standard error envelope returned by every endpoint on failure. properties: error: type: object properties: code: { type: string, description: "Stable machine-readable code, e.g. `invalid_argument`." } message: { type: string, description: "Human-readable message." } category: { type: string, description: "Coarse class, e.g. `validation`, `auth`, `not_found`, `internal`." } requestId: { type: string, description: "Correlation id for support/log lookup." } required: [code, message] required: [error] QueryRequest: type: object properties: model: { type: string, description: "The semantic model to query." } dimensions: type: array items: { type: string } measures: type: array items: { type: string } filters: type: array items: { $ref: "#/components/schemas/QueryFilter" } orderBy: type: array items: { type: string } limit: { type: integer } required: [model] QueryFilter: type: object properties: field: { type: string } op: { type: string } value: {} required: [field, op] QueryResult: type: object properties: columns: type: array items: type: object properties: name: { type: string } type: { type: string } rows: type: array items: type: array items: {} Sheet: type: object properties: id: { type: string } name: { type: string } createdAt: { type: string, format: date-time } SheetCreate: type: object properties: name: { type: string } required: [name] Chart: type: object properties: id: { type: string } name: { type: string } type: { type: string, description: "Chart type, e.g. `bar`, `line`, `waterfall`." } query: { $ref: "#/components/schemas/QueryRequest" } ChartCreate: type: object properties: name: { type: string } type: { type: string } query: { $ref: "#/components/schemas/QueryRequest" } required: [name, type, query] Dashboard: type: object properties: id: { type: string } name: { type: string } tiles: type: array items: { $ref: "#/components/schemas/DashboardTile" } DashboardCreate: type: object properties: name: { type: string } required: [name] DashboardTile: type: object properties: chartId: { type: string } x: { type: integer } y: { type: integer } w: { type: integer } h: { type: integer } Connection: type: object properties: id: { type: string } name: { type: string } driver: { type: string, enum: [postgres, snowflake, databricks, bigquery] } Project: type: object properties: id: { type: string } name: { type: string } Model: type: object properties: name: { type: string } dimensions: type: array items: { type: string } measures: type: array items: { type: string } Schedule: type: object properties: id: { type: string } resourceType: { type: string, enum: [chart, dashboard] } resourceId: { type: string } cron: { type: string } recipients: type: array items: { type: string, format: email } ScheduleCreate: type: object properties: resourceType: { type: string, enum: [chart, dashboard] } resourceId: { type: string } cron: { type: string } recipients: type: array items: { type: string, format: email } required: [resourceType, resourceId, cron, recipients] Action: type: object properties: id: { type: string } name: { type: string } trigger: { type: string } ActionRun: type: object properties: id: { type: string } actionId: { type: string } status: { type: string, enum: [pending, running, succeeded, failed] } startedAt: { type: string, format: date-time } Member: type: object properties: id: { type: string } email: { type: string, format: email } role: { type: string } ServiceAccount: type: object properties: id: { type: string } name: { type: string } scopes: type: array items: { type: string, enum: [read, write] } WhoAmI: type: object properties: userId: { type: string } orgId: { type: string } orgRole: { type: string, enum: [admin, member] } seatType: { type: string, enum: [editor, viewer] } tokenId: { type: string, description: Empty for a cookie session. } scopes: type: array items: { type: string, enum: [read, write, manage] } teams: type: array items: type: object properties: id: { type: string } role: { type: string, enum: [lead, member, viewer] } Dataset: type: object properties: id: { type: string } name: { type: string } slug: { type: string, description: The model name a chart references. } kind: { type: string, enum: [live, snapshot] } projectId: { type: string } visibility: { type: string, enum: [private, team, org] } DatasetCreate: type: object required: [name, kind] properties: name: { type: string } kind: { type: string, enum: [live, snapshot] } connectionId: { type: string } definition: { type: object, description: "For kind 'live': an exploration (the recompiled query)." } snapshotCsv: { type: string, description: "For kind 'snapshot': the frozen grid as CSV." } teamId: { type: string } visibility: { type: string, enum: [private, team, org] } Grant: type: object properties: id: { type: string } resourceType: { type: string, enum: [chart, sheet, dashboard] } resourceId: { type: string } granteeTeamId: { type: string } granteeUserId: { type: string } permission: { type: string, enum: [view, edit] } GrantCreate: type: object required: [resourceType, resourceId, permission] properties: resourceType: { type: string, enum: [chart, sheet, dashboard] } resourceId: { type: string } granteeTeamId: { type: string, description: Mutually exclusive with granteeUserId. } granteeUserId: { type: string } permission: { type: string, enum: [view, edit] } cascadeChartsPermission: type: string enum: [view, edit] description: Dashboards only — also grant the dashboard's charts at this permission. Team: type: object properties: id: { type: string } name: { type: string } role: { type: string, enum: [lead, member, viewer], description: The caller's role in the team. } ConnectionCreate: type: object required: [type, name, fields] properties: type: { type: string, enum: [postgres, snowflake, bigquery, databricks, duckdb] } name: { type: string } fields: type: object additionalProperties: { type: string } description: Connection details incl. write-only secrets (e.g. Postgres host/port/database/user/password/sslmode). ProjectCreate: type: object required: [name] properties: name: { type: string } connectionId: { type: string } defaultSchema: { type: string } gitUrl: { type: string } gitBranch: { type: string } gitSubdir: { type: string } gitToken: { type: string } IntrospectRequest: type: object properties: includeViews: { type: boolean } inferJoins: { type: boolean, description: Read FK constraints to infer joins. } graph: { type: object, description: On confirm, the reviewed/edited graph to persist. } JoinCreate: type: object required: [baseModel, target, baseKey, targetKey] properties: baseModel: { type: string } target: { type: string, description: The model to join in. } type: { type: string, enum: [left, inner, right, full] } relationship: { type: string, enum: [many_to_one, one_to_many, many_to_many] } baseKey: { type: string } targetKey: { type: string } Agent: type: object properties: id: { type: string } name: { type: string } instructions: { type: string } model: { type: string } active: { type: boolean } visibility: { type: string, enum: [private, team, org] } AgentCreate: type: object required: [name, instructions, cadence] properties: name: { type: string } instructions: { type: string, description: The task prompt for each run. } provider: { type: string } model: { type: string } grounding: type: array description: Resources the run may read as evidence. items: type: object properties: type: { type: string, enum: [dashboard, chart, dataset, sheet] } id: { type: string } vision: { type: boolean } cadence: { $ref: "#/components/schemas/Cadence" } outputs: type: array items: { type: object } maxRounds: { type: integer } maxTokensPerRun: { type: integer } teamId: { type: string } visibility: { type: string, enum: [private, team, org] } AgentRun: type: object properties: id: { type: string } agentId: { type: string } status: { type: string, enum: [pending, running, succeeded, failed] } startedAt: { type: string, format: date-time } inputTokens: { type: integer } outputTokens: { type: integer } Cadence: type: object required: [frequency] properties: frequency: { type: string, enum: [hourly, daily, weekly] } minute: { type: integer, minimum: 0, maximum: 59 } hour: { type: integer, minimum: 0, maximum: 23 } weekday: { type: integer, minimum: 0, maximum: 6, description: 0=Sunday. } timeZone: { type: string, description: IANA name; empty = UTC. }