diff --git a/_docs/master/README.md b/_docs/master/README.md index 7e1358199e..1d254d88e4 100644 --- a/_docs/master/README.md +++ b/_docs/master/README.md @@ -159,8 +159,13 @@ Metabase's reference documentation. - [AI overview](./ai/start) - [Metabot](./ai/metabot) - [AI settings](./ai/settings) +- [AI usage controls](./ai/usage-controls) +- [AI usage auditing](./ai/usage-auditing) +- [AI customization](./ai/customization) +- [AI system prompts](./ai/system-prompts) - [Agent API](./ai/agent-api) - [MCP server](./ai/mcp) +- [Metabot in Slack](./ai/metabot-slack) ### Exploration and organization diff --git a/_docs/master/ai/agent-api.md b/_docs/master/ai/agent-api.md index efea43ae21..04b714525a 100644 --- a/_docs/master/ai/agent-api.md +++ b/_docs/master/ai/agent-api.md @@ -12,7 +12,13 @@ summary: 'The Agent API is a REST API for building headless, agentic BI applicat # Agent API -The [Agent API](../api#tag/apiagent) is a REST API for building headless, agentic BI applications on top of Metabase's semantic layer, scoped to an authenticated user's permissions. +The [Agent API](../api#tag/apiagent) is a REST API for building headless, agentic BI applications on top of Metabase's semantic layer, scoped to an authenticated user's permissions. Agent API powers Metabase's MCP server. + +## Enable Agent API + +_Admin > AI > MCP_ + +Admins enable the Agent API under **Admin > AI > MCP**. ## Agent API endpoints and reference diff --git a/_docs/master/ai/customization.md b/_docs/master/ai/customization.md new file mode 100644 index 0000000000..03b39d4fd0 --- /dev/null +++ b/_docs/master/ai/customization.md @@ -0,0 +1,49 @@ +--- +version: master +has_magic_breadcrumbs: true +show_category_breadcrumb: true +show_title_breadcrumb: true +category: Ai +title: 'AI customization' +source_url: 'https://github.com/metabase/metabase/blob/master/docs/ai/customization.md' +layout: new-docs +summary: 'Change how Metabot appears in Metabase for a branded look.' +--- + +# AI customization + +{% include plans-blockquote.html feature="AI customization" %} + +_Admin > AI > Customization_ + +Admins can change how Metabot displays itself in Metabase. + +To navigate to the AI customization settings: + +1. Click the **grid** icon in the upper right. +2. Click **Admin**. +3. Go to the **AI** tab. +4. Click on the **Customization** tab. + +These customizations are just surface-level. If you want to change the AI's behavior, check out [System prompts](./system-prompts). + +## Metabot's name + +Rename Metabot. The new name shows up everywhere Metabase refers to Metabot (sidebar, buttons, suggested prompts, empty states). + +## Metabot's icon + +Upload a custom icon. SVG or PNG with a transparent background gives the cleanest result. Max size is 1MB. + +## Show Metabot illustrations + +![Metabot illustrations](./images/metabot-illustrations.png) + +Once you've uploaded a custom icon, this toggle appears and controls whether the default decorative illustrations show in the Metabot chat sidebar and on the AI exploration page. + +## Further reading + +- [AI settings](./settings) +- [AI usage controls](./usage-controls) +- [AI system prompts](./system-prompts) +- [Metabot](./metabot) diff --git a/_docs/master/ai/file-based-development.md b/_docs/master/ai/file-based-development.md index c5fc0e97f9..1341711b45 100644 --- a/_docs/master/ai/file-based-development.md +++ b/_docs/master/ai/file-based-development.md @@ -4,172 +4,220 @@ has_magic_breadcrumbs: true show_category_breadcrumb: true show_title_breadcrumb: true category: Ai -title: 'File-based development' +title: 'Agent-driven development' source_url: 'https://github.com/metabase/metabase/blob/master/docs/ai/file-based-development.md' layout: new-docs -summary: 'Use a combination of agent skills, the Metabase MCP server, and serialization to develop Metabase content with agents on your local file system.' +summary: 'Use an agent with skills to create Metabase content on your local machine as YAML files, then upload the files to your Metabase.' --- -# File-based development +# Agent-driven development -{% include plans-blockquote.html feature="File-based development" %} +{% include plans-blockquote.html feature="Agent-driven development" %} -Metabase content like questions and dashboards can be serialized as YAML files. You can edit those YAML files directly, but the most productive workflow is to let an agent do the editing for you — this article focuses on that agent-driven workflow. +Metabase content like questions and dashboards can be serialized as YAML files. You can edit those YAML files by hand, sure, but now that we have actual genies, you can just ask them to edit them for you (call it "lamp-rubbing development"). -## The file-based toolkit +Paired with some skills we've developed, you can export your Metabase as YAML files, ask your agent to create new questions and dashboards YAML files, then import that new content into your Metabase. It's a whole new way to work with Metabase. -We provide a set of tools for using an AI agent to create and edit Metabase content [serialized](../installation-and-operation/serialization) as YAML files. +## The agent-driven development toolkit -- The [Metabase Representation Format](https://github.com/metabase/representations). This is a directory that includes a spec, schemas, and examples for all Metabase entities as YAML files: questions, dashboards, and so on. -- The [`metabase-representation-format` agent skill](https://github.com/metabase/agent-skills) for working with these YAML files. -- CLI commands and API endpoints to export and import content serialized in YAML. -- [MCP server](./mcp) to look up database metadata when creating the YAML files. +To develop your Metabase content on your local filesystem, we've put together a set of tools, including a set of agent skills. -## Prerequisites +- [**Metabase Representation Format**](https://github.com/metabase/representations): the YAML schema and spec for every Metabase entity (questions, dashboards, collections, transforms, and so on). +- **[Metabase Database Metadata Format](https://github.com/metabase/database-metadata)**: diff-friendly representations of synced databases, their tables, and their fields, as a tree of YAML files. +- **Export and Import** CLI and API endpoints to move serialized content between your local files and Metabase. +- [**Remote Sync**](../installation-and-operation/remote-sync) (Optional): push content from a Read-write Metabase into a git repo, and pull it into a Read-only Metabase in production. + +## How content moves between files and Metabase + +You'll need a way to get YAML files out of Metabase to edit and back into Metabase to verify and ship. There are two options: + +- **[Remote Sync](../installation-and-operation/remote-sync)** — push and pull from inside Metabase. Requires a Read-write development instance and a Read-only production instance. +- **Serialization API** — `curl`-based export and import against the `/api/ee/serialization/` endpoints. + +Pick one before you start the [Initial setup](#initial-setup); the setup steps differ slightly (Remote Sync doesn't need a separate API key in production). + +## Initial setup + +Some things to put into place to get a workflow going: + +1. [Set up a development Metabase](#set-up-a-development-metabase) +2. [Set up a repository to version your YAML files](#set-up-a-repository-to-version-your-yaml-files) +3. [Add agent skills to your repository](#add-agent-skills-to-your-repository) +4. [Download the database metadata](#download-the-database-metadata) + +Once you have these set up, you can step through one of the example workflows. ### Set up a development Metabase -Set up a Metabase instance to check your work before pushing changes to production. This Metabase should connect to the same data warehouse(s) your production Metabase connects to. A [config file](../configuring-metabase/config-file) will come in handy here. +1. Set up a Metabase instance to check your work before pushing changes to production. This Metabase should connect to the same data warehouse(s) your production Metabase connects to. A [config file](../configuring-metabase/config-file) will come in handy here. + +2. Create an [API key](../people-and-groups/api-keys#create-an-api-key) and assign it to the Admin group. The skills export and import all content and read database metadata, so they need Admin-level access. If you're using the [Serialization API workflow](#how-content-moves-between-files-and-metabase), you'll also need to create an API key in your production Metabase so you can import your files into it. + +3. We also recommend turning off the sample content and usage analytics, so they don't pollute the data model. If you're using a [docker compose file](../installation-and-operation/running-metabase-on-docker), add these [environment variables](../configuring-metabase/environment-variables): -We also recommend turning off the sample content and usage analytics, so they don't pollute the data model. If you're using a [docker compose file](../installation-and-operation/running-metabase-on-docker), add these [environment variables](../configuring-metabase/environment-variables): ``` MB_LOAD_SAMPLE_CONTENT: "false" MB_INSTALL_ANALYTICS_DATABASE: "false" ``` -### For agent-driven development +### Set up a repository to version your YAML files + +1. Initialize a new repo. +2. Add a `.gitignore` file and add `.metabase/` and `.env`. +3. Add the following to your `.env`: + +``` + METABASE_URL={your-metabase-url} + METABASE_API_KEY={your-api-key} +``` + +### Add agent skills to your repository -If you want an agent to do the editing, you also need: +You should add the following skills to your agent so it has context it needs. If you commit the skills into `.claude/skills/` in your repo, for example, Claude loads them automatically whenever you run it from that directory. -1. **The `metabase-representation-format` skill added to your agent** so the agent understands the YAML schemas. See [Agent skills](https://github.com/metabase/agent-skills). +- [**`metabase-representation-format` agent skill**](https://github.com/metabase/agent-skills/blob/main/skills/metabase-representation-format/SKILL.md): teaches the agent the representation format and ships the schema checker. +- [**`metabase-database-metadata` agent skill**](https://github.com/metabase/agent-skills/blob/main/skills/metabase-database-metadata/SKILL.md): fetches database metadata from your Metabase into an on-disk YAML tree the agent can read while editing. +- [**`metabase-semantic-checker` agent skill**](https://github.com/metabase/agent-skills/blob/main/skills/metabase-semantic-checker/SKILL.md) (optional): runs Metabase's semantic checker in Docker to catch referential and query errors the schema check doesn't. -2. **Your agent connected to your Metabase's MCP server**, so it can look up database metadata (table names, fields, and sample values) when writing questions and dashboards. The MCP server exposes tools like `search`, `get_table`, and `get_table_field_values`. See [MCP server](./mcp). +### Download the database metadata -## Example agent-driven workflow +Invoke the `metabase-database-metadata` skill and ask your agent to fetch the database metadata. The agent will: -Here's an example workflow for using an agent to create Metabase content as YAML on your local machine, then importing that content into your development and production Metabases. +- Check that `.env` exists. If it doesn't, the agent will prompt you to create it. +- Verify that `.env` and `.metabase/` are in `.gitignore`, asking before adding them. +- Fetch `/api/database/metadata` into `.metabase/metadata.json` (raw API response; can be several GB on large warehouses). +- Extract a diff-friendly YAML tree to `.metabase/databases//schemas//tables/.yaml` by running `npx @metabase/database-metadata extract-metadata`. -### 1. Create a git repo +The agent can use the YAML extracted to your `.metabase` directory while creating and editing new questions and dashboards in YAML. That way your agent can refer to real column names, field types, and foreign-key relationships without making live API calls (which would be much slower). -Initialize a git repo with a README.md and an initial commit. +To refresh this database metadata, just ask your agent to re-fetch it. -### 2. Check out a branch +## Example workflows -Create a new branch to track your work. +The workflows below both assume you've completed the [Initial setup](#initial-setup). + +### Example prompts + +Once your repo has the agent skills and a baseline of content, prompt the agent with a structured request: ``` -git checkout -b your-branch-name +Use the metabase-representation-format and metabase-database-metadata skills to create new YAML files in this directory: + +1. Create a new dashboard called "Support overview" in collections/main/. +2. Add questions showing total ticket volume, open tickets, and average satisfaction rating. ``` -### 3. Export your production Metabase +Or, depending on how capable your model is, try a more open-ended request: -Always export before editing YAML files locally. If someone has updated a dashboard or question in the Metabase UI since your last export, and you edit and import stale local files, the import will overwrite those in-app changes. Re-export at the start of each editing session if the app may have changed since your last export. +``` +Use the metabase-representation-format and metabase-database-metadata skills to analyze our support data. Look at the tickets, customers, and interactions tables, and create a dashboard that gives an overview of our team's support workload. +``` + +The agent will read the representation format spec, check existing files for local conventions, consult `.metabase/databases/` for real column names, and write new YAML. -Your agent will also read these serialized YAML files to find info about existing content, so the agent can know what you mean when you ask it to "add the new question to the Handsome collection." +## Example workflow with Remote Sync -To export your Metabase: +### 1. Configure Remote Sync on both instances -1. Create an [API key](../people-and-groups/api-keys). -2. Assign the key to the Admin group. -3. Send a `curl` request to export data: +In your development Metabase, configure [Remote Sync in Read-write mode](../installation-and-operation/remote-sync#setting-up-remote-sync) pointed at your repo. In production, configure a second Metabase in Read-only mode pointed at the same repo. - ```sh - curl \ - -H 'X-API-Key: YOUR_API_KEY' \ - -X POST 'https://your-metabase-url/api/ee/serialization/export?data_model=false' \ - -o metabase_data.tgz - ``` +### 2. Create a branch from the Metabase UI - substituting `YOUR_API_KEY` with your API key and `your-metabase-url` with the URL of your Metabase instance. +Switch branches in Metabase, as the Metabase UI is the source of truth for which branch the development instance pushes to and pulls from. - Be sure to set the `data_model=false` query parameter excludes the data model from the export, since the data model payload can be large. Instead, your agent will use the MCP server to search for the metadata it needs to generate the YAML files. See [Serialization](../installation-and-operation/serialization) for other export options. +In your development Metabase, click the **branch dropdown** at the top and [create a new branch](../installation-and-operation/remote-sync#creating-a-branch) for your work, like `feature/support-dashboard`. - This command will download the files as a GZIP-compressed Tar file named `metabase_data.tgz`. +### 3. Push existing content to seed the repo -4. Extract the archive: +Click the up arrow (**push**) icon to [commit and push](../installation-and-operation/remote-sync#committing-and-pushing-your-changes) your existing synced collections to the branch. - ```sh - tar -xzf metabase_data.tgz - ``` +### 4. Clone the repo locally and check out the branch -Instead of running this `curl` by hand every time, you can ask your agent to generate an `export.sh` script that wraps the `curl` and the `tar -xzf` extraction, so you can re-export with a single command. +```sh +git clone your-metabase-repo +cd your-metabase-repo +git checkout feature/support-dashboard +``` -### 4. Commit the export +### 5. Ask the agent to edit or create content -Commit the initial exported set of YAML files. If your AI goes off the rails, you can always revert to the original export. +See [Example prompts](#example-prompts) above for prompt patterns to use here. -### 5. Use AI to edit or create new content +### 6. Validate the YAML files -Change into the directory with your serialized files and ask your agent to create whatever you want. Make sure your agent actually invokes the skills, otherwise the agent may not get the YAML format right. +Run the [schema check](#schema-check) after every batch of edits, and optionally run the [semantic check](#semantic-checker-for-deeper-validation) at the end of the session. See [Validating YAML files](#validating-yaml-files) below. -Example prompt: +If anything fails, the agent should be able to fix the issue if you give it the error. -``` -Use the metabase-representation-format skill and the Metabase MCP server to do the following by editing the YAML files in this directory: +### 7. Commit and open a pull request -1. Create a new collection called "File-based collection". -2. Create a new dashboard called "AI-created dashboard", saved to that collection. -3. Create a question called "AI counts products" that counts the number of products by category. -4. Add that question to the "AI-created dashboard". +```sh +git add -A +git commit -m "Add support-overview dashboard" +git push origin feature/support-dashboard ``` -Depending on how sophisticated your AI model is, you can also try more ambitious, open-ended requests: +Open a pull request so your team can review the YAML diff. -``` -Use the metabase-representation-format skill and the Metabase MCP server to analyze the data in the sample postgresql -database. Look at the orders, people, reviews, and products tables. +### 8. Pull the branch into your development Metabase -Create a dashboard with some questions that gives an overview of how the business is doing. -``` +Click the **pull** (down arrow) icon in your development Metabase to load the agent's changes. Verify the dashboard renders correctly and the questions return expected results. -### 6. Validate the YAML files +### 9. Merge the PR so production picks up the changes -Before importing, check your YAML files against the representation schemas. The `metabase-representation-format` skill should have the agent run the validator for you, but you can also run it yourself: +If you've enabled [auto-sync](../installation-and-operation/remote-sync#pulling-changes-automatically), your production Metabase (in Read-only mode) will pull the new main branch automatically on its next interval. Otherwise, trigger a pull from production manually. -``` -npx --yes @metabase/representations validate-schema +## Example workflow with import and export endpoints + +### 1. Clone the empty repo and create a branch + +```sh +git clone https://github.com/your-org/your-repo.git +cd your-repo +git checkout -b feature/support-dashboard ``` -You can also set up a workflow to run the validator on pull requests. Here's an example, saved to `.github/workflows/schema-check.yml`: +### 2. Export existing content to seed the repo -```yaml -name: Schema Check +The agent does better work when the repo already holds your current Metabase content, so it can see real examples of the Representation Format and your collection conventions. Run the [serialization export](../installation-and-operation/serialization#serialization-workflow-example) from inside the clone: -on: - push: - branches: [main] - pull_request: +```sh +curl \ + -H 'X-API-Key: YOUR_API_KEY' \ + -X POST 'https://your-metabase-url/api/ee/serialization/export?data_model=false' \ + -o metabase_data.tgz +tar -xzf metabase_data.tgz +``` -jobs: - schema-check: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 +Set `data_model=false` to keep the export small. The agent should get its metadata from the `metabase-database-metadata` skill instead. For more on export options, see [Serialization](../installation-and-operation/serialization). - - uses: actions/setup-node@v4 - with: - node-version: "20" +Commit the extracted YAML so you have a baseline to revert to if the agent goes off the rails. - - name: Validate representation YAML files - run: npx --yes @metabase/representations validate-schema -``` +### 3. Ask the agent to edit or create content -That way your team catches schema issues on the PR, before anyone imports the changes into Metabase. +See [Example prompts](#example-prompts) above for prompt patterns to use here. -### 7. Import the changes to your development Metabase +### 4. Validate the YAML files -Import your changes to your development Metabase, and check that the import works and the content is as expected. +Run the [schema check](#schema-check) after every batch of edits, and optionally run the [semantic check](#semantic-checker-for-deeper-validation) at the end of the session. See [Validating YAML files](#validating-yaml-files) below. -First, compress your directory of YAML files: +### 5. Commit and open a pull request -``` -tar -czf metabase_data.tgz metabase_data +```sh +git add -A +git commit -m "Add support-overview dashboard" +git push origin feature/support-dashboard ``` -Then import that compressed file: +Then open open a pull request so your team can review the YAML diff. -``` +### 6. Import the YAML into your development Metabase + +Re-bundle the YAML and import it: + +```sh +tar -czf metabase_data.tgz metabase_data curl -X POST \ -H 'X-API-Key: YOUR_API_KEY' \ -F 'file=@metabase_data.tgz' \ @@ -177,34 +225,109 @@ curl -X POST \ -o - ``` -The `-o -` flag writes the import response to stdout, so you can see whether the import succeeded and check any warnings. +The `-o -` flag writes the import response to stdout, so you can see whether the import succeeded and check any warnings. You can ask the agent to generate `export.sh` and `import.sh` wrappers so you're running a single command each time. + +Verify the dashboard renders correctly and the questions return expected results. + +### 7. Repeat the import against production + +Once you're confident in the changes, run the same `tar` + `curl` import against your production Metabase, using its API key. + +## Undoing the agent's changes + +If you want to undo the agent's changes, use `git` to revert your YAML files to the last known-good commit before pushing or re-importing. + +If you're using Remote Sync, don't try to fix things by re-pushing from Metabase: Metabase's push only reflects its current state and won't delete any new files the agent created locally. + +## Validating YAML files + +Run both checks locally before pushing. The same checks belong in CI — see [CI example](#ci-example) below. + +### Schema check + +You can run a quick schema check: + +```sh +npx --yes @metabase/representations validate-schema +``` + +The check validates the shape of every YAML file against the Representation Format spec. The `metabase-representation-format` skill should run this check for you automatically after the agent makes any edits. -Just like with export, you can ask your agent to generate an `import.sh` script that handles the `tar -czf` compression and the `curl` in one shot. +### Semantic checker for deeper validation -Log in to this Metabase and check that the changes are as you expect. +> The semantic checker is only available in the Pro/Enterprise plans. -#### Did your AI go off the rails? +The **semantic checker** catches things like references to tables that don't exist or columns the agent invented. -If you want to undo the agent's changes, use `git` to revert your YAML files to the last known-good commit. Don't try to undo the changes by re-exporting from your production Metabase: re-exporting will overwrite edits you made to existing files, but it _won't_ delete any new files the agent created, so your directory will still contain those unwanted files. +What it validates beyond schema: -### 8. Commit your changes +- Cross-entity references: `collection_id`, `dashboard_id`, `parent_id`, snippet names, transform tags, card embeddings. +- MBQL query compilation: `source-table`, field references, joins, segments, measures, expressions. +- Native-query references: tables, columns, and snippets named in SQL. -If all looks good, commit your changes. If you get any errors, give the error info to the agent in the same session and the agent should iron out any issues. +If you've installed the `metabase-semantic-checker` skill, just ask the agent to run the semantic checker; the skill picks the right image, passes the right flags, and summarizes the findings. -### 9. Import to your production Metabase +You can manually run the semantic checker via Docker like so: + +```sh +docker pull metabase/metabase-enterprise:latest + +docker run --rm \ + -v "$PWD:/workspace" \ + --entrypoint "" \ + -w /app \ + metabase/metabase-enterprise:latest \ + java -jar metabase.jar \ + --mode checker \ + --export /workspace \ + --schema-dir /workspace/.metabase/metadata.json \ + --schema-format concise +``` + +Match the image tag (`:latest`) to your Metabase build. + +### CI example + +You can hook the schema check into GitHub Actions so your team catches problems on the PR, before anyone pulls the changes into Metabase: + +```yaml +# .github/workflows/schema-check.yml +name: Schema Check + +on: + push: + branches: [main] + pull_request: + +jobs: + schema-check: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + + - uses: actions/setup-node@v6.4.0 + with: + node-version: "20" + + - name: Validate representation YAML files + run: npx --yes @metabase/representations validate-schema +``` -Import your changes via the API, push your changes to a remote git repository and set up [remote sync](../installation-and-operation/remote-sync) so that your production instance pulls in the changes automatically. +For the semantic check, add a second workflow that fetches `.metabase/metadata.json` from your Metabase and then runs the Docker command above against the checkout. If you run the semantic check in more than one workflow (for example, a semantic check and per-PR preview environments), you should probably factor the database metadata fetch to run and cache once a day so you don't hit the API on every push. ## Deleting content -Since imports and exports _don't_ delete content, you'll need to delete that content in the Metabase application itself, then update the YAML files as well. +Since imports and exports _don't_ delete content, you'll need to delete content in the Metabase application itself, then update the YAML files as well. -1. Delete the content in your production Metabase (in the app's UI itself). -2. Export from your production Metabase to your repo. -3. Commit the changes so that the YAML files are updated. That way Metabase won't recreate the deleted items the next time you import your changes. +1. Delete the content in your production Metabase (in the app's UI). +2. Push (with Remote Sync) or re-export (without) so the change is reflected in the repo. +3. Commit the deletion. That way Metabase won't recreate the deleted items the next time it pulls. ## Further reading -- [MCP server](./mcp) +- [Remote Sync](../installation-and-operation/remote-sync) - [Serialization](../installation-and-operation/serialization) +- [Metabase Representation Format](https://github.com/metabase/representations) +- [Metabase Database Metadata Format](https://github.com/metabase/database-metadata) - [Agent skills](https://github.com/metabase/agent-skills) +- [MCP server](./mcp) — for agents that need live metadata lookups outside the file-based workflow. diff --git a/_docs/master/ai/images/ai-usage-limits.png b/_docs/master/ai/images/ai-usage-limits.png new file mode 100644 index 0000000000..2dcf9268a4 Binary files /dev/null and b/_docs/master/ai/images/ai-usage-limits.png differ diff --git a/_docs/master/ai/images/metabot-illustrations.png b/_docs/master/ai/images/metabot-illustrations.png new file mode 100644 index 0000000000..4a1b8b787a Binary files /dev/null and b/_docs/master/ai/images/metabot-illustrations.png differ diff --git a/_docs/master/ai/metabot-slack.png b/_docs/master/ai/images/metabot-slack.png similarity index 100% rename from _docs/master/ai/metabot-slack.png rename to _docs/master/ai/images/metabot-slack.png diff --git a/_docs/master/ai/images/pythia-oracle-of-delphi-response.png b/_docs/master/ai/images/pythia-oracle-of-delphi-response.png new file mode 100644 index 0000000000..b5ec4ce16c Binary files /dev/null and b/_docs/master/ai/images/pythia-oracle-of-delphi-response.png differ diff --git a/_docs/master/ai/mcp.md b/_docs/master/ai/mcp.md index a3a809c762..d8bbfc6cb7 100644 --- a/_docs/master/ai/mcp.md +++ b/_docs/master/ai/mcp.md @@ -16,15 +16,51 @@ summary: 'Connect MCP-compatible AI clients to Metabase to search, explore, and Metabase includes an [MCP (Model Context Protocol)](https://modelcontextprotocol.io/) server (using Streamable HTTP transport) that lets AI clients connect directly to your Metabase, all scoped to the connecting person's permissions. +# Enable MCP server + +_Admin > AI > MCP_ + +MCP server and Agent API settings live on their own subpage. From **Admin > AI**, open the **MCP** tab in the left sidebar. + +Use the **MCP server** toggle to turn external access to the [MCP server](./mcp) on or off. + +### Supported MCP clients + +Under **Supported MCP clients**, switch on any clients you want to allow: + +- **Claude** (Claude Desktop and Claude on the web) +- **Cursor and VS Code** +- **ChatGPT** + +Toggling on a client automatically adds that client's sandbox domains to Metabase's CORS allowlist, which is what lets browser-based MCP clients make cross-origin requests to your Metabase. + +Some clients run outside the browser (like Claude Code on your own machine) and don't need a CORS allowlist entry. You can connect those clients without toggling anything on (assuming you've turned on the main MCP server setting). + +### Custom MCP client domains + +If you run a self-hosted MCP client, or a client that isn't in the supported list, add the client's domain to the **Custom MCP client domains** field. Separate values with a space, for example: + +``` +https://mcp.internal.example.com https://*.staging.example.com +``` + +The field accepts wildcards (`*`) for subdomains. Changes take effect in about a minute. Might be a good time to get up and pour yourself a glass of water. + ## Connect an MCP client -If your admin has turned on [your Metabase's MCP server](./settings#mcp-server-settings), all you need to do is point your MCP client at Metabase's MCP endpoint, `/api/mcp`. For example: +If your admin has turned on [your Metabase's MCP server](#enable-mcp-server), all you need to do is point your MCP client at Metabase's MCP endpoint, `/api/mcp`. For example: ``` https://{your-metabase.example.com}/api/mcp ``` -In Claude Code, for example, you can run `/mcp add metabase https://{your-metabase.example.com}/api/mcp --transport streamable-http` and Claude will handle the OAuth flow for you. +In the terminal, for example, you can run the following command. + +``` +claude mcp add --transport http metabase https://{your-metabase-url}/api/mcp +``` + +Replacing {your-metabase-url} with your Metabase address. Once added, Claude Code will handle the OAuth flow for you: For Claude Desktop, you can create a [custom connector](https://support.claude.com/en/articles/11175166-get-started-with-custom-connectors-using-remote-mcp) by just giving it that URL to your Metabase's mcp endpoint. @@ -55,6 +91,14 @@ Some explanation: OAuth discovery starts with Metabase returning a `WWW-Authenti If the site URL doesn't match an address your MCP client can reach, like if you're running Metabase in Docker and the site URL got auto-detected from an internal hostname like `metabase-dev:3000`, the client will register but fail the handshake. Your MCP client will typically report a connection failure rather than prompting you to authenticate (for example, Claude Code shows `✗ Failed to connect` rather than `! Needs authentication`). +## With the MCP server, your client provides the AI + +MCP server requests are handled by whatever AI client you're using (like a desktop AI app or editor plugin). The MCP server just provides tools (like searching for an entity or running the query) for your AI. + +For example, if you ask your AI client to use your Metabase's MCP server "what's our q3 revenue," your client will interact with the MCP server to figure out which tools it needs to field your request. Your AI can decide that it needs to use the tool **construct_query** and **execute_query**, and what those queries might be. Then your client will call those tools for Metabase to run. + +You don't need to have an [AI provider](settings#choose-ai-provider) configured in Metabase to use your Metabase's MCP server. If you _do_ have an AI provider configured in Metabase to power Metabot, that provider will _not_ be used for MCP server requests. MCP calls by your local client have no effect on token usage for your Metabase's AI connection. + ## Available tools Some clients (like Claude Desktop) will ask you to approve each tool the first time it's used. The MCP server builds on Metabase's [Agent API](./agent-api), and exposes the following tools. If you're building a custom integration and need full control, use the [Agent API](./agent-api) directly instead. @@ -67,6 +111,8 @@ Some clients (like Claude Desktop) will ask you to approve each tool the first t - **construct_query**: Construct a query against a table or metric. Returns an opaque query string that can be executed with `execute_query`. - **execute_query**: Execute a previously constructed query and return the results with column metadata, row count, and execution time. - **query**: Query a table or metric and return results. +- **create_question**: Create questions. +- **create_dashboard**: Create dashboards. ## Use the MCP server with file-based development diff --git a/_docs/master/ai/metabot-slack.md b/_docs/master/ai/metabot-slack.md index 929f109ca2..fbff129225 100644 --- a/_docs/master/ai/metabot-slack.md +++ b/_docs/master/ai/metabot-slack.md @@ -12,7 +12,7 @@ summary: 'Chat with Metabot directly in Slack to ask questions about your data, # Metabot in Slack -![Metabot in Slack](./metabot-slack.png) +![Metabot in Slack](./images/metabot-slack.png) Chat with [Metabot](./metabot) in Slack. Direct message Metabot for private analysis, or mention @Metabot in a channel to collaborate with your team. @@ -20,7 +20,7 @@ Chat with [Metabot](./metabot) in Slack. Direct message Metabot for private anal From Slack you can ask Metabot to: -- **Find existing content**: Search your Metabase for questions, and dashboards. Metabot links you directly to the content in your Metabase. +- **Find existing content**: Search your Metabase for questions and dashboards. Metabot links you directly to the content in your Metabase. - **Answer questions**: Create ad-hoc queries from natural language to answer your questions on the spot. You can click the link to save the question in Metabase. - **Show charts and tables**: Render static visualizations or tabular results in Slack. You can copy table results or download them as TSV. - **Work with CSVs**: [Upload a CSV](../databases/uploads) to Metabase, then ask follow-up questions about the data. @@ -68,7 +68,7 @@ Some caveats: - For goal-based alerts, the goal line must already be configured and saved on the question. Metabot can't add goal lines. - Metabot can't modify or delete existing alerts or subscriptions. - Alerts and subscriptions are delivered to the Slack channel where the conversation takes place. You can't redirect them to a different channel or to email. -- Alerts can only be set on questions not metrics or ad-hoc queries. +- Alerts can only be set on questions, not metrics or ad-hoc queries. ## Notes on privacy diff --git a/_docs/master/ai/metabot.md b/_docs/master/ai/metabot.md index 1fe943ee8b..a04f973970 100644 --- a/_docs/master/ai/metabot.md +++ b/_docs/master/ai/metabot.md @@ -22,16 +22,17 @@ To set up Metabot, see [Metabot settings](./settings). ## What Metabot can do -Metabot can help you to: +Here's a non-exhaustive list of things Metabot can help with: -- [AI exploration](#ai-exploration). +- [Answer data questions asked with natural language](#ai-exploration). - [Create a chart using the query builder](#how-metabot-uses-the-query-builder) from a natural language query. - [Generate SQL in the native editor](../questions/native-editor/writing-sql) from natural language. (Currently, only SQL is supported.) - [Edit SQL directly in the native editor](#inline-sql-editing). - [Analyze a chart](#analyze-charts-with-metabot). - [Fix errors in SQL code](#have-metabot-fix-sql-queries). -- Answer questions from our documentation (as in, the literature you're reading right now). -- [Chat with Metabot in Slack](./metabot-slack). +- [Generate transforms](../data-studio/transforms/transforms-overview#use-metabot-to-generate-code-for-transforms) +- [Generate charts in documents](../documents/introduction) +- [Answer questions from Slack](./metabot-slack). Like with all generative AI, you'll always need to double-check results. @@ -136,8 +137,6 @@ When answering questions in AI exploration, Metabot searches a limited set of co Metabot is getting smarter all the time, but there are some things it can't do yet: -- **Custom expressions.** Metabot can't use [custom expressions](../questions/query-builder/expressions-list) in query builder questions. -- **Multi-level aggregation.** Metabot is limited to a single level of aggregation and grouping. - **SQL variables.** Metabot can't generate SQL queries that include [SQL parameters](../questions/native-editor/sql-parameters) (like filters or field filters). - **Goal lines.** Metabot can't add [goal lines](../questions/visualizations/line-bar-and-area-charts#goal-lines) to charts. - **Chart formatting.** Metabot can't change visualization settings like colors, axis labels, or number formatting. diff --git a/_docs/master/ai/overview.md b/_docs/master/ai/overview.md new file mode 100644 index 0000000000..eadabf44a6 --- /dev/null +++ b/_docs/master/ai/overview.md @@ -0,0 +1,68 @@ +--- +version: master +has_magic_breadcrumbs: true +show_category_breadcrumb: true +show_title_breadcrumb: true +category: Ai +title: 'AI in Metabase overview' +source_url: 'https://github.com/metabase/metabase/blob/master/docs/ai/overview.md' +layout: new-docs +summary: 'Overview of all the ways you can use AI with Metabase.' +--- + +# AI in Metabase overview + +AI in Metabase is optional. You can use Metabase without AI at all. But if you do want to use AI to interact with Metabase, we have you covered. + +Here are the different ways to use AI with Metabase: + +- [Metabot](#metabot) +- [MCP server](#mcp-server) +- [Agent-driven file-based development workflow](#agent-driven-development-workflow) + +## Metabot + +**Best for: daily tasks in Metabase; granular control over people's AI usage.** + +Metabot is Metabase's built-in AI agent. Metabot can help you with most daily tasks around Metabase, like answering questions about your data, creating queries, generating SQL code, explaining charts, or creating Documents. If you're embedding Metabase into your product, you can get the Metabot agent through the [AI chat component](../embedding/components#ai-chat). See [non-exhaustive list of things Metabot can do](metabot#what-metabot-can-do), as well as its [limitations](metabot#current-limitations). + +**Controls:** Metabot will only see what the person using it can see. Metabot also comes with additional permission controls and usage limits so that you control who can use which Metabot tools (e.g. chat vs SQL generation) and how many tokens they can spend. + +**Provider**: Choose from: + +- Metabase's own AI Service (available as an add-on exclusively for Metabase Cloud) +- Third-party models via an API key (Anthropic models only for now). + +**Plans**: available on all plans. You can only use Metabase's AI Service on Metabase Cloud. + +See [full docs for Metabot](metabot) and [embedded AI chat](../embedding/components#ai-chat). + +## MCP server + +**Best for: asking ad-hoc, ephemeral questions; combining data from Metabase with data from other tools.** + +Connect your favorite third-party AI tool - like Claude or Codex - to the Metabase MCP server. MCP servers are designed for answering in-the-moment questions like "hey btw what's our q3 revenue?" Metabase's MCP server is also useful when combined with other MCP servers. For example, you can ask Claude a question about your customers that combines data from Metabase, your CRM, and your support ticket platform. + +Compared to the built-in Metabot, MCP server has somewhat restricted functionality (for example, it can't generate code or build transforms for now). See [the ever-expanding list of MCP server tools](mcp#available-tools). + +**Controls**: Metabase MCP server requires people to authenticate into Metabase, and all the responses it provides will be scoped to their permissions. However, unlike built-in Metabot, MCP server doesn't come with granular control over which _tools_ people can use, or disable MCP server altogether. + +**Provider**: Requests to Metabase's MCP server are handled by the provider you choose to connect to the MCP server (e.g. Claude, Cursor, etc). + +**Plans**: MCP server is available on all plans. + +See [full docs for MCP server](mcp). + +## Agent-driven development workflow + +**Best for: developers creating stuff that other people will use.** + +Use a coding agent like Claude Code to understand your database's metadata, generate Metabase content as YAML files locally, verify the schema, then sync and import the generated content into your production Metabase. Sky's the limit on what you can accomplish. + +**Controls**: Only admins can sync content to Metabase instances. + +**Provider**: Everything is handled by your coding agent of choice. + +**Plans**: Agent-driven workflows require a Pro/Enterprise plan. + +See [full docs for agent-driven workflow](./file-based-development) diff --git a/_docs/master/ai/settings.md b/_docs/master/ai/settings.md index 13aceeb92e..1c4b846db7 100644 --- a/_docs/master/ai/settings.md +++ b/_docs/master/ai/settings.md @@ -14,37 +14,56 @@ redirect_from: # AI settings -> AI features are available with your own AI provider API key, or as an add-on on [Metabase Cloud](/features/metabot-ai). +_Admin > AI_ + +This page covers admin settings for AI features in Metabase, including [Metabot](./metabot). To limit _who_ can use Metabot, see [AI controls](./usage-controls). + +## Enable AI features + +AI features are available on both Metabase Cloud and self-hosted Metabase. To turn them on: + +1. Go to **Admin settings > AI**. +2. In **Connect to an AI provider**, choose a **Provider**: + - **Metabase**: The Metabase AI service. Metabase picks a benchmarked, cost-effective model for you, and charges you on token usage. See [Choose AI provider](#choose-ai-provider) + - Another supported provider. See [bring your own API key](#bring-your-own-api-key). +3. Once connected, configure [Metabot](#configure-metabot) and other AI features below. + +## Choose AI provider _Admin > AI_ -This page covers admin settings for AI features in Metabase, including [Metabot](./metabot). +You can choose which AI provider and model is used to power Metabase's built-in agent. + +- If you're **self-hosting Metabase** and want to use Metabot, you need to [bring your own AI API key](#bring-your-own-api-key). +- On **Metabase Cloud**, you can either [bring your own AI API key](#bring-your-own-api-key) or [use the Metabase AI Service](#metabase-ai-service). -On **Metabase Cloud** you can either: +The AI provider that you specify in AI settings powers Metabase's built-in AI functionality, not the MCP server. [With the MCP server, your client provides the AI](mcp#with-the-mcp-server-your-client-provides-the-ai). -- [Purchase the Metabot add-on](#add-metabot-from-the-metabase-store) from the Metabase Store, or -- [Bring your own API key](#bring-your-own-api-key) from a supported AI provider. +### Metabase AI Service -On **self-hosted Metabases**: you can [bring your own API key](#bring-your-own-api-key) from a supported AI provider. +On Metabase Cloud, you can have us manage the AI for you with our AI Service. -## Add Metabot from the Metabase Store +Metabase's AI Service is a good option if you don't have a preferred AI provider, or if you want to manage all your Metabase AI costs through Metabase. We (Metabase the company) select the models for you. We use internal benchmarks to determine which AI models work best for different tasks, and we're constantly iterating to improve performance. -If you're on [Metabase Cloud](/cloud/), you can add Metabot from the Metabase Store: +If you use Metabase's AI Service, you'll get charge based on token usage (in addition to your regular Metabase Cloud subscription fee). See [Pricing](/pricing). -1. Go to [store.metabase.com](https://store.metabase.com). -2. Log in with your **Metabase Store account** (distinct from the account you use to log in to your Metabase). -3. In the **Instances** tab, find the instance you'd like to add Metabot to, and click "Add Metabot AI". -4. Pick the plan based on the number of requests you expect you'll need. +To use Metabase AI provider for your Metabot: - A "request" is any message anyone in your Metabase sends to Metabot. Several messages sent within the same chat session are counted as separate requests. Requests are added across the entire instance. +1. Go to **Admin > AI > AI settings**. +2. In **Connect to an AI provider**, choose **Metabase** as the provider. +3. Agree to the terms of service. +4. Click **Connect**. -5. Read through the [terms of service](/license/hosting) and click **Add Metabot AI**. +To disable Metabase AI provider and stop charges: -Once you've added Metabot AI in the Metabase store, you can log in to your Metabase and configure it in _Admin > AI_. +1. Go to **Admin > AI > AI settings**. +2. Under **Connected to Metabase**, click **Disconnect**. -## Bring your own API key +### Bring your own API key -_Admin > AI_ +You can specify your own API key and model for Metabot from one of the supported providers. Currently, Metabase only supports models from Anthropic. + +If you're interested in Metabase supporting more AI providers, let us know by submitting a [feature request](../troubleshooting-guide/requesting-new-features). To enable AI features with your own API key: @@ -54,17 +73,13 @@ To enable AI features with your own API key: 4. Click **Connect**. 5. Select a **Model** from the dropdown. Available models are fetched from the provider using your API key. -When your connection is active, the provider card header shows **Connected to [provider]** (for example, "Connected to Anthropic") next to a green status dot. With your key connected, you get access to [Metabot](./metabot), [inline SQL generation](./metabot#inline-sql-editing), the [MCP server](./mcp), and the [Agent API](./agent-api). +When your connection is active, the provider card header shows **Connected to [provider]** (for example, "Connected to Anthropic") next to a green status dot. With your key connected, you get access to [Metabot](./metabot), and [inline SQL generation](./metabot#inline-sql-editing). To clear your provider connection, click **Disconnect**. Disconnecting removes the stored API key and turns off any AI features that depend on the provider. -### Supported providers - -Currently, Metabase only supports models from Anthropic. - ## Configure Metabot -_Admin > AI > Metabot settings_ +_Admin > AI > AI settings_ ![Metabot settings](./images/ai-settings.png) @@ -76,7 +91,7 @@ _Internal tab._ Toggle [Metabot](./metabot) on or off for your Metabase. Metabot is enabled by default. -When enabled, Metabot is available to help people create questions, analyze data, and answer questions about your data. When disabled, the Metabot icon and keyboard shortcuts are hidden. Currently, Metabot is available to everyone who uses your Metabase. There's no way to scope Metabot usage per person. +When enabled, Metabot is available to help people create questions, analyze data, and answer questions about your data. When disabled, the Metabot icon and keyboard shortcuts are hidden. To scope Metabot to specific user or tenant groups, or to cap token usage, see [AI controls](./usage-controls). Toggling off Metabot only turns off in-app Metabot features. People can still use the [MCP server](./mcp) and [Agent API](./agent-api) if those are enabled. @@ -121,42 +136,14 @@ When people open a new Metabot chat, Metabase shows a few suggested prompts base Click **Regenerate suggested prompts** to generate a fresh set of prompts. You can also run individual prompts to test Metabot's answers, or delete prompts that aren't useful. The Internal and Embedded tabs each maintain their own set of suggestions, so regenerating on one tab doesn't affect the other. -## MCP server settings - -Use the **MCP server** toggle to turn external access to the [MCP server](./mcp) on or off. - -### Supported MCP clients - -Under **Supported MCP clients**, switch on any clients you want to allow: - -- **Claude** (Claude Desktop and Claude on the web) -- **Cursor and VS Code** -- **ChatGPT** - -Toggling on a client automatically adds that client's sandbox domains to Metabase's CORS allowlist, which is what lets browser-based MCP clients make cross-origin requests to your Metabase. - -Some clients run outside the browser (like Claude Code on your own machine) and don't need a CORS allowlist entry. You can connect those clients without toggling anything on (assuming you've turned on the main MCP server setting). - -### Custom MCP client domains - -If you run a self-hosted MCP client or one that isn't in the supported list, add its domain to the **Custom MCP client domains** field. Separate values with a space, for example: - -``` -https://mcp.internal.example.com https://*.staging.example.com -``` - -The field accepts wildcards (`*`) for subdomains. Changes take effect in about a minute. Might be a good time to get up and pour yourself a glass of water. - -## Agent API settings - -Use the **Agent API** toggle to turn external access to the [Agent API](./agent-api) on or off. - ## Disable all AI features The **Disable all AI features** toggle at the bottom of the AI features page is a master kill switch. When turned on, it hides all AI features across your instance — Metabot, inline SQL generation, the MCP server, the Agent API, and any embedded chat components — regardless of the individual toggles above. Use this toggle for an instance-wide shut-off without having to disconnect your provider or change each feature's own toggle. Turn it off again to restore your previous configuration. +For more granular options, check out [AI usage controls](./usage-controls). + ## Tips for making the most of Metabot The best thing you can do to improve Metabot's performance is to prep your data like you would for onboarding a new (human) hire to your data. In practice, this means you should: @@ -199,23 +186,17 @@ In other words, to restrict what data Metabot can see for each person, simply ap ## Viewing Metabot usage -If you're on Metabase Cloud with the Metabot add-on, you can see how many Metabot requests people have made this month by going to **Admin > Settings > License**. +If you're using the Metabase AI service, you can see how many Metabot requests people have made this month by going to **Admin > AI**. If you aren't logged into the [Metabase Store](../cloud/accounts-and-billing), you'll need to log in to the store before you can view the usage. Once logged in to the store, go back to your Metabase and view the license page. -The **Metabot AI requests used, this month (updated daily)** field shows how many requests your Metabase has used this month. Each message sent to Metabot counts as a request. - If you're using your own API key, you can track usage and costs through your AI provider's dashboard. -## Choosing the AI model - -If you're using your own API key, you can choose which AI model Metabase uses when you [bring your own API key](#bring-your-own-api-key). - -On Metabase Cloud, Metabase's AI service selects models automatically. We use internal benchmarks to determine which AI models work best for different tasks, and we're constantly iterating to improve performance. +On Metabase Pro/Enterprise, you also get access to detailed [AI usage auditing](usage-auditing) with detailed breakdown of AI usage by user, tool, feature etc. ## Privacy -On Metabase Cloud with the Metabot add-on, your questions and conversations remain private to your Metabase -- we don't send your data to external services. We do collect some metadata to gauge and improve usage. +When using the Metabase AI service, your questions and conversations remain private to your Metabase -- we don't send your data to external services. We do collect some metadata to gauge and improve usage. If you're using your own API key, your prompts and data are sent to your selected AI provider. Review your provider's data handling and privacy policies. When using the [MCP server](./mcp), query results are sent to the connected MCP client. @@ -229,4 +210,13 @@ Metabot has access to your Metabase metadata and some data values to help answer - **Sample field values**: When you ask questions like "Filter everyone from Wisconsin," Metabot might check the values in the state field to understand how the data is stored (like "WI" vs "Wisconsin"). See [syncs](../databases/sync-scan). - **Timeseries data**: For chart analysis, Metabot might see the timeseries data used to draw certain visualizations, depending on the chart type. -This data may be included when you [submit feedback](./metabot#giving-feedback-on-metabot-responses). +When you [submit feedback](./metabot#giving-feedback-on-metabot-responses), the context for the conversation - including this metadata and conversation prompts - might be sent to Metabase. + +## Further reading + +- [Using Metabot](metabot) +- [MCP server](mcp) +- [AI access and usage controls](usage-controls) +- [AI usage auditing](usage-auditing) +- [Metabot customization](customization) +- [Metabot system prompts](system-prompts) diff --git a/_docs/master/ai/start.md b/_docs/master/ai/start.md index 98b67582bd..f38516352f 100644 --- a/_docs/master/ai/start.md +++ b/_docs/master/ai/start.md @@ -11,8 +11,6 @@ layout: new-docs # AI in Metabase -> AI features are available as an add-on on [Metabase Cloud](/features/metabot-ai), or on self-hosted Metabase with your own AI provider API key. - ## [Metabot](./metabot) Metabot is an AI assistant that helps you explore and analyze your data. @@ -21,6 +19,18 @@ Metabot is an AI assistant that helps you explore and analyze your data. Connect an AI provider and configure AI features like Metabot. +## [AI usage controls](./usage-controls) + +Control who can use Metabot, and set token and message limits. + +## [AI customization](./customization) + +Customize Metabot's name, icon, and illustrations. + +## [AI system prompts](./system-prompts) + +Add standing instructions for Metabot's tools. + ## [Agent API](./agent-api) A REST API for building headless, agentic BI applications on top of Metabase's semantic layer. @@ -32,3 +42,7 @@ Connect MCP-compatible AI clients to your Metabase. ## [Metabot in Slack](./metabot-slack) Chat with Metabot directly in Slack — ask questions, get charts, and manage subscriptions without leaving Slack. + +## [AI usage auditing](./usage-auditing) + +See how people are using the AI features in your Metabase. diff --git a/_docs/master/ai/system-prompts.md b/_docs/master/ai/system-prompts.md new file mode 100644 index 0000000000..50bb1a7d19 --- /dev/null +++ b/_docs/master/ai/system-prompts.md @@ -0,0 +1,48 @@ +--- +version: master +has_magic_breadcrumbs: true +show_category_breadcrumb: true +show_title_breadcrumb: true +category: Ai +title: 'AI system prompts' +source_url: 'https://github.com/metabase/metabase/blob/master/docs/ai/system-prompts.md' +layout: new-docs +summary: 'Write custom instructions for Metabot to match your organization''s tone, terminology, and conventions.' +--- + +# AI system prompts + +{% include plans-blockquote.html feature="AI system prompts" is_plural=true%} + +_Admin > AI > System prompts_ + +System prompts let you customize instructions for Metabot. You can write a separate prompt for each of Metabot's three main tools: + +- **Metabot chat**: the general chat sidebar. +- **Natural language queries**: query-builder questions generated from natural language. +- **SQL generation**: SQL written from prompts (sidebar or [inline](./metabot#inline-sql-editing)). + +Like text cards on dashboards, prompts support [Markdown](/learn/metabase-basics/querying-and-dashboards/dashboards/markdown). + +## Prompt tips + +Be specific, give examples, and describe your organization's conventions. You can include whatever: preferred tone, business terms and acronyms, response format expectations. For example: + +``` +You are Pythia, Oracle of Delphi. + +Our fiscal year starts on February 1. "Last quarter" means the previous fiscal quarter, not the calendar quarter. + +... +``` + +![System prompts](./images/pythia-oracle-of-delphi-response.png) + +System prompts can only influence Metabot's behavior, not its access. A prompt can't grant Metabot permissions it doesn't already have. The person's [data](../permissions/data) and [collection](../permissions/collections) permissions still apply. + +## Further reading + +- [AI settings](./settings) +- [AI controls](./usage-controls) +- [AI customization](./customization) +- [Metabot](./metabot) diff --git a/_docs/master/ai/usage-auditing.md b/_docs/master/ai/usage-auditing.md new file mode 100644 index 0000000000..9ed6a803e6 --- /dev/null +++ b/_docs/master/ai/usage-auditing.md @@ -0,0 +1,155 @@ +--- +version: master +has_magic_breadcrumbs: true +show_category_breadcrumb: true +show_title_breadcrumb: true +category: Ai +title: 'AI usage auditing' +source_url: 'https://github.com/metabase/metabase/blob/master/docs/ai/usage-auditing.md' +layout: new-docs +summary: 'See token and message counts, chat logs, and more.' +--- + +# AI usage auditing + +{% include plans-blockquote.html feature="AI usage auditing" %} + +_Admin > AI > Usage auditing_ + +Admins can get an overview of human-robot interactions across Metabase, from high-level stats like total token counts down to visibility into actual conversations. These interactions include the in-product Metabot chat sidebar, Metabot conversations in [Documents](../documents/start), [Slack chats](./metabot-slack), and [inline SQL editing](./metabot#inline-sql-editing). + +The usage auditing section includes: + +- [Stats](#stats): aggregate charts across all Metabot activity. +- [Conversations](#conversations): a filterable list of every conversation, with a detail view for each. + +You can also build your own questions on top of the [Usage Analytics views](#building-custom-reports) that back these reports. + +## Stats + +_Admin > AI > Usage auditing > Stats_ + +The Stats page shows aggregate Metabot activity over a date range you choose, defaulting to the previous 30 days. + +### Filters + +- **Date range**: the time window the charts cover. +- **User**: limit to a single person (or **All users**). +- **Group**: limit to a single [group](../people-and-groups/managing) (or **All groups**). +- **Tenant**: limit to a single [tenant](../embedding/tenants). Only shows up if tenants are enabled. + +### Metrics + +Pick what you want to count: + +- **Conversations**: one row per distinct Metabot chat, across every surface listed above (chat sidebar, Documents, Slack, inline SQL). Not MCP conversations. +- **Tokens**: total tokens (input and output) consumed by LLM calls. +- **Messages**: every message exchanged, both from people and from Metabot. + +For each metric, you'll see the same set of charts: + +- **By time**: a time-series chart that buckets by hour or day depending on the date range you filter. Defaults to day. +- **By source**: _where_ in Metabase the request came from. See [Sources and profiles](#sources-and-profiles). +- **By profile**: _which_ Metabot persona answered. See [Sources and profiles](#sources-and-profiles). +- **Users with most ...**, **Groups with most ...**, **IP addresses with most ...**: top-N rankings. +- **Tenants with most ...**: only shown when tenants are enabled. + +You can drill through in the **By day**, **Groups with most ...**, **Users with most ...**, or **Tenants with most ...** charts to see the [Conversations list](#conversations) with the corresponding filter applied. The **By source**, **By profile**, and **IP addresses with most ...** charts are display-only. + +## Sources and profiles + +- **Source** is _where_ the request came from in Metabase. +- **Profile** is _which agent persona_ answered it. + +They often line up (a conversation that started in Slack is handled by the Slackbot profile), but they don't have to. A conversation started from the Metabot chat sidebar might be handled by the **Internal**, **NLQ**, or **SQL** profile depending on what the person asked. + +The Conversations admin page only shows **Profile**. Source is visible in the **Stats** charts and in the [Usage Analytics models](#building-custom-reports) used to build custom reports. + +### Sources + +Each conversation is tagged with a source, i.e. where in Metabase the conversation took place. The **By source** chart in [Stats](#stats) groups conversations by a human-readable `source_name`, and the [AI Usage Log](#building-custom-reports) model exposes both `source_name` and a raw `source` ID (e.g. `metabot_agent`, `oss-sql-gen`, `document_generate_content`) for custom reports. Conversations Metabase couldn't classify show up as `(empty)` on the chart. + +| Source name | Where it comes from | +| ------------------- | ----------------------------------------------------------------------------------------------------------------------- | +| `Metabot` | The Metabot chat sidebar inside Metabase. | +| `Documents` | Content generation inside [Documents](../documents/start). | +| `Suggested Prompts` | Background generation of suggested prompts. | +| `Slackbot` | Conversations that started in [Slack](./metabot-slack). | +| `SQL` | [Inline SQL editing](./metabot#inline-sql-editing) in the native editor. | +| `Unknown` | A conversation Metabase couldn't classify (distinct from no-source conversations, which appear as `(empty)` on charts). | + +### Profiles + +A profile is the configuration Metabot uses for a conversation: which prompt, which tools, and what it's allowed to do. The Conversations admin page, the **By profile** chart in [Stats](#stats), and the **Metabot Conversations** model (see [Building custom reports](#building-custom-reports)) all show the human-readable profile name. The [AI Usage Log](#building-custom-reports) model exposes the raw `profile_id` instead (e.g. `internal`, `transforms_codegen`, `embedding_next`). + +| Profile | What it does | +| -------------------- | ------------------------------------------------------------------------------------------------------------------------- | +| `Internal` | The default Metabot in the chat sidebar. Can build query-builder questions _and_ write SQL. | +| `NLQ` | Natural-language querying only. Always returns a [query builder](../questions/query-builder/editor) result, never SQL. | +| `SQL` | SQL writing only. Used by [inline SQL editing](./metabot#inline-sql-editing) and similar surfaces. | +| `Slackbot` | The persona behind [Metabot in Slack](./metabot-slack). | +| `Embedding` | The Metabot persona used inside [embedded Metabase](../embedding/start). | +| `Transforms codegen` | Generates [transform](../data-studio/transforms/transforms-overview), SQL, or Python. | +| `Documents` | Generates content inside [Documents](../documents/start). | + +## Conversations + +_Admin > AI > Usage auditing > Conversations_ + +The Conversations page lists every Metabot conversation Metabase has on file, newest first. + +### Filters + +- **Date range**, **User**, **Group**, **Tenant**: same as the [Stats filters](#filters). + +### Columns + +Each row shows: + +- **User**: who started the conversation. +- **Profile**: which Metabot persona answered. +- **Date**: when the conversation started. +- **Messages**: total messages, including both sides. +- **Tokens**: total LLM tokens spent. +- **Queries**: how many queries (SQL or query-builder) Metabot generated during the conversation. +- **Searches**: how many search-tool calls Metabot made. +- **IP**: the IP address the request came from. + +You can sort by Date, Messages, or Tokens. Click any row to open the [conversation detail](#conversation-detail). + +## Conversation detail + +The detail view is a full audit of a single conversation. It includes: + +- **Header**: start date, the person who chatted with Metabot, the profile Metabot used, the person's groups (including whether they're an admin), and tenant if applicable. From the **...** menu next to the person's name you can jump to all of their conversations, or to their account details. +- **Stat tiles**: Messages, Total tokens, Queries run, Searches. +- **Feedback** (if any): thumbs-up or thumbs-down and comments. The agent response that triggered the feedback is shown alongside. +- **Conversation transcript**: the full message-by-message exchange. Tool calls (search calls, query construction, etc.) are inlined. You can click "View" to open a modal with the info. +- **Queries generated**: every SQL or [query builder](../questions/query-builder/editor) (MBQL) query Metabot wrote during the conversation, with the referenced tables listed underneath. Hit **Visit** on a query to open the item in a new tab and run it yourself. Transform code-gen queries are shown read-only and can't be re-run from here. + +### The `/inspect` shortcut + +If you're an admin chatting with Metabot, type `/inspect` in the chat to jump straight from the current conversation to its detail page in Usage auditing. + +## Building custom reports + +Three [Usage Analytics](../usage-and-performance-tools/usage-analytics) models back the Usage auditing pages. + +- [AI Usage Log](../usage-and-performance-tools/usage-analytics-reference#ai-usage-log): one row per LLM call. +- [Metabot Conversations](../usage-and-performance-tools/usage-analytics-reference#metabot-conversations): one row per conversation. +- [Metabot Messages](../usage-and-performance-tools/usage-analytics-reference#metabot-messages): one row per message. + +Save your custom questions in the [Custom reports](../usage-and-performance-tools/usage-analytics#custom-reports-collection) sub-collection so the reports inherit the right permissions. + +## What isn't tracked + +[MCP](./mcp) activity isn't included in Usage auditing. MCP requests don't go through Metabot's conversation pipeline, so they don't generate conversations or token rows. + +## Further reading + +- [AI usage controls](./usage-controls) +- [AI settings](./settings) +- [Metabot](./metabot) +- [Metabot in Slack](./metabot-slack) +- [Usage analytics](../usage-and-performance-tools/usage-analytics) +- [Permissions overview](../permissions/start) diff --git a/_docs/master/ai/usage-controls.md b/_docs/master/ai/usage-controls.md new file mode 100644 index 0000000000..886ba76b3d --- /dev/null +++ b/_docs/master/ai/usage-controls.md @@ -0,0 +1,87 @@ +--- +version: master +has_magic_breadcrumbs: true +show_category_breadcrumb: true +show_title_breadcrumb: true +category: Ai +title: 'AI usage controls' +source_url: 'https://github.com/metabase/metabase/blob/master/docs/ai/usage-controls.md' +layout: new-docs +summary: 'Control who can use Metabot, and cap token or message usage by instance, group, or tenant.' +--- + +# AI usage controls + +{% include plans-blockquote.html feature="AI controls" is_plural=true%} + +_Admin > AI > Usage controls_ + +Once you've connected an AI provider (see [AI settings](./settings)), you can can control who can use Metabot and set usage budgets. + +- [AI feature access](#ai-feature-access): which groups can use Metabot, and which of its tools. +- [AI usage limits](#ai-usage-limits): token or message caps by instance, group, or tenant. + +## AI feature access + +_Admin > AI > Usage controls > AI feature access_ + +The AI feature access table lets you toggle Metabot on or off per group, and pick what Metabot can do for each group. Rows are your [internal groups](../people-and-groups/managing) and [tenant groups](../embedding/tenants); columns are Metabot capabilities. + +- **AI features** — the master toggle for the group. When off, people in that group won't see the Metabot icon, keyboard shortcuts, or any inline AI affordances. +- **Chat and NLQ** — access to the Metabot [chat sidebar](./metabot#the-metabot-chat-sidebar) and [natural language querying](./metabot#how-metabot-uses-the-query-builder). +- **SQL generation** — permission to have Metabot write or edit SQL ([from the sidebar](./metabot#metabot-in-the-native-editor) or [inline](./metabot#inline-sql-editing)). +- **Other tools** — other AI tools like error-fixing and chart analysis. + +These controls are granular. If you uncheck SQL generation but leave Chat and NLQ checked, Metabot will try to answer SQL-shaped prompts with a [query builder](../questions/query-builder/editor) result. + +[Tenant](../embedding/tenants) groups follow the same model as regular groups. + +## AI usage limits + +_Admin > AI > Usage controls > AI usage limits_ + +![AI usage limits](./images/ai-usage-limits.png) + +By default, AI usage is unlimited. + +These limits let you cap how much Metabot traffic Metabase allows — either across your whole instance, or for people in specific groups. + +### Settings and general limits + +- **How do you want to limit AI usage?** Choose between: + - **By token usage** in millions of tokens, so `2` would be 2 million tokens. + - **By message count**. Each message someone sends to Metabot counts as one message (not a conversation, but a single message). +- **When should usage limits reset?** The counter resets automatically; the limit values stay put. Pick from: + - **Daily** (resets at midnight). + - **Weekly** (resets on Monday). + - **Monthly** (resets the 1st). + +You can also set: + +- **Total instance limit**: the total pool of tokens or messages across every person and group. Once this limit is hit, Metabot stops responding to requests until the next reset. +- **Quota-reached message**: the error Metabot shows when someone hits a limit. Write whatever makes sense for your Metabase (like a Slack channel to ping, or a link to a request form). + +### Group limits + +Group limits set a per-_person_ cap for everyone in a user group. So, each person in the group gets the limit, not the group as a whole. + +If a person belongs to multiple groups, Metabase gives them the highest limit across those groups (_not_ the cumulative number across all of their groups). So if someone is in two groups, one group capped to 100 messages per week, and another group capped to 500, that person would enjoy 500 per week (not 600). + +### Tenant group limits + +You can set a limit for each [tenant group](../embedding/tenants#create-tenant-groups). They work just like the group limits described above. + +### Specific tenant limits + +This specific tenant limit is an aggregate pool shared by everyone in a single tenant. When the pool is empty, no one in that tenant can use Metabot for the rest of the period, regardless of how generous their tenant-group limits are. + +Per-tenant limits are handy for billing scenarios. Say you have a customer, Megafauna Analytics, who pays you for 100 million tokens a month. Set Megafauna Analytics's tenant limit to 100, and Metabase enforces that cap across every seat they provision. + +## Further reading + +- [AI settings](./settings) +- [Metabot](./metabot) +- [AI customization](./customization) +- [AI system prompts](./system-prompts) +- [Tenants](../embedding/tenants) +- [Permissions overview](../permissions/start) diff --git a/_docs/master/api.json b/_docs/master/api.json index 8037ab4be4..8eb0f60079 100644 --- a/_docs/master/api.json +++ b/_docs/master/api.json @@ -43,6 +43,31 @@ } }, "required" : [ "url", "created_at", "sync_started_at", "created_by_id", "db_id" ] + }, { + "type" : "object", + "properties" : { + "created_at" : { + "type" : "integer", + "minimum" : 1 + }, + "created_by_id" : { + "type" : "integer", + "minimum" : 1 + }, + "db_id" : { + "type" : "integer", + "minimum" : 1 + }, + "sync_started_at" : { + "type" : "integer", + "minimum" : 1 + }, + "url" : { + "type" : "string", + "minLength" : 1 + } + }, + "required" : [ "url", "created_at", "sync_started_at", "created_by_id", "db_id" ] }, { "type" : "object", "properties" : { @@ -1142,6 +1167,114 @@ "$ref" : "#/components/schemas/metabase-enterprise.action-v2.api.api-action-expression" } ] }, + "metabase-enterprise.data-complexity-score.api.node" : { + "anyOf" : [ { + "type" : "object", + "properties" : { + "error" : { + "type" : "string" + } + }, + "required" : [ "error" ], + "additionalProperties" : false + }, { + "type" : "object", + "properties" : { + "measurement" : { + "type" : "number" + }, + "rating" : { + "oneOf" : [ { + "type" : "string", + "enum" : [ "low", "medium", "high" ] + }, { + "type" : "null" + } ] + }, + "rating_label" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "score" : { + "type" : "integer", + "minimum" : 0 + } + }, + "required" : [ "measurement", "score", "rating", "rating_label" ], + "additionalProperties" : false + }, { + "type" : "object", + "properties" : { + "components" : { + "type" : "object", + "additionalProperties" : { + "$ref" : "#/components/schemas/metabase-enterprise.data-complexity-score.api.node" + } + }, + "rating" : { + "oneOf" : [ { + "type" : "string", + "enum" : [ "low", "medium", "high" ] + }, { + "type" : "null" + } ] + }, + "rating_label" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "score" : { + "oneOf" : [ { + "type" : "integer", + "minimum" : 0 + }, { + "type" : "null" + } ] + } + }, + "required" : [ "score", "rating", "rating_label", "components" ], + "additionalProperties" : false + } ] + }, + "metabase-enterprise.data-studio.api.table.publish-table-selectors" : { + "type" : "object", + "properties" : { + "collection_id" : { + "description" : "value must be an integer greater than zero.", + "type" : "integer", + "minimum" : 1 + }, + "database_ids" : { + "type" : "array", + "items" : { + "description" : "value must be an integer greater than zero.", + "type" : "integer", + "minimum" : 1 + } + }, + "schema_ids" : { + "type" : "array", + "items" : { + "type" : "string" + } + }, + "table_ids" : { + "type" : "array", + "items" : { + "description" : "value must be an integer greater than zero.", + "type" : "integer", + "minimum" : 1 + } + } + }, + "required" : [ "collection_id" ] + }, "metabase-enterprise.data-studio.api.table.publish-tables-response" : { "description" : "Schema for /publish-tables endpoint response. Matches frontend PublishTablesResponse type.", "type" : "object", @@ -2139,6 +2272,156 @@ }, "required" : [ "min", "fixed" ] }, + "metabase-enterprise.serialization.schema.export-metadata-response" : { + "type" : "object", + "properties" : { + "databases" : { + "type" : "array", + "items" : { + "$ref" : "#/components/schemas/metabase-enterprise.serialization.schema.exported-database" + } + }, + "fields" : { + "type" : "array", + "items" : { + "$ref" : "#/components/schemas/metabase-enterprise.serialization.schema.exported-field" + } + }, + "tables" : { + "type" : "array", + "items" : { + "$ref" : "#/components/schemas/metabase-enterprise.serialization.schema.exported-table" + } + } + } + }, + "metabase-enterprise.serialization.schema.exported-database" : { + "type" : "object", + "properties" : { + "engine" : { + "type" : "string" + }, + "id" : { + "$ref" : "#/components/schemas/metabase.lib.schema.id.database" + }, + "name" : { + "type" : "string" + } + }, + "required" : [ "id", "name", "engine" ] + }, + "metabase-enterprise.serialization.schema.exported-field" : { + "type" : "object", + "properties" : { + "base_type" : { + "type" : "string" + }, + "id" : { + "$ref" : "#/components/schemas/metabase.lib.schema.id.field" + }, + "coercion_strategy" : { + "type" : "string" + }, + "name" : { + "type" : "string" + }, + "semantic_type" : { + "type" : "string" + }, + "table_id" : { + "$ref" : "#/components/schemas/metabase.lib.schema.id.table" + }, + "nfc_path" : { + "type" : "array", + "items" : { + "type" : "string" + } + }, + "effective_type" : { + "type" : "string" + }, + "parent_id" : { + "$ref" : "#/components/schemas/metabase.lib.schema.id.field" + }, + "database_type" : { + "type" : "string" + }, + "description" : { + "type" : "string" + }, + "fk_target_field_id" : { + "$ref" : "#/components/schemas/metabase.lib.schema.id.field" + } + }, + "required" : [ "id", "table_id", "name", "base_type" ] + }, + "metabase-enterprise.serialization.schema.exported-table" : { + "type" : "object", + "properties" : { + "db_id" : { + "$ref" : "#/components/schemas/metabase.lib.schema.id.database" + }, + "description" : { + "type" : "string" + }, + "id" : { + "$ref" : "#/components/schemas/metabase.lib.schema.id.table" + }, + "name" : { + "type" : "string" + }, + "schema" : { + "type" : "string" + } + }, + "required" : [ "id", "db_id", "name" ] + }, + "metabase-enterprise.serialization.schema.import-status-response" : { + "description" : "Wire shape of `GET /metadata/import/:id`. Timestamps are ISO-8601 strings.\n `:started-at`/`:finished-at`/`:wall-ms` are nil until the relevant lifecycle\n stage is reached; `:error` is nil unless the import failed.", + "type" : "object", + "properties" : { + "enqueued-at" : { + "type" : "string" + }, + "error" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "finished-at" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "id" : { + "type" : "string" + }, + "started-at" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "status" : { + "type" : "string", + "enum" : [ "queued", "running", "ok", "error" ] + }, + "wall-ms" : { + "oneOf" : [ { + "type" : "number" + }, { + "type" : "null" + } ] + } + }, + "required" : [ "id", "status", "enqueued-at", "started-at", "finished-at", "wall-ms", "error" ], + "additionalProperties" : false + }, "metabase-enterprise.support-access-grants.schema.create-grant-request" : { "description" : "Schema for POST /api/ee/support-access-grants request body.", "type" : "object", @@ -3206,10 +3489,39 @@ }, "required" : [ "name", "base_type", "display_name" ] }, + "metabase.agent-api.api.construct-query-request" : { + "description" : "Request body for /v2/construct-query and the fresh-query branch of /v2/query.\n A single `:query` key whose value is a JSON object matching\n [[metabase.lib.schema/external-query]] — the canonical portable MBQL 5 wire format. The\n query is fully self-describing: the database is derived from the first stage's\n `source-table:` or `source-card:`, all field references are portable FKs\n (`[, , , ]`), and there is no auxiliary\n `source_entity` / `referenced_entities` envelope. See\n `resources/metabot/prompts/tools/construct_notebook_query.md` for the full format reference\n (including operators, joins, expressions, multi-stage queries, and FK conventions).\n\n Closed map: any extra top-level keys (notably the legacy `source_entity` /\n `referenced_entities` envelope from before the repr migration) are rejected with a 400 so\n callers don't silently send fields the server ignores.\n\n The inner `:query` value is intentionally typed as a plain `:map` at this boundary rather\n than `::lib.schema/external-query`. Reasons:\n\n 1. Deep MBQL-shape validation runs inside the representations pipeline\n (`metabot.tools.construct/execute-representations-query` calls `repr/validate-query`\n after the repair pass), so the boundary check would be redundant.\n\n 2. The strict-tool manifest lint (`assert-optional-fields-nullable!`) walks every map\n reachable from the tool input schema. `::external-query` references `::query`, which\n carries several `:optional` keys (`:lib/metadata`, `:database`, `:settings`, …) that\n are not `[:maybe ...]` — for sound reasons unrelated to this endpoint. Recursing into\n them would force a wide schema change just to satisfy the lint at the agent boundary.", + "type" : "object", + "properties" : { + "prompt" : { + "oneOf" : [ { + "type" : "string", + "minLength" : 1, + "maxLength" : 10000 + }, { + "type" : "null" + } ] + }, + "query" : { + "type" : "object", + "properties" : { } + } + }, + "required" : [ "query" ], + "additionalProperties" : false + }, "metabase.agent-api.api.construct-query-response" : { - "description" : "Response containing a base64-encoded MBQL query for use with /v1/execute.", + "description" : "Response containing a base64-encoded MBQL query for use with /v1/execute. The optional\n `:prompt` echoes the request's prompt back so the MCP layer can store it with the\n handle (see `metabase.mcp.tools/make-store-construct-query-result`).", "type" : "object", "properties" : { + "prompt" : { + "oneOf" : [ { + "type" : "string", + "minLength" : 1 + }, { + "type" : "null" + } ] + }, "query" : { "type" : "string", "minLength" : 1 @@ -3217,6 +3529,162 @@ }, "required" : [ "query" ] }, + "metabase.agent-api.api.create-dashboard-request" : { + "type" : "object", + "properties" : { + "collection_id" : { + "oneOf" : [ { + "description" : "value must be an integer greater than zero.", + "type" : "integer", + "minimum" : 1 + }, { + "type" : "null" + } ] + }, + "description" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "name" : { + "type" : "string", + "minLength" : 1 + }, + "question_ids" : { + "oneOf" : [ { + "type" : "array", + "items" : { + "description" : "value must be an integer greater than zero.", + "type" : "integer", + "minimum" : 1 + } + }, { + "type" : "null" + } ] + } + }, + "required" : [ "name" ] + }, + "metabase.agent-api.api.create-dashboard-response" : { + "type" : "object", + "properties" : { + "collection_id" : { + "oneOf" : [ { + "description" : "value must be an integer greater than zero.", + "type" : "integer", + "minimum" : 1 + }, { + "type" : "null" + } ] + }, + "dashcard_ids" : { + "type" : "array", + "items" : { + "description" : "value must be an integer greater than zero.", + "type" : "integer", + "minimum" : 1 + } + }, + "description" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "id" : { + "description" : "value must be an integer greater than zero.", + "type" : "integer", + "minimum" : 1 + }, + "name" : { + "type" : "string", + "minLength" : 1 + } + }, + "required" : [ "id", "name", "collection_id", "description", "dashcard_ids" ] + }, + "metabase.agent-api.api.create-question-request" : { + "type" : "object", + "properties" : { + "collection_id" : { + "oneOf" : [ { + "description" : "value must be an integer greater than zero.", + "type" : "integer", + "minimum" : 1 + }, { + "type" : "null" + } ] + }, + "description" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "display" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "name" : { + "type" : "string", + "minLength" : 1 + }, + "query" : { + "type" : "string", + "minLength" : 1 + }, + "visualization_settings" : { + "oneOf" : [ { + "type" : "object", + "properties" : { } + }, { + "type" : "null" + } ] + } + }, + "required" : [ "name", "query" ] + }, + "metabase.agent-api.api.create-question-response" : { + "type" : "object", + "properties" : { + "collection_id" : { + "oneOf" : [ { + "description" : "value must be an integer greater than zero.", + "type" : "integer", + "minimum" : 1 + }, { + "type" : "null" + } ] + }, + "description" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "display" : { + "type" : "string" + }, + "id" : { + "description" : "value must be an integer greater than zero.", + "type" : "integer", + "minimum" : 1 + }, + "name" : { + "type" : "string", + "minLength" : 1 + } + }, + "required" : [ "id", "name", "display", "collection_id", "description" ] + }, "metabase.agent-api.api.entity-type" : { "description" : "The type of queryable entity.", "type" : "string", @@ -3500,12 +3968,8 @@ }, "required" : [ "id", "type", "name" ] }, - "metabase.agent-api.api.program-request" : { - "description" : "Request body for /v2/construct-query and /v2/query.\n An agent-lib structured program with `:source` and `:operations`. The top-level\n `:source` must reference a database entity (`table`, `card`, `dataset`, or\n `metric`); `context` and nested `program` sources are rejected at the HTTP\n boundary by [[evaluate-program-for-execution]] because they require an\n in-process evaluation context.", - "$ref" : "#/components/schemas/metabase.agent-lib.schema.program" - }, "metabase.agent-api.api.query-request" : { - "description" : "Request body for /v2/query. Accepts either a structured program or a continuation_token.", + "description" : "Request body for /v2/query. Accepts either a fresh-query payload (`{:query }`,\n same shape as /v2/construct-query) or a `:continuation_token` from a prior response.\n\n Both branches are closed maps: extra top-level keys (e.g. the legacy\n `source_entity` / `referenced_entities` envelope, or sending `:query` and\n `:continuation_token` simultaneously) are rejected with a 400.", "oneOf" : [ { "type" : "object", "properties" : { @@ -3514,9 +3978,10 @@ "minLength" : 1 } }, - "required" : [ "continuation_token" ] + "required" : [ "continuation_token" ], + "additionalProperties" : false }, { - "$ref" : "#/components/schemas/metabase.agent-api.api.program-request" + "$ref" : "#/components/schemas/metabase.agent-api.api.construct-query-request" } ] }, "metabase.agent-api.api.query-response" : { @@ -3934,302 +4399,6 @@ }, "required" : [ "id", "type", "name", "display_name", "database_id", "database_engine", "fields" ] }, - "metabase.agent-lib.schema.aggregation-ref-form" : { - "type" : "array", - "prefixItems" : [ { - "const" : "aggregation-ref" - }, { - "type" : "integer", - "minimum" : 0 - } ] - }, - "metabase.agent-lib.schema.expression-ref-form" : { - "type" : "array", - "prefixItems" : [ { - "const" : "expression-ref" - }, { - "$ref" : "#/components/schemas/metabase.agent-lib.schema.non-blank-string" - } ] - }, - "metabase.agent-lib.schema.form" : { - "anyOf" : [ { - "$ref" : "#/components/schemas/metabase.agent-lib.schema.source-ref" - }, { - "$ref" : "#/components/schemas/metabase.agent-lib.schema.query-aware-ref" - }, { - "$ref" : "#/components/schemas/metabase.agent-lib.schema.nested-operator-form" - } ] - }, - "metabase.agent-lib.schema.map-literal" : { - "type" : "object", - "additionalProperties" : { - "$ref" : "#/components/schemas/metabase.agent-lib.schema.node" - } - }, - "metabase.agent-lib.schema.nested-operator-form" : { - "type" : "array", - "items" : { - "$ref" : "#/components/schemas/metabase.agent-lib.schema.node" - }, - "minItems" : 1 - }, - "metabase.agent-lib.schema.node" : { - "anyOf" : [ { - "$ref" : "#/components/schemas/metabase.agent-lib.schema.scalar" - }, { - "$ref" : "#/components/schemas/metabase.agent-lib.schema.program-literal" - }, { - "$ref" : "#/components/schemas/metabase.agent-lib.schema.map-literal" - }, { - "$ref" : "#/components/schemas/metabase.agent-lib.schema.form" - }, { - "$ref" : "#/components/schemas/metabase.agent-lib.schema.vector-literal" - } ] - }, - "metabase.agent-lib.schema.non-blank-string" : { - "type" : "string" - }, - "metabase.agent-lib.schema.page" : { - "type" : "object", - "properties" : { - "items" : { - "description" : "value must be an integer greater than zero.", - "type" : "integer", - "minimum" : 1 - }, - "page" : { - "description" : "value must be an integer greater than zero.", - "type" : "integer", - "minimum" : 1 - } - }, - "required" : [ "page", "items" ], - "additionalProperties" : false - }, - "metabase.agent-lib.schema.program" : { - "type" : "object", - "properties" : { - "operations" : { - "type" : "array", - "items" : { - "$ref" : "#/components/schemas/metabase.agent-lib.schema.top-level-op" - } - }, - "source" : { - "$ref" : "#/components/schemas/metabase.agent-lib.schema.source" - } - }, - "required" : [ "source", "operations" ], - "additionalProperties" : false - }, - "metabase.agent-lib.schema.program-literal" : { - "type" : "object", - "properties" : { - "program" : { - "$ref" : "#/components/schemas/metabase.agent-lib.schema.program" - }, - "type" : { - "const" : "program" - } - }, - "required" : [ "type", "program" ], - "additionalProperties" : false - }, - "metabase.agent-lib.schema.query-aware-ref" : { - "anyOf" : [ { - "$ref" : "#/components/schemas/metabase.agent-lib.schema.expression-ref-form" - }, { - "$ref" : "#/components/schemas/metabase.agent-lib.schema.aggregation-ref-form" - } ] - }, - "metabase.agent-lib.schema.scalar" : { - "anyOf" : [ { - "type" : "null" - }, { - "type" : "string" - }, { - "type" : "number" - }, { - "type" : "boolean" - } ] - }, - "metabase.agent-lib.schema.source" : { - "anyOf" : [ { - "type" : "object", - "properties" : { - "ref" : { - "const" : "source" - }, - "type" : { - "const" : "context" - } - }, - "required" : [ "type", "ref" ], - "additionalProperties" : false - }, { - "type" : "object", - "properties" : { - "id" : { - "description" : "value must be an integer greater than zero.", - "type" : "integer", - "minimum" : 1 - }, - "type" : { - "type" : "string", - "enum" : [ "table", "card", "dataset", "metric" ] - } - }, - "required" : [ "type", "id" ], - "additionalProperties" : false - }, { - "$ref" : "#/components/schemas/metabase.agent-lib.schema.program-literal" - } ] - }, - "metabase.agent-lib.schema.source-ref" : { - "anyOf" : [ { - "type" : "array", - "prefixItems" : [ { - "const" : "field" - }, { - "description" : "value must be an integer greater than zero.", - "type" : "integer", - "minimum" : 1 - } ] - }, { - "type" : "array", - "prefixItems" : [ { - "const" : "table" - }, { - "description" : "value must be an integer greater than zero.", - "type" : "integer", - "minimum" : 1 - } ] - }, { - "type" : "array", - "prefixItems" : [ { - "const" : "card" - }, { - "description" : "value must be an integer greater than zero.", - "type" : "integer", - "minimum" : 1 - } ] - }, { - "type" : "array", - "prefixItems" : [ { - "const" : "metric" - }, { - "description" : "value must be an integer greater than zero.", - "type" : "integer", - "minimum" : 1 - } ] - } ] - }, - "metabase.agent-lib.schema.top-level-op" : { - "anyOf" : [ { - "type" : "array", - "prefixItems" : [ { - "const" : "filter" - }, { - "$ref" : "#/components/schemas/metabase.agent-lib.schema.form" - } ] - }, { - "type" : "array", - "prefixItems" : [ { - "const" : "aggregate" - }, { - "$ref" : "#/components/schemas/metabase.agent-lib.schema.form" - } ] - }, { - "type" : "array", - "prefixItems" : [ { - "const" : "breakout" - }, { - "$ref" : "#/components/schemas/metabase.agent-lib.schema.form" - } ] - }, { - "type" : "array", - "prefixItems" : [ { - "const" : "with-fields" - }, { - "type" : "array", - "items" : { - "$ref" : "#/components/schemas/metabase.agent-lib.schema.form" - } - } ] - }, { - "type" : "array", - "prefixItems" : [ { - "const" : "limit" - }, { - "description" : "value must be an integer greater than zero.", - "type" : "integer", - "minimum" : 1 - } ] - }, { - "type" : "array", - "prefixItems" : [ { - "const" : "expression" - }, { - "$ref" : "#/components/schemas/metabase.agent-lib.schema.non-blank-string" - }, { - "$ref" : "#/components/schemas/metabase.agent-lib.schema.form" - } ] - }, { - "type" : "array", - "prefixItems" : [ { - "const" : "join" - }, { - "$ref" : "#/components/schemas/metabase.agent-lib.schema.form" - } ] - }, { - "anyOf" : [ { - "type" : "array", - "prefixItems" : [ { - "const" : "order-by" - }, { - "$ref" : "#/components/schemas/metabase.agent-lib.schema.form" - } ] - }, { - "type" : "array", - "prefixItems" : [ { - "const" : "order-by" - }, { - "$ref" : "#/components/schemas/metabase.agent-lib.schema.form" - }, { - "type" : "string", - "enum" : [ "asc", "desc" ] - } ] - } ] - }, { - "type" : "array", - "prefixItems" : [ { - "const" : "append-stage" - } ] - }, { - "type" : "array", - "prefixItems" : [ { - "const" : "drop-stage" - } ] - }, { - "type" : "array", - "prefixItems" : [ { - "const" : "drop-empty-stages" - } ] - }, { - "type" : "array", - "prefixItems" : [ { - "const" : "with-page" - }, { - "$ref" : "#/components/schemas/metabase.agent-lib.schema.page" - } ] - } ] - }, - "metabase.agent-lib.schema.vector-literal" : { - "type" : "array", - "items" : { - "$ref" : "#/components/schemas/metabase.agent-lib.schema.node" - } - }, "metabase.analyze.query-results.ResultsMetadata" : { "description" : "value must be an array of valid results column metadata maps.", "oneOf" : [ { @@ -5168,7 +5337,32 @@ }, "metabase.driver.connection.connection-type" : { "type" : "string", - "enum" : [ "default", "write-data" ] + "enum" : [ "default", "write-data", "admin", "transform" ] + }, + "metabase.embedding-rest.api.theme.EmbeddingTheme" : { + "type" : "object", + "properties" : { + "created_at" : { }, + "entity_id" : { + "type" : "string", + "minLength" : 1 + }, + "id" : { + "description" : "value must be an integer greater than zero.", + "type" : "integer", + "minimum" : 1 + }, + "name" : { + "type" : "string", + "minLength" : 1 + }, + "settings" : { + "type" : "object", + "properties" : { } + }, + "updated_at" : { } + }, + "required" : [ "id", "entity_id", "name", "settings", "created_at", "updated_at" ] }, "metabase.frontend-errors.api.frontend-error-type" : { "type" : "string", @@ -7975,6 +8169,8 @@ "required" : [ "lib/type" ] }, { "$ref" : "#/components/schemas/metabase.lib.schema..stage.valid-refs" + }, { + "$ref" : "#/components/schemas/metabase.lib.schema..stage.page-and-limit-are-mutually-exclusive" }, { "allOf" : [ ] } ] @@ -8028,6 +8224,9 @@ "allOf" : [ ] } ] }, + "metabase.lib.schema..stage.page-and-limit-are-mutually-exclusive" : { + "description" : "If an MBQL query stage specifies `:page`, it should not also specify `:limit`" + }, "metabase.lib.schema..stage.type" : { "type" : "string", "enum" : [ "mbql.stage/native", "mbql.stage/mbql" ] @@ -9547,7 +9746,21 @@ "description" : "Schema for fingerprint information for Fields deriving from `:type/Number`.", "type" : "object", "properties" : { - "avg" : { + "mode-fraction" : { + "oneOf" : [ { + "$ref" : "#/components/schemas/metabase.lib.schema.metadata.fingerprint.percent" + }, { + "type" : "null" + } ] + }, + "min" : { + "oneOf" : [ { + "type" : "number" + }, { + "type" : "null" + } ] + }, + "q1" : { "oneOf" : [ { "type" : "number" }, { @@ -9561,14 +9774,21 @@ "type" : "null" } ] }, - "min" : { + "avg" : { "oneOf" : [ { "type" : "number" }, { "type" : "null" } ] }, - "q1" : { + "sd" : { + "oneOf" : [ { + "type" : "number" + }, { + "type" : "null" + } ] + }, + "skewness" : { "oneOf" : [ { "type" : "number" }, { @@ -9582,12 +9802,26 @@ "type" : "null" } ] }, - "sd" : { + "top-3-fraction" : { + "oneOf" : [ { + "$ref" : "#/components/schemas/metabase.lib.schema.metadata.fingerprint.percent" + }, { + "type" : "null" + } ] + }, + "excess-kurtosis" : { "oneOf" : [ { "type" : "number" }, { "type" : "null" } ] + }, + "zero-fraction" : { + "oneOf" : [ { + "$ref" : "#/components/schemas/metabase.lib.schema.metadata.fingerprint.percent" + }, { + "type" : "null" + } ] } } }, @@ -9608,6 +9842,27 @@ }, { "type" : "null" } ] + }, + "mode-fraction" : { + "oneOf" : [ { + "$ref" : "#/components/schemas/metabase.lib.schema.metadata.fingerprint.percent" + }, { + "type" : "null" + } ] + }, + "skewness" : { + "oneOf" : [ { + "type" : "number" + }, { + "type" : "null" + } ] + }, + "top-3-fraction" : { + "oneOf" : [ { + "$ref" : "#/components/schemas/metabase.lib.schema.metadata.fingerprint.percent" + }, { + "type" : "null" + } ] } } }, @@ -9622,6 +9877,20 @@ "type" : "null" } ] }, + "mode-fraction" : { + "oneOf" : [ { + "$ref" : "#/components/schemas/metabase.lib.schema.metadata.fingerprint.percent" + }, { + "type" : "null" + } ] + }, + "percent-blank" : { + "oneOf" : [ { + "$ref" : "#/components/schemas/metabase.lib.schema.metadata.fingerprint.percent" + }, { + "type" : "null" + } ] + }, "percent-email" : { "oneOf" : [ { "$ref" : "#/components/schemas/metabase.lib.schema.metadata.fingerprint.percent" @@ -9649,6 +9918,13 @@ }, { "type" : "null" } ] + }, + "top-3-fraction" : { + "oneOf" : [ { + "$ref" : "#/components/schemas/metabase.lib.schema.metadata.fingerprint.percent" + }, { + "type" : "null" + } ] } } }, @@ -13772,212 +14048,58 @@ "required" : [ "enabled" ] } }, - "metabase.warehouses-rest.api.database-info" : { - "type" : "object", - "properties" : { - "engine" : { - "type" : "string" - }, - "id" : { - "$ref" : "#/components/schemas/metabase.lib.schema.id.database" - }, - "name" : { - "type" : "string" - } - }, - "required" : [ "id", "name", "engine" ] - }, - "metabase.warehouses-rest.api.databases-metadata-response" : { + "metabase.workspaces.core.table-namespace" : { + "description" : "A `{:db ?, :schema ?}` namespace map. Either or both keys may be present\n depending on the driver's `qualified-name-components`; at least one must\n populate. Empty-string `\"\"` is reserved for the storage layer; the atom\n carries `nil`/missing for absent slots.", "type" : "object", "properties" : { - "databases" : { - "type" : "array", - "items" : { - "$ref" : "#/components/schemas/metabase.warehouses-rest.api.database-info" - } - }, - "fields" : { - "type" : "array", - "items" : { - "$ref" : "#/components/schemas/metabase.warehouses-rest.api.field-info" - } - }, - "tables" : { - "type" : "array", - "items" : { - "$ref" : "#/components/schemas/metabase.warehouses-rest.api.table-info" - } - } - }, - "required" : [ "databases", "tables", "fields" ] - }, - "metabase.warehouses-rest.api.field-info" : { - "type" : "object", - "properties" : { - "base_type" : { - "type" : "string" - }, - "id" : { - "$ref" : "#/components/schemas/metabase.lib.schema.id.field" - }, - "coercion_strategy" : { - "type" : "string" - }, - "name" : { - "type" : "string" - }, - "semantic_type" : { - "type" : "string" - }, - "table_id" : { - "$ref" : "#/components/schemas/metabase.lib.schema.id.table" - }, - "effective_type" : { - "type" : "string" - }, - "parent_id" : { - "$ref" : "#/components/schemas/metabase.lib.schema.id.field" - }, - "database_type" : { - "type" : "string" - }, - "description" : { - "type" : "string" + "db" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] }, - "fk_target_field_id" : { - "$ref" : "#/components/schemas/metabase.lib.schema.id.field" + "schema" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] } - }, - "required" : [ "id", "table_id", "name", "base_type" ] + } }, - "metabase.warehouses-rest.api.field-values-info" : { + "metabase.workspaces.core.workspace-database-config" : { + "description" : "Per-database workspace config: `:input_schemas` is a vector of driver-opaque\n schema names (the source schemas the workspace reads from) — may be empty\n on drivers with no schema layer (e.g. MySQL), where the bound DB itself acts\n as the implicit input namespace; `:output` is a single namespace map (the\n workspace's isolation schema, expanded with the warehouse catalog at boot).", "type" : "object", "properties" : { - "field_id" : { - "$ref" : "#/components/schemas/metabase.lib.schema.id.field" - }, - "has_more_values" : { - "type" : "boolean" - }, - "human_readable_values" : { + "input_schemas" : { "type" : "array", "items" : { - "oneOf" : [ { - "type" : "string" - }, { - "type" : "null" - } ] + "type" : "string" } }, - "values" : { - "type" : "array", - "items" : { - "type" : "array", - "items" : { } - } - } - }, - "required" : [ "field_id", "values", "has_more_values" ] - }, - "metabase.warehouses-rest.api.field-values-response" : { - "type" : "object", - "properties" : { - "field_values" : { - "type" : "array", - "items" : { - "$ref" : "#/components/schemas/metabase.warehouses-rest.api.field-values-info" - } + "output" : { + "$ref" : "#/components/schemas/metabase.workspaces.core.table-namespace" } }, - "required" : [ "field_values" ] + "required" : [ "input_schemas", "output" ] }, - "metabase.warehouses-rest.api.metadata-import-report" : { + "metabase.workspaces.core.workspace-instance-config" : { + "description" : "The shape stored in the EE `instance-workspace` setting after the `:workspace`\n config.yml loader has resolved database names to ids. Database keys are integer\n ids (post-resolution); the wire format with name keys lives in\n `metabase-enterprise.advanced-config.file.workspace`.", "type" : "object", "properties" : { "databases" : { "type" : "object", - "properties" : { - "failed" : { - "type" : "array", - "items" : { - "type" : "object", - "properties" : { } - } - }, - "matched" : { - "type" : "integer" - }, - "missing" : { - "type" : "array", - "items" : { - "type" : "object", - "properties" : { } - } - } - }, - "required" : [ "matched", "missing" ] - }, - "fields" : { - "type" : "object", - "properties" : { - "created" : { - "type" : "integer" - }, - "matched" : { - "type" : "integer" - }, - "missing" : { - "type" : "array", - "items" : { - "type" : "object", - "properties" : { } - } - } - }, - "required" : [ "matched", "created", "missing" ] - }, - "tables" : { - "type" : "object", - "properties" : { - "created" : { - "type" : "integer" - }, - "matched" : { - "type" : "integer" - }, - "missing" : { - "type" : "array", - "items" : { - "type" : "object", - "properties" : { } - } - } - }, - "required" : [ "matched", "created", "missing" ] - } - }, - "required" : [ "databases", "tables", "fields" ] - }, - "metabase.warehouses-rest.api.table-info" : { - "type" : "object", - "properties" : { - "db_id" : { - "$ref" : "#/components/schemas/metabase.lib.schema.id.database" - }, - "description" : { - "type" : "string" - }, - "id" : { - "$ref" : "#/components/schemas/metabase.lib.schema.id.table" + "additionalProperties" : { + "$ref" : "#/components/schemas/metabase.workspaces.core.workspace-database-config" + } }, "name" : { - "type" : "string" - }, - "schema" : { - "type" : "string" + "type" : "string", + "minLength" : 1 } }, - "required" : [ "id", "db_id", "name" ] + "required" : [ "name", "databases" ] }, "metabase.xrays.api.automagic-dashboards.base-64-encoded-json" : { "description" : "form-encoded base-64-encoded JSON" @@ -14493,6 +14615,42 @@ "tags" : [ "/api/activity" ] } }, + "/api/agent/v1/dashboard" : { + "post" : { + "operationId" : "post-api-agent-v1-dashboard", + "summary" : "POST /api/agent/v1/dashboard", + "description" : "Create a new dashboard, optionally populated with saved questions.\n\n Pass `question_ids` to add existing saved questions as cards on the dashboard.\n Cards are automatically positioned on the grid based on their display type.", + "parameters" : [ ], + "responses" : { + "2XX" : { + "description" : "Successful response", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/metabase.agent-api.api.create-dashboard-response" + } + } + } + }, + "4XX" : { + "description" : "Client error response" + }, + "5XX" : { + "description" : "Server error response" + } + }, + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/metabase.agent-api.api.create-dashboard-request" + } + } + } + }, + "tags" : [ "/api/agent" ] + } + }, "/api/agent/v1/execute" : { "post" : { "operationId" : "post-api-agent-v1-execute", @@ -14686,6 +14844,42 @@ "tags" : [ "/api/agent" ] } }, + "/api/agent/v1/question" : { + "post" : { + "operationId" : "post-api-agent-v1-question", + "summary" : "POST /api/agent/v1/question", + "description" : "Save a previously constructed query as a named question (card).\n\n The `query` parameter should be a base64-encoded string returned by construct_query.\n Optionally specify display type, description, collection, and visualization settings.", + "parameters" : [ ], + "responses" : { + "2XX" : { + "description" : "Successful response", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/metabase.agent-api.api.create-question-response" + } + } + } + }, + "4XX" : { + "description" : "Client error response" + }, + "5XX" : { + "description" : "Server error response" + } + }, + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/metabase.agent-api.api.create-question-request" + } + } + } + }, + "tags" : [ "/api/agent" ] + } + }, "/api/agent/v1/search" : { "post" : { "operationId" : "post-api-agent-v1-search", @@ -14906,7 +15100,7 @@ "post" : { "operationId" : "post-api-agent-v2-construct-query", "summary" : "POST /api/agent/v2/construct-query", - "description" : "Construct an MBQL query from a structured agent-lib program.\n\n The body is the program itself: a JSON object with `source` (identifying the\n table/card/dataset/metric to query) and `operations` (an array of operator\n tuples). Returns a base64-encoded MBQL query that can be executed via\n /v1/execute. See the agent_api reference for the full program syntax.", + "description" : "Construct an MBQL query from a portable MBQL 5 representations JSON payload.\n\n The body is `{\"query\": }` where `` is a JSON object\n matching `::lib.schema/external-query` — see the `construct_notebook_query` tool\n documentation for the format reference. Returns a base64-encoded MBQL query that can be\n executed via /v1/execute or paginated via /v2/query.", "parameters" : [ ], "responses" : { "2XX" : { @@ -14930,7 +15124,7 @@ "content" : { "application/json" : { "schema" : { - "$ref" : "#/components/schemas/metabase.agent-api.api.program-request" + "$ref" : "#/components/schemas/metabase.agent-api.api.construct-query-request" } } } @@ -14942,7 +15136,7 @@ "post" : { "operationId" : "post-api-agent-v2-query", "summary" : "POST /api/agent/v2/query", - "description" : "Execute a structured program and stream the results, with continuation-token pagination.\n\n Accepts either a program (same shape as /v2/construct-query) or a\n `continuation_token` from a previous response. Returns results with column\n metadata and an optional `continuation_token` for fetching the next page.", + "description" : "Execute a portable MBQL 5 representations JSON query and stream the results, with\n continuation-token pagination.\n\n Accepts either a JSON body (same shape as /v2/construct-query) or a `continuation_token`\n from a previous response. Returns results with column metadata and an optional\n `continuation_token` for fetching the next page.", "parameters" : [ ], "responses" : { "2XX" : { @@ -15172,6 +15366,78 @@ "tags" : [ "/api/analytics" ] } }, + "/api/analytics/internal" : { + "post" : { + "operationId" : "post-api-analytics-internal", + "summary" : "POST /api/analytics/internal", + "description" : "Receive a batch of internal analytics events from the frontend and record them as Prometheus metrics.", + "parameters" : [ ], + "responses" : { + "2XX" : { + "description" : "Successful response", + "content" : { + "application/json" : { + "schema" : { + "type" : "null" + } + } + } + }, + "4XX" : { + "description" : "Client error response" + }, + "5XX" : { + "description" : "Server error response" + } + }, + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "type" : "object", + "properties" : { + "events" : { + "type" : "array", + "items" : { + "type" : "object", + "properties" : { + "amount" : { + "oneOf" : [ { + "type" : "number" + }, { + "type" : "null" + } ] + }, + "labels" : { + "oneOf" : [ { + "type" : "object", + "additionalProperties" : { + "type" : "string" + } + }, { + "type" : "null" + } ] + }, + "metric" : { + "type" : "string" + }, + "op" : { + "type" : "string", + "enum" : [ "inc", "dec", "set", "observe", "clear" ] + } + }, + "required" : [ "op", "metric" ] + } + } + }, + "required" : [ "events" ] + } + } + } + }, + "tags" : [ "/api/analytics" ] + } + }, "/api/api-key" : { "post" : { "operationId" : "post-api-api-key", @@ -16643,6 +16909,26 @@ "type" : "string", "minLength" : 1 }, + "size" : { + "oneOf" : [ { + "type" : "object", + "properties" : { + "size_x" : { + "description" : "value must be an integer greater than zero.", + "type" : "integer", + "minimum" : 1 + }, + "size_y" : { + "description" : "value must be an integer greater than zero.", + "type" : "integer", + "minimum" : 1 + } + }, + "required" : [ "size_x", "size_y" ] + }, { + "type" : "null" + } ] + }, "parameters" : { "oneOf" : [ { "$ref" : "#/components/schemas/metabase.parameters.schema.parameters" @@ -18268,7 +18554,7 @@ "type" : "array", "items" : { "type" : "string", - "enum" : [ "dashboard", "table", "dataset", "no_models", "timeline", "snippet", "collection", "transform", "document", "pulse", "metric", "card" ] + "enum" : [ "dashboard", "table", "dataset", "no_models", "timeline", "snippet", "collection", "measure", "transform", "document", "pulse", "metric", "card" ] } }, { "type" : "null" @@ -18796,7 +19082,7 @@ "type" : "array", "items" : { "type" : "string", - "enum" : [ "dashboard", "table", "dataset", "no_models", "timeline", "snippet", "collection", "transform", "document", "pulse", "metric", "card" ] + "enum" : [ "dashboard", "table", "dataset", "no_models", "timeline", "snippet", "collection", "measure", "transform", "document", "pulse", "metric", "card" ] } }, { "type" : "null" @@ -21071,94 +21357,6 @@ "tags" : [ "/api/database" ] } }, - "/api/database/field-values" : { - "get" : { - "operationId" : "get-api-database-field-values", - "summary" : "GET /api/database/field-values", - "description" : "Get sampled field values for every field in the instance, streamed as a single\n `{\"field_values\": [...]}` document. Each entry carries `field_id`, `values`,\n optional `human_readable_values`, and `has_more_values`.\n\n Only unconstrained (`:full`) FieldValues are included — sandboxed, impersonation, and\n linked-filter variants are user-specific and would bypass their own enforcement\n mechanisms in a bulk export. Pair with `GET /api/database/metadata` to resolve\n `field_id` to table and field names. Response is streamed for efficiency with large\n schemas.\n\n Admin-only: this endpoint exposes cached values computed over the unrestricted\n dataset, so it would leak data past sandbox / impersonation rules if served to\n regular users.", - "parameters" : [ ], - "responses" : { - "2XX" : { - "description" : "Successful response", - "content" : { - "application/json" : { - "schema" : { - "$ref" : "#/components/schemas/metabase.warehouses-rest.api.field-values-response" - } - } - } - }, - "4XX" : { - "description" : "Client error response" - }, - "5XX" : { - "description" : "Server error response" - } - }, - "tags" : [ "/api/database" ] - } - }, - "/api/database/metadata" : { - "get" : { - "operationId" : "get-api-database-metadata", - "summary" : "GET /api/database/metadata", - "description" : "Get metadata (databases, tables, and fields) for all databases visible to the current user.\n Returns a flat structure with three arrays: databases, tables, and fields.\n Response is streamed for efficiency with large schemas.\n\n Requires `View data` → `Can view` and `Create queries` → `Query builder only` (or\n `Query builder and native`) permissions on each database and table.", - "parameters" : [ ], - "responses" : { - "2XX" : { - "description" : "Successful response", - "content" : { - "application/json" : { - "schema" : { - "$ref" : "#/components/schemas/metabase.warehouses-rest.api.databases-metadata-response" - } - } - } - }, - "4XX" : { - "description" : "Client error response" - }, - "5XX" : { - "description" : "Server error response" - } - }, - "tags" : [ "/api/database" ] - }, - "post" : { - "operationId" : "post-api-database-metadata", - "summary" : "POST /api/database/metadata", - "description" : "Import database/table/field metadata previously exported from `GET /api/database/metadata`.\n\n Entities are matched by natural key — databases by `(name, engine)`, tables by\n `(database, schema, name)`, fields by `(table, parent-path, name)` — so the numeric ids\n in the payload are only used to link fields to their tables within the request.\n\n Tables and fields that don't exist on the target are created when their parent\n (database for tables; table for fields) is present on the target. Databases are\n not auto-created — missing databases are reported instead. Field `fk_target_field_id`\n is re-resolved through the natural-key lookup after all fields exist.\n\n For matched entities, only user-editable metadata is written: table `description`;\n field `description`, `semantic_type`, `coercion_strategy`, `effective_type`, and\n `fk_target_field_id`. For newly-created fields, `base_type` and `database_type` are\n also populated from the payload. Keys absent from the payload (including null values)\n are left untouched on matched entities.\n\n Processing is isolated per target database: each matched DB imports in its own\n transaction so a failure on one DB does not roll back the others. DBs whose\n transaction failed appear under `databases.failed` in the response along with\n the error message; every other DB's tables, fields, and same-DB `fk_target_field_id`\n references still commit. Cross-database `fk_target_field_id` references are\n resolved in a final pass after all per-DB transactions have committed.\n\n Returns counts of matched + created entities per type, a list of entities in the\n payload that could not be placed (their parent was missing on the target), and,\n when any DB failed, a `databases.failed` list naming each failed DB.", - "parameters" : [ ], - "responses" : { - "2XX" : { - "description" : "Successful response", - "content" : { - "application/json" : { - "schema" : { - "$ref" : "#/components/schemas/metabase.warehouses-rest.api.metadata-import-report" - } - } - } - }, - "4XX" : { - "description" : "Client error response" - }, - "5XX" : { - "description" : "Server error response" - } - }, - "requestBody" : { - "content" : { - "application/json" : { - "schema" : { - "$ref" : "#/components/schemas/metabase.warehouses-rest.api.databases-metadata-response" - } - } - } - }, - "tags" : [ "/api/database" ] - } - }, "/api/database/sample_database" : { "post" : { "operationId" : "post-api-database-sample_database", @@ -21392,6 +21590,15 @@ "type" : "null" } ] }, + "admin_details" : { + "oneOf" : [ { + "description" : "Value must be a map.", + "type" : "object", + "properties" : { } + }, { + "type" : "null" + } ] + }, "refingerprint" : { "oneOf" : [ { "type" : "boolean" @@ -21863,6 +22070,17 @@ "type" : "null" } ] } + }, { + "in" : "query", + "name" : "include_measures", + "required" : false, + "schema" : { + "oneOf" : [ { + "type" : "boolean" + }, { + "type" : "null" + } ] + } } ], "responses" : { "2XX" : { @@ -21946,6 +22164,17 @@ "type" : "null" } ] } + }, { + "in" : "query", + "name" : "include_measures", + "required" : false, + "schema" : { + "oneOf" : [ { + "type" : "boolean" + }, { + "type" : "null" + } ] + } } ], "responses" : { "2XX" : { @@ -22324,7 +22553,7 @@ "post" : { "operationId" : "post-api-dataset-native", "summary" : "POST /api/dataset/native", - "description" : "Fetch a native version of an MBQL query.", + "description" : "Fetch a native version of an MBQL query.\n\n Display path: workspace remapping is suppressed via\n [[ws.table-remapping/with-display-context]] so the user sees canonical-schema SQL\n in the 'Show me the SQL' panel. The query still executes against the workspace\n isolation schema at warehouse time (separate code path); this endpoint only\n affects what the user reads.", "parameters" : [ ], "responses" : { "2XX" : { @@ -23436,6 +23665,55 @@ "tags" : [ "/api/ee/action-v2" ] } }, + "/api/ee/advanced-config" : { + "post" : { + "operationId" : "post-api-ee-advanced-config", + "summary" : "POST /api/ee/advanced-config", + "description" : "Apply an uploaded `config.yml` to this instance. Runs the same per-section\n initializers (`settings`, `databases`, `users`, `api-keys`, `workspace`, ...)\n the boot-time loader runs. Superuser-only.\n\n Unlike the boot-time loader, `{{env VAR}}` templates are NOT expanded — the\n file's values are inserted verbatim, so an admin's upload can't read\n server-side environment variables it didn't intend to.", + "parameters" : [ ], + "responses" : { + "2XX" : { + "description" : "Successful response", + "content" : { + "application/json" : { + "schema" : { + "type" : "null" + } + } + } + }, + "4XX" : { + "description" : "Client error response" + }, + "5XX" : { + "description" : "Server error response" + } + }, + "requestBody" : { + "content" : { + "multipart/form-data" : { + "schema" : { + "type" : "object", + "properties" : { + "config" : { + "type" : "object", + "properties" : { + "filename" : { + "type" : "string" + }, + "tempfile" : { } + }, + "required" : [ "filename", "tempfile" ] + } + }, + "required" : [ "config" ] + } + } + } + }, + "tags" : [ "/api/ee/advanced-config" ] + } + }, "/api/ee/advanced-permissions/application/graph" : { "get" : { "operationId" : "get-api-ee-advanced-permissions-application-graph", @@ -23597,6 +23875,9 @@ "schema" : { "type" : "object", "properties" : { + "advanced" : { + "type" : "boolean" + }, "permissions" : { "type" : "array", "items" : { @@ -23619,7 +23900,7 @@ } } }, - "required" : [ "permissions" ] + "required" : [ "permissions", "advanced" ] } } } @@ -23646,6 +23927,9 @@ "schema" : { "type" : "object", "properties" : { + "advanced" : { + "type" : "boolean" + }, "permissions" : { "type" : "array", "items" : { @@ -23668,7 +23952,7 @@ } } }, - "required" : [ "permissions" ] + "required" : [ "permissions", "advanced" ] } } } @@ -23716,6 +24000,112 @@ "tags" : [ "/api/ee/ai-controls/permissions" ] } }, + "/api/ee/ai-controls/permissions/advanced" : { + "post" : { + "operationId" : "post-api-ee-ai-controls-permissions-advanced", + "summary" : "POST /api/ee/ai-controls/permissions/advanced", + "description" : "Switch to advanced group-level permissions. Removes any custom permissions from the All Users group.", + "parameters" : [ ], + "responses" : { + "2XX" : { + "description" : "Successful response", + "content" : { + "application/json" : { + "schema" : { + "type" : "object", + "properties" : { + "advanced" : { + "type" : "boolean" + }, + "permissions" : { + "type" : "array", + "items" : { + "type" : "object", + "properties" : { + "group_id" : { + "type" : "integer", + "minimum" : 1 + }, + "perm_type" : { + "type" : "string", + "enum" : [ "permission/metabot", "permission/metabot-nlq", "permission/metabot-other-tools", "permission/metabot-sql-generation" ] + }, + "perm_value" : { + "type" : "string", + "enum" : [ "yes", "no" ] + } + }, + "required" : [ "group_id", "perm_type", "perm_value" ] + } + } + }, + "required" : [ "permissions", "advanced" ] + } + } + } + }, + "4XX" : { + "description" : "Client error response" + }, + "5XX" : { + "description" : "Server error response" + } + }, + "tags" : [ "/api/ee/ai-controls/permissions" ] + }, + "delete" : { + "operationId" : "delete-api-ee-ai-controls-permissions-advanced", + "summary" : "DELETE /api/ee/ai-controls/permissions/advanced", + "description" : "Switch back to simple permissions. Removes any custom permissions from all specific groups, keeping only Admins and All Users.", + "parameters" : [ ], + "responses" : { + "2XX" : { + "description" : "Successful response", + "content" : { + "application/json" : { + "schema" : { + "type" : "object", + "properties" : { + "advanced" : { + "type" : "boolean" + }, + "permissions" : { + "type" : "array", + "items" : { + "type" : "object", + "properties" : { + "group_id" : { + "type" : "integer", + "minimum" : 1 + }, + "perm_type" : { + "type" : "string", + "enum" : [ "permission/metabot", "permission/metabot-nlq", "permission/metabot-other-tools", "permission/metabot-sql-generation" ] + }, + "perm_value" : { + "type" : "string", + "enum" : [ "yes", "no" ] + } + }, + "required" : [ "group_id", "perm_type", "perm_value" ] + } + } + }, + "required" : [ "permissions", "advanced" ] + } + } + } + }, + "4XX" : { + "description" : "Client error response" + }, + "5XX" : { + "description" : "Server error response" + } + }, + "tags" : [ "/api/ee/ai-controls/permissions" ] + } + }, "/api/ee/ai-controls/usage/group" : { "get" : { "operationId" : "get-api-ee-ai-controls-usage-group", @@ -24550,11 +24940,11 @@ "tags" : [ "/api/ee/content-translation" ] } }, - "/api/ee/data-studio/table/publish-tables" : { + "/api/ee/custom-viz-plugin" : { "post" : { - "operationId" : "post-api-ee-data-studio-table-publish-tables", - "summary" : "POST /api/ee/data-studio/table/publish-tables", - "description" : "Set collection for each of selected tables and all upstream dependencies recursively.", + "operationId" : "post-api-ee-custom-viz-plugin", + "summary" : "POST /api/ee/custom-viz-plugin", + "description" : "Register a new custom visualization plugin from an uploaded tar.gz bundle.\n\n The archive must contain `metabase-plugin.json` at the root and\n `dist/index.js` for the JS bundle, plus any whitelisted assets under\n `dist/assets/`. The plugin's `identifier` is taken from the manifest's `name`\n field.", "parameters" : [ ], "responses" : { "2XX" : { @@ -24562,7 +24952,75 @@ "content" : { "application/json" : { "schema" : { - "$ref" : "#/components/schemas/metabase-enterprise.data-studio.api.table.publish-tables-response" + "type" : "object", + "properties" : { + "enabled" : { + "type" : "boolean" + }, + "id" : { + "description" : "value must be an integer greater than zero.", + "type" : "integer", + "minimum" : 1 + }, + "updated_at" : { }, + "status" : { + "type" : "string", + "enum" : [ "active", "error" ] + }, + "error_message" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "identifier" : { + "type" : "string", + "minLength" : 1 + }, + "display_name" : { + "type" : "string", + "minLength" : 1 + }, + "dev_only" : { + "type" : "boolean" + }, + "created_at" : { }, + "bundle_hash" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "manifest" : { + "oneOf" : [ { }, { + "type" : "null" + } ] + }, + "dev_bundle_url" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "metabase_version" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "icon" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + } + }, + "required" : [ "id", "display_name", "identifier", "status", "enabled", "dev_only", "created_at", "updated_at" ] } } } @@ -24576,21 +25034,32 @@ }, "requestBody" : { "content" : { - "application/json" : { + "multipart/form-data" : { "schema" : { - "$ref" : "#/components/schemas/metabase-enterprise.data-studio.api.table.table-selectors" + "type" : "object", + "properties" : { + "file" : { + "type" : "object", + "properties" : { + "filename" : { + "type" : "string" + }, + "tempfile" : { } + }, + "required" : [ "filename", "tempfile" ] + } + }, + "required" : [ "file" ] } } } }, - "tags" : [ "/api/ee/data-studio/table" ] - } - }, - "/api/ee/data-studio/table/unpublish-tables" : { - "post" : { - "operationId" : "post-api-ee-data-studio-table-unpublish-tables", - "summary" : "POST /api/ee/data-studio/table/unpublish-tables", - "description" : "Unset collection for each of selected tables and all downstream dependents recursively.", + "tags" : [ "/api/ee/custom-viz-plugin" ] + }, + "get" : { + "operationId" : "get-api-ee-custom-viz-plugin", + "summary" : "GET /api/ee/custom-viz-plugin", + "description" : "List all registered custom visualization plugins.", "parameters" : [ ], "responses" : { "2XX" : { @@ -24598,7 +25067,78 @@ "content" : { "application/json" : { "schema" : { - "type" : "null" + "type" : "array", + "items" : { + "type" : "object", + "properties" : { + "enabled" : { + "type" : "boolean" + }, + "id" : { + "description" : "value must be an integer greater than zero.", + "type" : "integer", + "minimum" : 1 + }, + "updated_at" : { }, + "status" : { + "type" : "string", + "enum" : [ "active", "error" ] + }, + "error_message" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "identifier" : { + "type" : "string", + "minLength" : 1 + }, + "display_name" : { + "type" : "string", + "minLength" : 1 + }, + "dev_only" : { + "type" : "boolean" + }, + "created_at" : { }, + "bundle_hash" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "manifest" : { + "oneOf" : [ { }, { + "type" : "null" + } ] + }, + "dev_bundle_url" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "metabase_version" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "icon" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + } + }, + "required" : [ "id", "display_name", "identifier", "status", "enabled", "dev_only", "created_at", "updated_at" ] + } } } } @@ -24610,36 +25150,93 @@ "description" : "Server error response" } }, - "requestBody" : { - "content" : { - "application/json" : { - "schema" : { - "$ref" : "#/components/schemas/metabase-enterprise.data-studio.api.table.table-selectors" - } - } - } - }, - "tags" : [ "/api/ee/data-studio/table" ] + "tags" : [ "/api/ee/custom-viz-plugin" ] } }, - "/api/ee/database-replication/connection/{database-id}" : { + "/api/ee/custom-viz-plugin/dev" : { "post" : { - "operationId" : "post-api-ee-database-replication-connection-database-id", - "summary" : "POST /api/ee/database-replication/connection/{database-id}", - "description" : "Create a new PG replication connection for the specified database.", - "parameters" : [ { - "in" : "path", - "name" : "database-id", - "required" : true, - "schema" : { - "type" : "integer", - "minimum" : 1 - }, - "description" : "value must be an integer greater than zero." - } ], + "operationId" : "post-api-ee-custom-viz-plugin-dev", + "summary" : "POST /api/ee/custom-viz-plugin/dev", + "description" : "Register a dev-only custom visualization plugin from a local dev server.\n No bundle upload is required — files are served from the dev server URL.\n Requires custom viz plugin dev mode to be enabled.", + "parameters" : [ ], "responses" : { "2XX" : { - "description" : "Successful response" + "description" : "Successful response", + "content" : { + "application/json" : { + "schema" : { + "type" : "object", + "properties" : { + "enabled" : { + "type" : "boolean" + }, + "id" : { + "description" : "value must be an integer greater than zero.", + "type" : "integer", + "minimum" : 1 + }, + "updated_at" : { }, + "status" : { + "type" : "string", + "enum" : [ "active", "error" ] + }, + "error_message" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "identifier" : { + "type" : "string", + "minLength" : 1 + }, + "display_name" : { + "type" : "string", + "minLength" : 1 + }, + "dev_only" : { + "type" : "boolean" + }, + "created_at" : { }, + "bundle_hash" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "manifest" : { + "oneOf" : [ { }, { + "type" : "null" + } ] + }, + "dev_bundle_url" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "metabase_version" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "icon" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + } + }, + "required" : [ "id", "display_name", "identifier", "status", "enabled", "dev_only", "created_at", "updated_at" ] + } + } + } }, "4XX" : { "description" : "Client error response" @@ -24654,33 +25251,111 @@ "schema" : { "type" : "object", "properties" : { - "replicationSchemaFilters" : { + "dev_bundle_url" : { + "type" : "string", + "minLength" : 1 + }, + "identifier" : { + "oneOf" : [ { + "type" : "string", + "minLength" : 1 + }, { + "type" : "null" + } ] + } + }, + "required" : [ "dev_bundle_url" ] + } + } + } + }, + "tags" : [ "/api/ee/custom-viz-plugin" ] + } + }, + "/api/ee/custom-viz-plugin/list" : { + "get" : { + "operationId" : "get-api-ee-custom-viz-plugin-list", + "summary" : "GET /api/ee/custom-viz-plugin/list", + "description" : "List active and enabled custom visualization plugins. Available to any authenticated user.\n Plugins with incompatible Metabase version requirements are excluded.\n Dev-only plugins are excluded when dev mode is disabled.", + "parameters" : [ ], + "responses" : { + "2XX" : { + "description" : "Successful response", + "content" : { + "application/json" : { + "schema" : { + "type" : "array", + "items" : { "type" : "object", "properties" : { - "schema-filters-patterns" : { - "type" : "string" + "bundle_hash" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] }, - "schema-filters-type" : { + "bundle_url" : { "type" : "string", - "enum" : [ "inclusion", "exclusion", "all" ] + "minLength" : 1 + }, + "dev_bundle_url" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "display_name" : { + "type" : "string", + "minLength" : 1 + }, + "icon" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "id" : { + "description" : "value must be an integer greater than zero.", + "type" : "integer", + "minimum" : 1 + }, + "identifier" : { + "type" : "string", + "minLength" : 1 + }, + "manifest" : { + "oneOf" : [ { }, { + "type" : "null" + } ] } }, - "required" : [ "schema-filters-type", "schema-filters-patterns" ] + "required" : [ "id", "identifier", "display_name", "bundle_url" ] } } } } + }, + "4XX" : { + "description" : "Client error response" + }, + "5XX" : { + "description" : "Server error response" } }, - "tags" : [ "/api/ee/database-replication" ] - }, + "tags" : [ "/api/ee/custom-viz-plugin" ] + } + }, + "/api/ee/custom-viz-plugin/{id}" : { "delete" : { - "operationId" : "delete-api-ee-database-replication-connection-database-id", - "summary" : "DELETE /api/ee/database-replication/connection/{database-id}", - "description" : "Delete PG replication connection for the specified database.", + "operationId" : "delete-api-ee-custom-viz-plugin-id", + "summary" : "DELETE /api/ee/custom-viz-plugin/{id}", + "description" : "Remove a custom visualization plugin and evict its on-disk cache.", "parameters" : [ { "in" : "path", - "name" : "database-id", + "name" : "id", "required" : true, "schema" : { "type" : "integer", @@ -24690,7 +25365,14 @@ } ], "responses" : { "2XX" : { - "description" : "Successful response" + "description" : "Successful response", + "content" : { + "application/json" : { + "schema" : { + "type" : "null" + } + } + } }, "4XX" : { "description" : "Client error response" @@ -24699,17 +25381,15 @@ "description" : "Server error response" } }, - "tags" : [ "/api/ee/database-replication" ] - } - }, - "/api/ee/database-replication/connection/{database-id}/preview" : { - "post" : { - "operationId" : "post-api-ee-database-replication-connection-database-id-preview", - "summary" : "POST /api/ee/database-replication/connection/{database-id}/preview", - "description" : "Return info about pg-replication connection that is about to be created.", + "tags" : [ "/api/ee/custom-viz-plugin" ] + }, + "put" : { + "operationId" : "put-api-ee-custom-viz-plugin-id", + "summary" : "PUT /api/ee/custom-viz-plugin/{id}", + "description" : "Update a custom visualization plugin. Currently only `enabled` may be toggled.", "parameters" : [ { "in" : "path", - "name" : "database-id", + "name" : "id", "required" : true, "schema" : { "type" : "integer", @@ -24719,7 +25399,82 @@ } ], "responses" : { "2XX" : { - "description" : "Successful response" + "description" : "Successful response", + "content" : { + "application/json" : { + "schema" : { + "type" : "object", + "properties" : { + "enabled" : { + "type" : "boolean" + }, + "id" : { + "description" : "value must be an integer greater than zero.", + "type" : "integer", + "minimum" : 1 + }, + "updated_at" : { }, + "status" : { + "type" : "string", + "enum" : [ "active", "error" ] + }, + "error_message" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "identifier" : { + "type" : "string", + "minLength" : 1 + }, + "display_name" : { + "type" : "string", + "minLength" : 1 + }, + "dev_only" : { + "type" : "boolean" + }, + "created_at" : { }, + "bundle_hash" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "manifest" : { + "oneOf" : [ { }, { + "type" : "null" + } ] + }, + "dev_bundle_url" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "metabase_version" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "icon" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + } + }, + "required" : [ "id", "display_name", "identifier", "status", "enabled", "dev_only", "created_at", "updated_at" ] + } + } + } }, "4XX" : { "description" : "Client error response" @@ -24734,43 +25489,52 @@ "schema" : { "type" : "object", "properties" : { - "replicationSchemaFilters" : { - "type" : "object", - "properties" : { - "schema-filters-patterns" : { - "type" : "string" - }, - "schema-filters-type" : { - "type" : "string", - "enum" : [ "inclusion", "exclusion", "all" ] - } - }, - "required" : [ "schema-filters-type", "schema-filters-patterns" ] + "enabled" : { + "oneOf" : [ { + "type" : "boolean" + }, { + "type" : "null" + } ] } } } } } }, - "tags" : [ "/api/ee/database-replication" ] + "tags" : [ "/api/ee/custom-viz-plugin" ] } }, - "/api/ee/database-routing/destination-database" : { - "post" : { - "operationId" : "post-api-ee-database-routing-destination-database", - "summary" : "POST /api/ee/database-routing/destination-database", - "description" : "Create new Destination Databases.\n\n Note that unlike the normal `POST /api/database` endpoint, does NOT check the details before adding the Database.\n\n This is OK, it's not an invariant that all database details are always valid, but it's something to note.", + "/api/ee/custom-viz-plugin/{id}/asset" : { + "get" : { + "operationId" : "get-api-ee-custom-viz-plugin-id-asset", + "summary" : "GET /api/ee/custom-viz-plugin/{id}/asset", + "description" : "Serve a static image asset from the plugin's bundle.\n The asset path is passed as a `path` query parameter (e.g. `?path=icon.svg`)\n and must match an entry in the manifest's `assets` whitelist.\n Only image files are served.\n In dev mode, proxies from the dev base URL if set.", "parameters" : [ { + "in" : "path", + "name" : "id", + "required" : true, + "schema" : { + "type" : "integer", + "minimum" : 1 + }, + "description" : "value must be an integer greater than zero." + }, { "in" : "query", - "name" : "check_connection_details", - "required" : false, + "name" : "path", + "required" : true, "schema" : { - "type" : "boolean" + "type" : "string", + "minLength" : 1 } } ], "responses" : { "2XX" : { - "description" : "Successful response" + "description" : "Successful response", + "content" : { + "application/json" : { + "schema" : { } + } + } }, "4XX" : { "description" : "Client error response" @@ -24779,49 +25543,14 @@ "description" : "Server error response" } }, - "requestBody" : { - "content" : { - "application/json" : { - "schema" : { - "type" : "object", - "properties" : { - "destinations" : { - "type" : "array", - "items" : { - "type" : "object", - "properties" : { - "details" : { - "description" : "Value must be a map.", - "type" : "object", - "properties" : { } - }, - "name" : { - "type" : "string", - "minLength" : 1 - } - }, - "required" : [ "name", "details" ] - } - }, - "router_database_id" : { - "description" : "value must be an integer greater than zero.", - "type" : "integer", - "minimum" : 1 - } - }, - "required" : [ "router_database_id", "destinations" ] - } - } - } - }, - "tags" : [ "/api/ee/database-routing" ] + "tags" : [ "/api/ee/custom-viz-plugin" ] } }, - "/api/ee/database-routing/router-database/{id}" : { + "/api/ee/custom-viz-plugin/{id}/bundle" : { "put" : { - "operationId" : "put-api-ee-database-routing-router-database-id", - "summary" : "PUT /api/ee/database-routing/router-database/{id}", - "description" : "Updates an existing Database with the `user_attribute` to route on. Will either:\n - turn an existing Database into a Router database\n - change the `user_attribute` used to route for an existing Router database, or\n - turn a Router database into a regular Database\n depending on the value of `user_attribute`", + "operationId" : "put-api-ee-custom-viz-plugin-id-bundle", + "summary" : "PUT /api/ee/custom-viz-plugin/{id}/bundle", + "description" : "Replace the bundle for an existing plugin. Accepts a multipart tar.gz upload in\n the same format as the `POST /` endpoint. The manifest's `name` field must\n match the plugin's existing `identifier`.", "parameters" : [ { "in" : "path", "name" : "id", @@ -24832,45 +25561,6 @@ }, "description" : "value must be an integer greater than zero." } ], - "responses" : { - "2XX" : { - "description" : "Successful response" - }, - "4XX" : { - "description" : "Client error response" - }, - "5XX" : { - "description" : "Server error response" - } - }, - "requestBody" : { - "content" : { - "application/json" : { - "schema" : { - "type" : "object", - "properties" : { - "user_attribute" : { - "oneOf" : [ { - "type" : "string", - "minLength" : 1 - }, { - "type" : "null" - } ] - } - } - } - } - } - }, - "tags" : [ "/api/ee/database-routing" ] - } - }, - "/api/ee/dependencies/backfill-status" : { - "get" : { - "operationId" : "get-api-ee-dependencies-backfill-status", - "summary" : "GET /api/ee/dependencies/backfill-status", - "description" : "Returns whether the dependency backfill has pending work.\n `complete` is true when there are no stale or outdated entities awaiting processing.", - "parameters" : [ ], "responses" : { "2XX" : { "description" : "Successful response", @@ -24879,11 +25569,73 @@ "schema" : { "type" : "object", "properties" : { - "complete" : { + "enabled" : { + "type" : "boolean" + }, + "id" : { + "description" : "value must be an integer greater than zero.", + "type" : "integer", + "minimum" : 1 + }, + "updated_at" : { }, + "status" : { + "type" : "string", + "enum" : [ "active", "error" ] + }, + "error_message" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "identifier" : { + "type" : "string", + "minLength" : 1 + }, + "display_name" : { + "type" : "string", + "minLength" : 1 + }, + "dev_only" : { "type" : "boolean" + }, + "created_at" : { }, + "bundle_hash" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "manifest" : { + "oneOf" : [ { }, { + "type" : "null" + } ] + }, + "dev_bundle_url" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "metabase_version" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "icon" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] } }, - "required" : [ "complete" ] + "required" : [ "id", "display_name", "identifier", "status", "enabled", "dev_only", "created_at", "updated_at" ] } } } @@ -24895,23 +25647,50 @@ "description" : "Server error response" } }, - "tags" : [ "/api/ee/dependencies" ] - } - }, - "/api/ee/dependencies/check-card" : { - "post" : { - "operationId" : "post-api-ee-dependencies-check-card", - "summary" : "POST /api/ee/dependencies/check-card", - "description" : "Check a proposed edit to a card, and return the card IDs for those cards this edit will break.", - "parameters" : [ ], + "requestBody" : { + "content" : { + "multipart/form-data" : { + "schema" : { + "type" : "object", + "properties" : { + "file" : { + "type" : "object", + "properties" : { + "filename" : { + "type" : "string" + }, + "tempfile" : { } + }, + "required" : [ "filename", "tempfile" ] + } + }, + "required" : [ "file" ] + } + } + } + }, + "tags" : [ "/api/ee/custom-viz-plugin" ] + }, + "get" : { + "operationId" : "get-api-ee-custom-viz-plugin-id-bundle", + "summary" : "GET /api/ee/custom-viz-plugin/{id}/bundle", + "description" : "Serve the JS bundle for a plugin from the on-disk cache.\n Returns application/javascript with ETag and Cache-Control headers.\n In dev mode, proxies from `dev_bundle_url` if set.", + "parameters" : [ { + "in" : "path", + "name" : "id", + "required" : true, + "schema" : { + "type" : "integer", + "minimum" : 1 + }, + "description" : "value must be an integer greater than zero." + } ], "responses" : { "2XX" : { "description" : "Successful response", "content" : { "application/json" : { - "schema" : { - "$ref" : "#/components/schemas/metabase-enterprise.dependencies.api.broken-cards-response" - } + "schema" : { } } } }, @@ -24922,32 +25701,30 @@ "description" : "Server error response" } }, - "requestBody" : { - "content" : { - "application/json" : { - "schema" : { - "$ref" : "#/components/schemas/metabase-enterprise.dependencies.api.card-body" - } - } - } - }, - "tags" : [ "/api/ee/dependencies" ] + "tags" : [ "/api/ee/custom-viz-plugin" ] } }, - "/api/ee/dependencies/check-snippet" : { - "post" : { - "operationId" : "post-api-ee-dependencies-check-snippet", - "summary" : "POST /api/ee/dependencies/check-snippet", - "description" : "Check a proposed edit to a native snippet, and return the cards, etc. which will be broken.", - "parameters" : [ ], + "/api/ee/custom-viz-plugin/{id}/dev-sse" : { + "get" : { + "operationId" : "get-api-ee-custom-viz-plugin-id-dev-sse", + "summary" : "GET /api/ee/custom-viz-plugin/{id}/dev-sse", + "description" : "Proxy Server-Sent Events from the plugin's dev server.\n Connects to `{dev_bundle_url}/__sse` and forwards events to the browser.\n This avoids the need for a CSP exception for the dev server origin.\n Requires custom viz plugin dev mode to be enabled.", + "parameters" : [ { + "in" : "path", + "name" : "id", + "required" : true, + "schema" : { + "type" : "integer", + "minimum" : 1 + }, + "description" : "value must be an integer greater than zero." + } ], "responses" : { "2XX" : { "description" : "Successful response", "content" : { "application/json" : { - "schema" : { - "$ref" : "#/components/schemas/metabase-enterprise.dependencies.api.broken-cards-response" - } + "schema" : { } } } }, @@ -24958,43 +25735,41 @@ "description" : "Server error response" } }, - "requestBody" : { - "content" : { - "application/json" : { - "schema" : { - "type" : "object", - "properties" : { - "content" : { - "type" : "string" - }, - "id" : { - "$ref" : "#/components/schemas/metabase.lib.schema.id.snippet" - }, - "name" : { - "description" : "snippet names cannot include '}' or start with spaces" - } - }, - "required" : [ "id" ] - } - } - } - }, - "tags" : [ "/api/ee/dependencies" ] + "tags" : [ "/api/ee/custom-viz-plugin" ] } }, - "/api/ee/dependencies/check-transform" : { - "post" : { - "operationId" : "post-api-ee-dependencies-check-transform", - "summary" : "POST /api/ee/dependencies/check-transform", - "description" : "Check a proposed edit to a transform, and return the card, transform, etc. IDs for things that will break.", - "parameters" : [ ], + "/api/ee/custom-viz-plugin/{id}/dev-url" : { + "put" : { + "operationId" : "put-api-ee-custom-viz-plugin-id-dev-url", + "summary" : "PUT /api/ee/custom-viz-plugin/{id}/dev-url", + "description" : "Set or clear the dev base URL for a plugin (e.g. `http://localhost:5174`).\n The bundle is fetched from `{base}/index.js` and assets from `{base}/assets/{name}`.\n Persisted to the database so it survives server restarts.\n Requires custom viz plugin dev mode to be enabled.", + "parameters" : [ { + "in" : "path", + "name" : "id", + "required" : true, + "schema" : { + "type" : "integer", + "minimum" : 1 + }, + "description" : "value must be an integer greater than zero." + } ], "responses" : { "2XX" : { "description" : "Successful response", "content" : { "application/json" : { "schema" : { - "$ref" : "#/components/schemas/metabase-enterprise.dependencies.api.broken-cards-response" + "type" : "object", + "properties" : { + "dev_bundle_url" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + } + }, + "required" : [ "dev_bundle_url" ] } } } @@ -25010,42 +25785,38 @@ "content" : { "application/json" : { "schema" : { - "$ref" : "#/components/schemas/metabase-enterprise.dependencies.api.transform-body" + "type" : "object", + "properties" : { + "dev_bundle_url" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + } + }, + "required" : [ "dev_bundle_url" ] } } } }, - "tags" : [ "/api/ee/dependencies" ] + "tags" : [ "/api/ee/custom-viz-plugin" ] } }, - "/api/ee/dependencies/graph" : { - "get" : { - "operationId" : "get-api-ee-dependencies-graph", - "summary" : "GET /api/ee/dependencies/graph", - "description" : "This endpoint takes an :id and a supported entity :type, and returns a graph of all its upstream dependencies.\n The graph is represented by a list of :nodes and a list of :edges. Each node has an :id, :type, :data (which\n depends on the node type), and a map of :dependent_counts per entity type. Each edge is a :model/Dependency.\n\n Optional :archived parameter controls whether entities in archived collections are included:\n - false (default): Excludes entities in archived collections\n - true: Includes entities in archived collections", + "/api/ee/custom-viz-plugin/{id}/refresh" : { + "post" : { + "operationId" : "post-api-ee-custom-viz-plugin-id-refresh", + "summary" : "POST /api/ee/custom-viz-plugin/{id}/refresh", + "description" : "Re-fetch the manifest from the dev server for a dev-only plugin. For uploaded\n plugins this is a no-op — to update an upload-backed plugin, PUT a new bundle\n to `/:id/bundle`.", "parameters" : [ { - "in" : "query", + "in" : "path", "name" : "id", - "required" : false, + "required" : true, "schema" : { "type" : "integer", "minimum" : 1 }, "description" : "value must be an integer greater than zero." - }, { - "in" : "query", - "name" : "type", - "required" : false, - "schema" : { - "$ref" : "#/components/schemas/metabase-enterprise.dependencies.dependency-types.dependency-types" - } - }, { - "in" : "query", - "name" : "archived", - "required" : false, - "schema" : { - "type" : "boolean" - } } ], "responses" : { "2XX" : { @@ -25053,7 +25824,75 @@ "content" : { "application/json" : { "schema" : { - "$ref" : "#/components/schemas/metabase-enterprise.dependencies.api.graph-response" + "type" : "object", + "properties" : { + "enabled" : { + "type" : "boolean" + }, + "id" : { + "description" : "value must be an integer greater than zero.", + "type" : "integer", + "minimum" : 1 + }, + "updated_at" : { }, + "status" : { + "type" : "string", + "enum" : [ "active", "error" ] + }, + "error_message" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "identifier" : { + "type" : "string", + "minLength" : 1 + }, + "display_name" : { + "type" : "string", + "minLength" : 1 + }, + "dev_only" : { + "type" : "boolean" + }, + "created_at" : { }, + "bundle_hash" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "manifest" : { + "oneOf" : [ { }, { + "type" : "null" + } ] + }, + "dev_bundle_url" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "metabase_version" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "icon" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + } + }, + "required" : [ "id", "display_name", "identifier", "status", "enabled", "dev_only", "created_at", "updated_at" ] } } } @@ -25065,81 +25904,22 @@ "description" : "Server error response" } }, - "tags" : [ "/api/ee/dependencies" ] + "tags" : [ "/api/ee/custom-viz-plugin" ] } }, - "/api/ee/dependencies/graph/breaking" : { + "/api/ee/data-complexity-score/complexity" : { "get" : { - "operationId" : "get-api-ee-dependencies-graph-breaking", - "summary" : "GET /api/ee/dependencies/graph/breaking", - "description" : "Returns a list of entities that are breaking other entities (sources of errors).\n These are tables or cards that other entities depend on, where those dependents\n have validation errors traced back to this source entity.\n\n Accepts optional parameters for filtering:\n - `types`: List of source entity types - only `:card` or `:table` (default: both)\n - `card-types`: List of card types to include when filtering cards (e.g., `[:question :model :metric]`)\n - `query`: Search string to filter by name or location\n - `archived`: Controls whether archived entities are included\n - `include-personal-collections`: Controls whether items in personal collections are included (default: false)\n - `sort-column`: Sort column - `:name`, `:location`, `:dependents-errors`, or `:dependents-with-errors` (default: `:name`)\n - `sort-direction`: Sort direction - `:asc` or `:desc` (default: `:asc`)\n - `offset`: Default 0\n - `limit`: Default 50\n\n Returns a map with:\n - `data`: List of breaking source entities\n - `total`: Total count of matched items\n - `offset`: Applied offset\n - `limit`: Applied limit", + "operationId" : "get-api-ee-data-complexity-score-complexity", + "summary" : "GET /api/ee/data-complexity-score/complexity", + "description" : "Return the most recently stored Data Complexity Score for this instance.\n Pass `force-recalculation=true` to recompute, persist, and return a fresh score.\n Superuser-only.", "parameters" : [ { "in" : "query", - "name" : "types", - "required" : false, - "schema" : { - "anyOf" : [ { - "$ref" : "#/components/schemas/metabase-enterprise.dependencies.dependency-types.dependency-types" - }, { - "type" : "array", - "items" : { - "$ref" : "#/components/schemas/metabase-enterprise.dependencies.dependency-types.dependency-types" - } - } ] - } - }, { - "in" : "query", - "name" : "card-types", - "required" : false, - "schema" : { - "anyOf" : [ { - "type" : "string", - "enum" : [ "question", "metric", "model" ] - }, { - "type" : "array", - "items" : { - "type" : "string", - "enum" : [ "question", "metric", "model" ] - } - } ] - } - }, { - "in" : "query", - "name" : "query", - "required" : false, - "schema" : { - "type" : "string" - } - }, { - "in" : "query", - "name" : "archived", - "required" : false, - "schema" : { - "type" : "boolean" - } - }, { - "in" : "query", - "name" : "include-personal-collections", - "required" : false, + "name" : "force-recalculation", + "required" : true, "schema" : { + "default" : false, "type" : "boolean" } - }, { - "in" : "query", - "name" : "sort-column", - "required" : false, - "schema" : { - "type" : "string", - "enum" : [ "dependents-with-errors", "dependents-errors", "name", "location" ] - } - }, { - "in" : "query", - "name" : "sort-direction", - "required" : false, - "schema" : { - "type" : "string", - "enum" : [ "desc", "asc" ] - } } ], "responses" : { "2XX" : { @@ -25149,27 +25929,51 @@ "schema" : { "type" : "object", "properties" : { - "data" : { - "type" : "array", - "items" : { - "$ref" : "#/components/schemas/metabase-enterprise.dependencies.api.entity" - } + "library" : { + "$ref" : "#/components/schemas/metabase-enterprise.data-complexity-score.api.node" }, - "limit" : { - "description" : "value must be an integer greater than zero.", - "type" : "integer", - "minimum" : 1 + "meta" : { + "type" : "object", + "properties" : { + "calculated_at" : { }, + "embedding_model" : { + "oneOf" : [ { + "type" : "object", + "properties" : { + "model_name" : { + "type" : "string" + }, + "provider" : { + "type" : "string" + } + }, + "required" : [ "provider", "model_name" ] + }, { + "type" : "null" + } ] + }, + "format_version" : { + "type" : "integer", + "minimum" : 1 + }, + "formula_version" : { + "type" : "integer", + "minimum" : 1 + }, + "synonym_threshold" : { + "type" : "number" + } + }, + "required" : [ "formula_version", "format_version", "synonym_threshold" ] }, - "offset" : { - "type" : "integer", - "minimum" : 0 + "metabot" : { + "$ref" : "#/components/schemas/metabase-enterprise.data-complexity-score.api.node" }, - "total" : { - "type" : "integer", - "minimum" : 0 + "universe" : { + "$ref" : "#/components/schemas/metabase-enterprise.data-complexity-score.api.node" } }, - "required" : [ "data", "total", "offset", "limit" ] + "required" : [ "library", "universe", "metabot", "meta" ] } } } @@ -25181,94 +25985,22 @@ "description" : "Server error response" } }, - "tags" : [ "/api/ee/dependencies" ] + "tags" : [ "/api/ee/data-complexity-score" ] } }, - "/api/ee/dependencies/graph/broken" : { - "get" : { - "operationId" : "get-api-ee-dependencies-graph-broken", - "summary" : "GET /api/ee/dependencies/graph/broken", - "description" : "Returns the broken dependents for a specific source entity.\n These are entities that have validation errors traced back to the specified source.\n\n Required parameters:\n - `id`: The ID of the source entity\n - `type`: The type of the source entity (card, table)\n\n Optional parameters:\n - `dependent-types`: Dependency types to filter by. Can be single value or array.\n - `dependent-card-types`: Card types to filter by when dependent-types includes :card.\n - `include-personal-collections`: Include items in personal collections (default: false)\n - `sort-column`: Column to sort by - name, location, or view-count (default: name)\n - `sort-direction`: Sort direction - asc or desc (default: asc)", - "parameters" : [ { - "in" : "query", - "name" : "id", - "required" : true, - "schema" : { - "type" : "integer", - "minimum" : 1 - }, - "description" : "value must be an integer greater than zero." - }, { - "in" : "query", - "name" : "type", - "required" : true, - "schema" : { - "$ref" : "#/components/schemas/metabase-enterprise.dependencies.dependency-types.dependency-types" - } - }, { - "in" : "query", - "name" : "dependent-types", - "required" : false, - "schema" : { - "anyOf" : [ { - "$ref" : "#/components/schemas/metabase-enterprise.dependencies.dependency-types.dependency-types" - }, { - "type" : "array", - "items" : { - "$ref" : "#/components/schemas/metabase-enterprise.dependencies.dependency-types.dependency-types" - } - } ] - } - }, { - "in" : "query", - "name" : "dependent-card-types", - "required" : false, - "schema" : { - "anyOf" : [ { - "type" : "string", - "enum" : [ "question", "metric", "model" ] - }, { - "type" : "array", - "items" : { - "type" : "string", - "enum" : [ "question", "metric", "model" ] - } - } ] - } - }, { - "in" : "query", - "name" : "include-personal-collections", - "required" : false, - "schema" : { - "type" : "boolean" - } - }, { - "in" : "query", - "name" : "sort-column", - "required" : false, - "schema" : { - "type" : "string", - "enum" : [ "name", "view-count", "location" ] - } - }, { - "in" : "query", - "name" : "sort-direction", - "required" : false, - "schema" : { - "type" : "string", - "enum" : [ "desc", "asc" ] - } - } ], + "/api/ee/data-studio/table/publish-tables" : { + "post" : { + "operationId" : "post-api-ee-data-studio-table-publish-tables", + "summary" : "POST /api/ee/data-studio/table/publish-tables", + "description" : "Set collection for each of selected tables and all upstream dependencies recursively.", + "parameters" : [ ], "responses" : { "2XX" : { "description" : "Successful response", "content" : { "application/json" : { "schema" : { - "type" : "array", - "items" : { - "$ref" : "#/components/schemas/metabase-enterprise.dependencies.api.broken-dependent-entity" - } + "$ref" : "#/components/schemas/metabase-enterprise.data-studio.api.table.publish-tables-response" } } } @@ -25280,103 +26012,477 @@ "description" : "Server error response" } }, - "tags" : [ "/api/ee/dependencies" ] + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/metabase-enterprise.data-studio.api.table.publish-table-selectors" + } + } + } + }, + "tags" : [ "/api/ee/data-studio/table" ] } }, - "/api/ee/dependencies/graph/dependents" : { - "get" : { - "operationId" : "get-api-ee-dependencies-graph-dependents", - "summary" : "GET /api/ee/dependencies/graph/dependents", - "description" : "Returns a list of dependents for the specified entity.\n\n Required parameters:\n - `id`: The ID of the entity\n - `type`: The type of the entity (card, table, dashboard, etc.)\n\n Optional parameters:\n - `dependent-types`: Dependency types to filter by. Can be single value or array.\n If not provided, returns all types. Example: ?dependent-types=card&dependent-types=dashboard\n - `dependent-card-types`: Card types to filter by when dependent-types includes :card.\n Ignored if dependent-types doesn't include :card. Example: ?dependent-card-types=question&dependent-card-types=model\n - `archived`: Include entities in archived collections (default: false)\n - `broken`: Return only broken entities (default: false)\n - `query`: Search string to filter results by name or location (case-insensitive)\n - `include-personal-collections`: Include items in personal collections (default: false)\n - `sort-column`: Column to sort by - name, location, or view-count (default: name)\n - `sort-direction`: Sort direction - asc or desc (default: asc)", - "parameters" : [ { - "in" : "query", - "name" : "id", - "required" : true, + "/api/ee/data-studio/table/unpublish-tables" : { + "post" : { + "operationId" : "post-api-ee-data-studio-table-unpublish-tables", + "summary" : "POST /api/ee/data-studio/table/unpublish-tables", + "description" : "Unset collection for each of selected tables and all downstream dependents recursively.", + "parameters" : [ ], + "responses" : { + "2XX" : { + "description" : "Successful response", + "content" : { + "application/json" : { + "schema" : { + "type" : "null" + } + } + } + }, + "4XX" : { + "description" : "Client error response" + }, + "5XX" : { + "description" : "Server error response" + } + }, + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/metabase-enterprise.data-studio.api.table.table-selectors" + } + } + } + }, + "tags" : [ "/api/ee/data-studio/table" ] + } + }, + "/api/ee/database-replication/connection/{database-id}" : { + "post" : { + "operationId" : "post-api-ee-database-replication-connection-database-id", + "summary" : "POST /api/ee/database-replication/connection/{database-id}", + "description" : "Create a new PG replication connection for the specified database.", + "parameters" : [ { + "in" : "path", + "name" : "database-id", + "required" : true, "schema" : { "type" : "integer", "minimum" : 1 }, "description" : "value must be an integer greater than zero." - }, { - "in" : "query", - "name" : "type", + } ], + "responses" : { + "2XX" : { + "description" : "Successful response" + }, + "4XX" : { + "description" : "Client error response" + }, + "5XX" : { + "description" : "Server error response" + } + }, + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "type" : "object", + "properties" : { + "replicationSchemaFilters" : { + "type" : "object", + "properties" : { + "schema-filters-patterns" : { + "type" : "string" + }, + "schema-filters-type" : { + "type" : "string", + "enum" : [ "inclusion", "exclusion", "all" ] + } + }, + "required" : [ "schema-filters-type", "schema-filters-patterns" ] + } + } + } + } + } + }, + "tags" : [ "/api/ee/database-replication" ] + }, + "delete" : { + "operationId" : "delete-api-ee-database-replication-connection-database-id", + "summary" : "DELETE /api/ee/database-replication/connection/{database-id}", + "description" : "Delete PG replication connection for the specified database.", + "parameters" : [ { + "in" : "path", + "name" : "database-id", "required" : true, "schema" : { - "$ref" : "#/components/schemas/metabase-enterprise.dependencies.dependency-types.dependency-types" + "type" : "integer", + "minimum" : 1 + }, + "description" : "value must be an integer greater than zero." + } ], + "responses" : { + "2XX" : { + "description" : "Successful response" + }, + "4XX" : { + "description" : "Client error response" + }, + "5XX" : { + "description" : "Server error response" } - }, { - "in" : "query", - "name" : "dependent-types", - "required" : false, + }, + "tags" : [ "/api/ee/database-replication" ] + } + }, + "/api/ee/database-replication/connection/{database-id}/preview" : { + "post" : { + "operationId" : "post-api-ee-database-replication-connection-database-id-preview", + "summary" : "POST /api/ee/database-replication/connection/{database-id}/preview", + "description" : "Return info about pg-replication connection that is about to be created.", + "parameters" : [ { + "in" : "path", + "name" : "database-id", + "required" : true, "schema" : { - "anyOf" : [ { - "$ref" : "#/components/schemas/metabase-enterprise.dependencies.dependency-types.dependency-types" - }, { - "type" : "array", - "items" : { - "$ref" : "#/components/schemas/metabase-enterprise.dependencies.dependency-types.dependency-types" - } - } ] + "type" : "integer", + "minimum" : 1 + }, + "description" : "value must be an integer greater than zero." + } ], + "responses" : { + "2XX" : { + "description" : "Successful response" + }, + "4XX" : { + "description" : "Client error response" + }, + "5XX" : { + "description" : "Server error response" } - }, { - "in" : "query", - "name" : "dependent-card-types", - "required" : false, - "schema" : { - "anyOf" : [ { - "type" : "string", - "enum" : [ "question", "metric", "model" ] - }, { - "type" : "array", - "items" : { - "type" : "string", - "enum" : [ "question", "metric", "model" ] + }, + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "type" : "object", + "properties" : { + "replicationSchemaFilters" : { + "type" : "object", + "properties" : { + "schema-filters-patterns" : { + "type" : "string" + }, + "schema-filters-type" : { + "type" : "string", + "enum" : [ "inclusion", "exclusion", "all" ] + } + }, + "required" : [ "schema-filters-type", "schema-filters-patterns" ] + } + } } - } ] + } } - }, { + }, + "tags" : [ "/api/ee/database-replication" ] + } + }, + "/api/ee/database-routing/destination-database" : { + "post" : { + "operationId" : "post-api-ee-database-routing-destination-database", + "summary" : "POST /api/ee/database-routing/destination-database", + "description" : "Create new Destination Databases.\n\n Note that unlike the normal `POST /api/database` endpoint, this endpoint does not test that the database is actually\n reachable before adding it — destination details are not required to be valid at creation time, and an\n unreachable destination is fine.", + "parameters" : [ { "in" : "query", - "name" : "archived", + "name" : "check_connection_details", "required" : false, "schema" : { "type" : "boolean" } - }, { - "in" : "query", - "name" : "broken", - "required" : false, - "schema" : { - "type" : "boolean" + } ], + "responses" : { + "2XX" : { + "description" : "Successful response" + }, + "4XX" : { + "description" : "Client error response" + }, + "5XX" : { + "description" : "Server error response" } - }, { - "in" : "query", - "name" : "query", - "required" : false, + }, + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "type" : "object", + "properties" : { + "destinations" : { + "type" : "array", + "items" : { + "type" : "object", + "properties" : { + "details" : { + "description" : "Value must be a map.", + "type" : "object", + "properties" : { } + }, + "name" : { + "type" : "string", + "minLength" : 1 + } + }, + "required" : [ "name", "details" ] + } + }, + "router_database_id" : { + "description" : "value must be an integer greater than zero.", + "type" : "integer", + "minimum" : 1 + } + }, + "required" : [ "router_database_id", "destinations" ] + } + } + } + }, + "tags" : [ "/api/ee/database-routing" ] + } + }, + "/api/ee/database-routing/router-database/{id}" : { + "put" : { + "operationId" : "put-api-ee-database-routing-router-database-id", + "summary" : "PUT /api/ee/database-routing/router-database/{id}", + "description" : "Updates an existing Database with the `user_attribute` to route on. Will either:\n - turn an existing Database into a Router database\n - change the `user_attribute` used to route for an existing Router database, or\n - turn a Router database into a regular Database\n depending on the value of `user_attribute`", + "parameters" : [ { + "in" : "path", + "name" : "id", + "required" : true, "schema" : { - "type" : "string" + "type" : "integer", + "minimum" : 1 + }, + "description" : "value must be an integer greater than zero." + } ], + "responses" : { + "2XX" : { + "description" : "Successful response" + }, + "4XX" : { + "description" : "Client error response" + }, + "5XX" : { + "description" : "Server error response" } - }, { + }, + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "type" : "object", + "properties" : { + "user_attribute" : { + "oneOf" : [ { + "type" : "string", + "minLength" : 1 + }, { + "type" : "null" + } ] + } + } + } + } + } + }, + "tags" : [ "/api/ee/database-routing" ] + } + }, + "/api/ee/dependencies/backfill-status" : { + "get" : { + "operationId" : "get-api-ee-dependencies-backfill-status", + "summary" : "GET /api/ee/dependencies/backfill-status", + "description" : "Returns whether the dependency backfill has pending work.\n `complete` is true when there are no stale or outdated entities awaiting processing.", + "parameters" : [ ], + "responses" : { + "2XX" : { + "description" : "Successful response", + "content" : { + "application/json" : { + "schema" : { + "type" : "object", + "properties" : { + "complete" : { + "type" : "boolean" + } + }, + "required" : [ "complete" ] + } + } + } + }, + "4XX" : { + "description" : "Client error response" + }, + "5XX" : { + "description" : "Server error response" + } + }, + "tags" : [ "/api/ee/dependencies" ] + } + }, + "/api/ee/dependencies/check-card" : { + "post" : { + "operationId" : "post-api-ee-dependencies-check-card", + "summary" : "POST /api/ee/dependencies/check-card", + "description" : "Check a proposed edit to a card, and return the card IDs for those cards this edit will break.", + "parameters" : [ ], + "responses" : { + "2XX" : { + "description" : "Successful response", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/metabase-enterprise.dependencies.api.broken-cards-response" + } + } + } + }, + "4XX" : { + "description" : "Client error response" + }, + "5XX" : { + "description" : "Server error response" + } + }, + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/metabase-enterprise.dependencies.api.card-body" + } + } + } + }, + "tags" : [ "/api/ee/dependencies" ] + } + }, + "/api/ee/dependencies/check-snippet" : { + "post" : { + "operationId" : "post-api-ee-dependencies-check-snippet", + "summary" : "POST /api/ee/dependencies/check-snippet", + "description" : "Check a proposed edit to a native snippet, and return the cards, etc. which will be broken.", + "parameters" : [ ], + "responses" : { + "2XX" : { + "description" : "Successful response", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/metabase-enterprise.dependencies.api.broken-cards-response" + } + } + } + }, + "4XX" : { + "description" : "Client error response" + }, + "5XX" : { + "description" : "Server error response" + } + }, + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "type" : "object", + "properties" : { + "content" : { + "type" : "string" + }, + "id" : { + "$ref" : "#/components/schemas/metabase.lib.schema.id.snippet" + }, + "name" : { + "description" : "snippet names cannot include '}' or start with spaces" + } + }, + "required" : [ "id" ] + } + } + } + }, + "tags" : [ "/api/ee/dependencies" ] + } + }, + "/api/ee/dependencies/check-transform" : { + "post" : { + "operationId" : "post-api-ee-dependencies-check-transform", + "summary" : "POST /api/ee/dependencies/check-transform", + "description" : "Check a proposed edit to a transform, and return the card, transform, etc. IDs for things that will break.", + "parameters" : [ ], + "responses" : { + "2XX" : { + "description" : "Successful response", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/metabase-enterprise.dependencies.api.broken-cards-response" + } + } + } + }, + "4XX" : { + "description" : "Client error response" + }, + "5XX" : { + "description" : "Server error response" + } + }, + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/metabase-enterprise.dependencies.api.transform-body" + } + } + } + }, + "tags" : [ "/api/ee/dependencies" ] + } + }, + "/api/ee/dependencies/graph" : { + "get" : { + "operationId" : "get-api-ee-dependencies-graph", + "summary" : "GET /api/ee/dependencies/graph", + "description" : "This endpoint takes an :id and a supported entity :type, and returns a graph of all its upstream dependencies.\n The graph is represented by a list of :nodes and a list of :edges. Each node has an :id, :type, :data (which\n depends on the node type), and a map of :dependent_counts per entity type. Each edge is a :model/Dependency.\n\n Optional :archived parameter controls whether entities in archived collections are included:\n - false (default): Excludes entities in archived collections\n - true: Includes entities in archived collections", + "parameters" : [ { "in" : "query", - "name" : "include-personal-collections", + "name" : "id", "required" : false, "schema" : { - "type" : "boolean" - } + "type" : "integer", + "minimum" : 1 + }, + "description" : "value must be an integer greater than zero." }, { "in" : "query", - "name" : "sort-column", + "name" : "type", "required" : false, "schema" : { - "type" : "string", - "enum" : [ "name", "view-count", "location" ] + "$ref" : "#/components/schemas/metabase-enterprise.dependencies.dependency-types.dependency-types" } }, { "in" : "query", - "name" : "sort-direction", + "name" : "archived", "required" : false, "schema" : { - "type" : "string", - "enum" : [ "desc", "asc" ] + "type" : "boolean" } } ], "responses" : { @@ -25385,10 +26491,7 @@ "content" : { "application/json" : { "schema" : { - "type" : "array", - "items" : { - "$ref" : "#/components/schemas/metabase-enterprise.dependencies.api.entity" - } + "$ref" : "#/components/schemas/metabase-enterprise.dependencies.api.graph-response" } } } @@ -25403,11 +26506,11 @@ "tags" : [ "/api/ee/dependencies" ] } }, - "/api/ee/dependencies/graph/unreferenced" : { + "/api/ee/dependencies/graph/breaking" : { "get" : { - "operationId" : "get-api-ee-dependencies-graph-unreferenced", - "summary" : "GET /api/ee/dependencies/graph/unreferenced", - "description" : "Returns a list of all unreferenced items in the instance.\n An unreferenced item is one that is not a dependency of any other item.\n\n Accepts optional parameters for filtering:\n - `types`: List of entity types to include (e.g., [:card :transform :snippet :dashboard])\n - `card-types`: List of card types to include when filtering cards (e.g., [:question :model :metric])\n - `query`: Search string to filter by name or location\n - `archived`: Controls whether archived entities are included\n - `include-personal-collections`: Controls whether items in personal collections are included (default: false)\n - `sort-column`: Sort column - `:name`, `:location`, `:dependents-errors`, or `:dependents-with-errors` (default: `:name`)\n - `sort-direction`: Sort direction - `:asc` or `:desc` (default: `:asc`)\n - `offset`: Default 0\n - `limit`: Default 50\n\n Returns a map with:\n - `data`: List of unreferenced items, each with `:id`, `:type`, and `:data` fields\n - `total`: Total count of matched items\n - `offset`: Applied offset\n - `limit`: Applied limit", + "operationId" : "get-api-ee-dependencies-graph-breaking", + "summary" : "GET /api/ee/dependencies/graph/breaking", + "description" : "Returns a list of entities that are breaking other entities (sources of errors).\n These are tables or cards that other entities depend on, where those dependents\n have validation errors traced back to this source entity.\n\n Accepts optional parameters for filtering:\n - `types`: List of source entity types - only `:card` or `:table` (default: both)\n - `card-types`: List of card types to include when filtering cards (e.g., `[:question :model :metric]`)\n - `query`: Search string to filter by name or location\n - `archived`: Controls whether archived entities are included\n - `include-personal-collections`: Controls whether items in personal collections are included (default: false)\n - `sort-column`: Sort column - `:name`, `:location`, `:dependents-errors`, or `:dependents-with-errors` (default: `:name`)\n - `sort-direction`: Sort direction - `:asc` or `:desc` (default: `:asc`)\n - `offset`: Default 0\n - `limit`: Default 50\n\n Returns a map with:\n - `data`: List of breaking source entities\n - `total`: Total count of matched items\n - `offset`: Applied offset\n - `limit`: Applied limit", "parameters" : [ { "in" : "query", "name" : "types", @@ -25519,26 +26622,361 @@ "tags" : [ "/api/ee/dependencies" ] } }, - "/api/ee/email/override" : { - "put" : { - "operationId" : "put-api-ee-email-override", - "summary" : "PUT /api/ee/email/override", - "description" : "Update multiple cloud email Settings. You must be a superuser or have `setting` permission to do this.\n Calling this automatically sets `cloud-smtp-enabled` to true if the settings are valid.", - "parameters" : [ ], - "responses" : { - "2XX" : { - "description" : "Successful response" - }, - "4XX" : { - "description" : "Client error response" - }, - "5XX" : { - "description" : "Server error response" - } - }, - "requestBody" : { - "content" : { - "application/json" : { + "/api/ee/dependencies/graph/broken" : { + "get" : { + "operationId" : "get-api-ee-dependencies-graph-broken", + "summary" : "GET /api/ee/dependencies/graph/broken", + "description" : "Returns the broken dependents for a specific source entity.\n These are entities that have validation errors traced back to the specified source.\n\n Required parameters:\n - `id`: The ID of the source entity\n - `type`: The type of the source entity (card, table)\n\n Optional parameters:\n - `dependent-types`: Dependency types to filter by. Can be single value or array.\n - `dependent-card-types`: Card types to filter by when dependent-types includes :card.\n - `include-personal-collections`: Include items in personal collections (default: false)\n - `sort-column`: Column to sort by - name, location, or view-count (default: name)\n - `sort-direction`: Sort direction - asc or desc (default: asc)", + "parameters" : [ { + "in" : "query", + "name" : "id", + "required" : true, + "schema" : { + "type" : "integer", + "minimum" : 1 + }, + "description" : "value must be an integer greater than zero." + }, { + "in" : "query", + "name" : "type", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/metabase-enterprise.dependencies.dependency-types.dependency-types" + } + }, { + "in" : "query", + "name" : "dependent-types", + "required" : false, + "schema" : { + "anyOf" : [ { + "$ref" : "#/components/schemas/metabase-enterprise.dependencies.dependency-types.dependency-types" + }, { + "type" : "array", + "items" : { + "$ref" : "#/components/schemas/metabase-enterprise.dependencies.dependency-types.dependency-types" + } + } ] + } + }, { + "in" : "query", + "name" : "dependent-card-types", + "required" : false, + "schema" : { + "anyOf" : [ { + "type" : "string", + "enum" : [ "question", "metric", "model" ] + }, { + "type" : "array", + "items" : { + "type" : "string", + "enum" : [ "question", "metric", "model" ] + } + } ] + } + }, { + "in" : "query", + "name" : "include-personal-collections", + "required" : false, + "schema" : { + "type" : "boolean" + } + }, { + "in" : "query", + "name" : "sort-column", + "required" : false, + "schema" : { + "type" : "string", + "enum" : [ "name", "view-count", "location" ] + } + }, { + "in" : "query", + "name" : "sort-direction", + "required" : false, + "schema" : { + "type" : "string", + "enum" : [ "desc", "asc" ] + } + } ], + "responses" : { + "2XX" : { + "description" : "Successful response", + "content" : { + "application/json" : { + "schema" : { + "type" : "array", + "items" : { + "$ref" : "#/components/schemas/metabase-enterprise.dependencies.api.broken-dependent-entity" + } + } + } + } + }, + "4XX" : { + "description" : "Client error response" + }, + "5XX" : { + "description" : "Server error response" + } + }, + "tags" : [ "/api/ee/dependencies" ] + } + }, + "/api/ee/dependencies/graph/dependents" : { + "get" : { + "operationId" : "get-api-ee-dependencies-graph-dependents", + "summary" : "GET /api/ee/dependencies/graph/dependents", + "description" : "Returns a list of dependents for the specified entity.\n\n Required parameters:\n - `id`: The ID of the entity\n - `type`: The type of the entity (card, table, dashboard, etc.)\n\n Optional parameters:\n - `dependent-types`: Dependency types to filter by. Can be single value or array.\n If not provided, returns all types. Example: ?dependent-types=card&dependent-types=dashboard\n - `dependent-card-types`: Card types to filter by when dependent-types includes :card.\n Ignored if dependent-types doesn't include :card. Example: ?dependent-card-types=question&dependent-card-types=model\n - `archived`: Include entities in archived collections (default: false)\n - `broken`: Return only broken entities (default: false)\n - `query`: Search string to filter results by name or location (case-insensitive)\n - `include-personal-collections`: Include items in personal collections (default: false)\n - `sort-column`: Column to sort by - name, location, or view-count (default: name)\n - `sort-direction`: Sort direction - asc or desc (default: asc)", + "parameters" : [ { + "in" : "query", + "name" : "id", + "required" : true, + "schema" : { + "type" : "integer", + "minimum" : 1 + }, + "description" : "value must be an integer greater than zero." + }, { + "in" : "query", + "name" : "type", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/metabase-enterprise.dependencies.dependency-types.dependency-types" + } + }, { + "in" : "query", + "name" : "dependent-types", + "required" : false, + "schema" : { + "anyOf" : [ { + "$ref" : "#/components/schemas/metabase-enterprise.dependencies.dependency-types.dependency-types" + }, { + "type" : "array", + "items" : { + "$ref" : "#/components/schemas/metabase-enterprise.dependencies.dependency-types.dependency-types" + } + } ] + } + }, { + "in" : "query", + "name" : "dependent-card-types", + "required" : false, + "schema" : { + "anyOf" : [ { + "type" : "string", + "enum" : [ "question", "metric", "model" ] + }, { + "type" : "array", + "items" : { + "type" : "string", + "enum" : [ "question", "metric", "model" ] + } + } ] + } + }, { + "in" : "query", + "name" : "archived", + "required" : false, + "schema" : { + "type" : "boolean" + } + }, { + "in" : "query", + "name" : "broken", + "required" : false, + "schema" : { + "type" : "boolean" + } + }, { + "in" : "query", + "name" : "query", + "required" : false, + "schema" : { + "type" : "string" + } + }, { + "in" : "query", + "name" : "include-personal-collections", + "required" : false, + "schema" : { + "type" : "boolean" + } + }, { + "in" : "query", + "name" : "sort-column", + "required" : false, + "schema" : { + "type" : "string", + "enum" : [ "name", "view-count", "location" ] + } + }, { + "in" : "query", + "name" : "sort-direction", + "required" : false, + "schema" : { + "type" : "string", + "enum" : [ "desc", "asc" ] + } + } ], + "responses" : { + "2XX" : { + "description" : "Successful response", + "content" : { + "application/json" : { + "schema" : { + "type" : "array", + "items" : { + "$ref" : "#/components/schemas/metabase-enterprise.dependencies.api.entity" + } + } + } + } + }, + "4XX" : { + "description" : "Client error response" + }, + "5XX" : { + "description" : "Server error response" + } + }, + "tags" : [ "/api/ee/dependencies" ] + } + }, + "/api/ee/dependencies/graph/unreferenced" : { + "get" : { + "operationId" : "get-api-ee-dependencies-graph-unreferenced", + "summary" : "GET /api/ee/dependencies/graph/unreferenced", + "description" : "Returns a list of all unreferenced items in the instance.\n An unreferenced item is one that is not a dependency of any other item.\n\n Accepts optional parameters for filtering:\n - `types`: List of entity types to include (e.g., [:card :transform :snippet :dashboard])\n - `card-types`: List of card types to include when filtering cards (e.g., [:question :model :metric])\n - `query`: Search string to filter by name or location\n - `archived`: Controls whether archived entities are included\n - `include-personal-collections`: Controls whether items in personal collections are included (default: false)\n - `sort-column`: Sort column - `:name`, `:location`, `:dependents-errors`, or `:dependents-with-errors` (default: `:name`)\n - `sort-direction`: Sort direction - `:asc` or `:desc` (default: `:asc`)\n - `offset`: Default 0\n - `limit`: Default 50\n\n Returns a map with:\n - `data`: List of unreferenced items, each with `:id`, `:type`, and `:data` fields\n - `total`: Total count of matched items\n - `offset`: Applied offset\n - `limit`: Applied limit", + "parameters" : [ { + "in" : "query", + "name" : "types", + "required" : false, + "schema" : { + "anyOf" : [ { + "$ref" : "#/components/schemas/metabase-enterprise.dependencies.dependency-types.dependency-types" + }, { + "type" : "array", + "items" : { + "$ref" : "#/components/schemas/metabase-enterprise.dependencies.dependency-types.dependency-types" + } + } ] + } + }, { + "in" : "query", + "name" : "card-types", + "required" : false, + "schema" : { + "anyOf" : [ { + "type" : "string", + "enum" : [ "question", "metric", "model" ] + }, { + "type" : "array", + "items" : { + "type" : "string", + "enum" : [ "question", "metric", "model" ] + } + } ] + } + }, { + "in" : "query", + "name" : "query", + "required" : false, + "schema" : { + "type" : "string" + } + }, { + "in" : "query", + "name" : "archived", + "required" : false, + "schema" : { + "type" : "boolean" + } + }, { + "in" : "query", + "name" : "include-personal-collections", + "required" : false, + "schema" : { + "type" : "boolean" + } + }, { + "in" : "query", + "name" : "sort-column", + "required" : false, + "schema" : { + "type" : "string", + "enum" : [ "dependents-with-errors", "dependents-errors", "name", "location" ] + } + }, { + "in" : "query", + "name" : "sort-direction", + "required" : false, + "schema" : { + "type" : "string", + "enum" : [ "desc", "asc" ] + } + } ], + "responses" : { + "2XX" : { + "description" : "Successful response", + "content" : { + "application/json" : { + "schema" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "array", + "items" : { + "$ref" : "#/components/schemas/metabase-enterprise.dependencies.api.entity" + } + }, + "limit" : { + "description" : "value must be an integer greater than zero.", + "type" : "integer", + "minimum" : 1 + }, + "offset" : { + "type" : "integer", + "minimum" : 0 + }, + "total" : { + "type" : "integer", + "minimum" : 0 + } + }, + "required" : [ "data", "total", "offset", "limit" ] + } + } + } + }, + "4XX" : { + "description" : "Client error response" + }, + "5XX" : { + "description" : "Server error response" + } + }, + "tags" : [ "/api/ee/dependencies" ] + } + }, + "/api/ee/email/override" : { + "put" : { + "operationId" : "put-api-ee-email-override", + "summary" : "PUT /api/ee/email/override", + "description" : "Update multiple cloud email Settings. You must be a superuser or have `setting` permission to do this.\n Calling this automatically sets `cloud-smtp-enabled` to true if the settings are valid.", + "parameters" : [ ], + "responses" : { + "2XX" : { + "description" : "Successful response" + }, + "4XX" : { + "description" : "Client error response" + }, + "5XX" : { + "description" : "Server error response" + } + }, + "requestBody" : { + "content" : { + "application/json" : { "schema" : { "type" : "object", "properties" : { @@ -25935,113 +27373,86 @@ "tags" : [ "/api/ee/logs" ] } }, - "/api/ee/metabot/usage" : { - "get" : { - "operationId" : "get-api-ee-metabot-usage", - "summary" : "GET /api/ee/metabot/usage", - "description" : "Fetch current Metabot token usage for the current billing period.", - "parameters" : [ ], - "responses" : { - "2XX" : { - "description" : "Successful response", - "content" : { - "application/json" : { - "schema" : { - "type" : "object", - "properties" : { - "is_locked" : { - "oneOf" : [ { - "type" : "boolean" - }, { - "type" : "null" - } ] - }, - "tokens" : { - "oneOf" : [ { - "type" : "integer" - }, { - "type" : "null" - } ] - }, - "updated_at" : { - "oneOf" : [ { - "type" : "string" - }, { - "type" : "null" - } ] - } - }, - "required" : [ "is_locked", "tokens", "updated_at" ] - } - } - } - }, - "4XX" : { - "description" : "Client error response" - }, - "5XX" : { - "description" : "Server error response" - } - }, - "tags" : [ "/api/ee/metabot" ] - } - }, - "/api/ee/permission_debug" : { + "/api/ee/metabot-analytics/conversations" : { "get" : { - "operationId" : "get-api-ee-permission_debug", - "summary" : "GET /api/ee/permission_debug", - "description" : "This endpoint expects a `user_id`, a `model_id` to debug permissions against, and `action_type`.\n The type of model we are debugging against is inferred by the `action_type`.\n\n It will return:\n - `decision`: The overall permission decision (\"allow\", \"denied\", or \"limited\")\n - `model-type`: The type of model being checked (e.g., \"question\")\n - `model-id`: The ID of the model being checked\n - `segment`: A set of segmentation types applied (e.g., \"sandboxed\", \"impersonated\", \"routed\")\n - `message`: A sequence of strings explaining the decision\n - `data`: A map containing details about permissions (table or collection names to group names)\n - `suggestions`: A map of group IDs to group names that could provide access\n\n Example requests:\n - Check if user can read a card: `GET /api/ee/permission_debug?user_id=123&model_id=456&action_type=card/read`\n - Check if user can query a card: `GET /api/ee/permission_debug?user_id=123&model_id=456&action_type=card/query`\n - Check if user can download data: `GET /api/ee/permission_debug?user_id=123&model_id=456&action_type=card/download-data`\n\n Example responses:\n - Allowed access:\n ```json\n {\n \"decision\": \"allow\",\n \"model-type\": \"question\",\n \"model-id\": \"456\",\n \"segment\": [],\n \"message\": [\"User has permission to read this card\"],\n \"data\": {},\n \"suggestions\": {}\n }\n ```\n - Denied access with blocked table:\n ```json\n {\n \"decision\": \"denied\",\n \"model-type\": \"question\",\n \"model-id\": \"456\",\n \"segment\": [],\n \"message\": [\"User does not have permission to query this card\"],\n \"data\": {\"sample-db.PUBLIC.ORDERS\": [\"All Users\"]},\n \"suggestions\": {}\n }\n ```\n - Limited access:\n ```json\n {\n \"decision\": \"limited\",\n \"model-type\": \"question\",\n \"model-id\": \"456\",\n \"segment\": [],\n \"message\": [\"User has permission to download some data from this card\"],\n \"data\": {},\n \"suggestions\": {}\n }\n ```", + "operationId" : "get-api-ee-metabot-analytics-conversations", + "summary" : "GET /api/ee/metabot-analytics/conversations", + "description" : "Return paginated list of AI conversations with summary statistics.", "parameters" : [ { + "in" : "query", + "name" : "sort_by", + "required" : false, + "schema" : { + "oneOf" : [ { + "type" : "string", + "enum" : [ "created_at", "message_count", "total_tokens", "user", "profile_id", "ip_address" ] + }, { + "type" : "null" + } ] + } + }, { + "in" : "query", + "name" : "sort_dir", + "required" : false, + "schema" : { + "oneOf" : [ { + "type" : "string", + "enum" : [ "asc", "desc" ] + }, { + "type" : "null" + } ] + } + }, { "in" : "query", "name" : "user_id", - "required" : true, + "required" : false, "schema" : { - "type" : "integer", - "minimum" : 1 + "oneOf" : [ { + "description" : "value must be an integer greater than zero.", + "type" : "integer", + "minimum" : 1 + }, { + "type" : "null" + } ] } }, { "in" : "query", - "name" : "model_id", - "required" : true, + "name" : "group_id", + "required" : false, "schema" : { - "type" : "string" + "oneOf" : [ { + "description" : "value must be an integer greater than zero.", + "type" : "integer", + "minimum" : 1 + }, { + "type" : "null" + } ] } }, { "in" : "query", - "name" : "action_type", - "required" : true, + "name" : "tenant_id", + "required" : false, "schema" : { - "type" : "string", - "enum" : [ "card/read", "card/query", "card/download-data" ] + "oneOf" : [ { + "description" : "value must be an integer greater than zero.", + "type" : "integer", + "minimum" : 1 + }, { + "type" : "null" + } ] } - } ], - "responses" : { - "2XX" : { - "description" : "Successful response", - "content" : { - "application/json" : { - "schema" : { - "$ref" : "#/components/schemas/metabase-enterprise.permission-debug.impl.perm-debug-info" - } - } - } - }, - "4XX" : { - "description" : "Client error response" - }, - "5XX" : { - "description" : "Server error response" + }, { + "in" : "query", + "name" : "date", + "required" : false, + "schema" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] } - }, - "tags" : [ "/api/ee/permission_debug" ] - } - }, - "/api/ee/remote-sync/branches" : { - "get" : { - "operationId" : "get-api-ee-remote-sync-branches", - "summary" : "GET /api/ee/remote-sync/branches", - "description" : "Get list of branches from the configured source.\n\n Returns a JSON object with branch names under the :items key.\n\n Requires superuser permissions.", - "parameters" : [ ], + } ], "responses" : { "2XX" : { "description" : "Successful response", @@ -26050,50 +27461,160 @@ "schema" : { "type" : "object", "properties" : { - "items" : { + "data" : { "type" : "array", "items" : { - "type" : "string" - } - } - }, - "required" : [ "items" ] - } - } - } - }, - "4XX" : { - "description" : "Client error response" - }, - "5XX" : { - "description" : "Server error response" - } - }, - "tags" : [ "/api/ee/remote-sync" ] - } - }, - "/api/ee/remote-sync/create-branch" : { - "post" : { - "operationId" : "post-api-ee-remote-sync-create-branch", - "summary" : "POST /api/ee/remote-sync/create-branch", - "description" : "Create a new branch from the current remote-sync branch and switches the current remote-sync branch to it.\n Requires superuser permissions.", - "parameters" : [ ], - "responses" : { - "2XX" : { - "description" : "Successful response", - "content" : { - "application/json" : { - "schema" : { - "type" : "object", - "properties" : { - "message" : { - "type" : "string" + "type" : "object", + "properties" : { + "sanitized_user_agent" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "embedding_path" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "user" : { + "oneOf" : [ { + "type" : "object", + "properties" : { + "email" : { + "type" : "string" + }, + "first_name" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "id" : { + "description" : "value must be an integer greater than zero.", + "type" : "integer", + "minimum" : 1 + }, + "last_name" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + } + }, + "required" : [ "id", "email", "first_name", "last_name" ] + }, { + "type" : "null" + } ] + }, + "embedding_hostname" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "summary" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "message_count" : { + "description" : "value must be an integer greater or equal to than zero.", + "type" : "integer", + "minimum" : 0 + }, + "user_message_count" : { + "description" : "value must be an integer greater or equal to than zero.", + "type" : "integer", + "minimum" : 0 + }, + "profile_id" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "conversation_id" : { + "description" : "value must be a valid UUID.", + "type" : "string", + "pattern" : "[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}" + }, + "last_message_at" : { + "oneOf" : [ { + "type" : "string", + "format" : "date-time" + }, { + "type" : "null" + } ] + }, + "created_at" : { + "type" : "string", + "format" : "date-time" + }, + "ip_address" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "search_count" : { + "description" : "value must be an integer greater or equal to than zero.", + "type" : "integer", + "minimum" : 0 + }, + "assistant_message_count" : { + "description" : "value must be an integer greater or equal to than zero.", + "type" : "integer", + "minimum" : 0 + }, + "total_tokens" : { + "description" : "value must be an integer greater or equal to than zero.", + "type" : "integer", + "minimum" : 0 + }, + "query_count" : { + "description" : "value must be an integer greater or equal to than zero.", + "type" : "integer", + "minimum" : 0 + }, + "user_agent" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + } + }, + "required" : [ "conversation_id", "created_at", "summary", "message_count", "user_message_count", "assistant_message_count", "total_tokens", "last_message_at", "profile_id", "search_count", "query_count", "ip_address", "embedding_hostname", "embedding_path", "user_agent", "sanitized_user_agent", "user" ] + } }, - "status" : { - "type" : "string" + "limit" : { + "description" : "value must be an integer greater or equal to than zero.", + "type" : "integer", + "minimum" : 0 + }, + "offset" : { + "description" : "value must be an integer greater or equal to than zero.", + "type" : "integer", + "minimum" : 0 + }, + "total" : { + "description" : "value must be an integer greater or equal to than zero.", + "type" : "integer", + "minimum" : 0 } }, - "required" : [ "status", "message" ] + "required" : [ "data", "total", "limit", "offset" ] } } } @@ -26105,136 +27626,24 @@ "description" : "Server error response" } }, - "requestBody" : { - "content" : { - "application/json" : { - "schema" : { - "type" : "object", - "properties" : { - "name" : { - "type" : "string", - "minLength" : 1 - } - }, - "required" : [ "name" ] - } - } - } - }, - "tags" : [ "/api/ee/remote-sync" ] + "tags" : [ "/api/ee/metabot-analytics" ] } }, - "/api/ee/remote-sync/current-task" : { + "/api/ee/metabot-analytics/conversations/{id}" : { "get" : { - "operationId" : "get-api-ee-remote-sync-current-task", - "summary" : "GET /api/ee/remote-sync/current-task", - "description" : "Get the current sync task", - "parameters" : [ ], - "responses" : { - "2XX" : { - "description" : "Successful response", - "content" : { - "application/json" : { - "schema" : { - "oneOf" : [ { - "type" : "object", - "properties" : { - "progress" : { - "oneOf" : [ { - "type" : "number", - "minimum" : 0.0, - "maximum" : 1.0 - }, { - "type" : "null" - } ] - }, - "conflicts" : { - "oneOf" : [ { - "type" : "array", - "items" : { - "type" : "string" - } - }, { - "type" : "null" - } ] - }, - "last_progress_report_at" : { - "oneOf" : [ { }, { - "type" : "null" - } ] - }, - "id" : { - "type" : "integer", - "minimum" : 1 - }, - "started_at" : { }, - "ended_at" : { - "oneOf" : [ { }, { - "type" : "null" - } ] - }, - "initiated_by" : { - "oneOf" : [ { - "type" : "integer", - "minimum" : 1 - }, { - "type" : "null" - } ] - }, - "cancelled" : { - "oneOf" : [ { - "type" : "boolean" - }, { - "type" : "null" - } ] - }, - "status" : { - "type" : "string", - "enum" : [ "running", "successful", "errored", "cancelled", "timed-out", "conflict" ] - }, - "error_message" : { - "oneOf" : [ { - "type" : "string" - }, { - "type" : "null" - } ] - }, - "sync_task_type" : { - "type" : "string", - "enum" : [ "import", "export" ] - }, - "version" : { - "oneOf" : [ { - "type" : "string" - }, { - "type" : "null" - } ] - } - }, - "required" : [ "id", "sync_task_type", "progress", "started_at", "status" ] - }, { - "type" : "null" - } ] - } - } - } - }, - "4XX" : { - "description" : "Client error response" + "operationId" : "get-api-ee-metabot-analytics-conversations-id", + "summary" : "GET /api/ee/metabot-analytics/conversations/{id}", + "description" : "Return full details for a specific conversation including all messages.", + "parameters" : [ { + "in" : "path", + "name" : "id", + "required" : true, + "schema" : { + "type" : "string", + "pattern" : "[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}" }, - "5XX" : { - "description" : "Server error response" - } - }, - "tags" : [ "/api/ee/remote-sync" ] - } - }, - "/api/ee/remote-sync/current-task/cancel" : { - "post" : { - "operationId" : "post-api-ee-remote-sync-current-task-cancel", - "summary" : "POST /api/ee/remote-sync/current-task/cancel", - "description" : "Cancels the current task if one is running", - "parameters" : [ ], + "description" : "value must be a valid UUID." + } ], "responses" : { "2XX" : { "description" : "Successful response", @@ -26243,191 +27652,2246 @@ "schema" : { "type" : "object", "properties" : { - "progress" : { + "queries" : { + "type" : "array", + "items" : { + "type" : "object", + "properties" : { + "tables" : { + "type" : "array", + "items" : { + "type" : "string" + } + }, + "mbql" : { + "oneOf" : [ { + "type" : "object", + "properties" : { } + }, { + "type" : "null" + } ] + }, + "database_id" : { + "oneOf" : [ { + "description" : "value must be an integer greater than zero.", + "type" : "integer", + "minimum" : 1 + }, { + "type" : "null" + } ] + }, + "query_id" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "query_type" : { + "type" : "string", + "enum" : [ "sql", "notebook" ] + }, + "display" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "tool" : { + "type" : "string", + "enum" : [ "construct_notebook_query", "create_sql_query", "edit_sql_query", "replace_sql_query" ] + }, + "call_id" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "sql" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "message_id" : { + "description" : "value must be an integer greater than zero.", + "type" : "integer", + "minimum" : 1 + } + }, + "required" : [ "tool", "call_id", "message_id", "query_id", "query_type", "sql", "mbql", "display", "database_id", "tables" ] + } + }, + "sanitized_user_agent" : { "oneOf" : [ { - "type" : "number", - "minimum" : 0.0, - "maximum" : 1.0 + "type" : "string" }, { "type" : "null" } ] }, - "conflicts" : { + "embedding_path" : { "oneOf" : [ { - "type" : "array", - "items" : { - "type" : "string" - } + "type" : "string" }, { "type" : "null" } ] }, - "last_progress_report_at" : { - "oneOf" : [ { }, { - "type" : "null" - } ] - }, - "id" : { - "type" : "integer", - "minimum" : 1 - }, - "started_at" : { }, - "ended_at" : { - "oneOf" : [ { }, { - "type" : "null" - } ] - }, - "initiated_by" : { + "slack_permalink" : { "oneOf" : [ { - "type" : "integer", - "minimum" : 1 + "type" : "string" }, { "type" : "null" } ] }, - "cancelled" : { + "user" : { "oneOf" : [ { - "type" : "boolean" + "type" : "object", + "properties" : { + "email" : { + "type" : "string" + }, + "first_name" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "id" : { + "description" : "value must be an integer greater than zero.", + "type" : "integer", + "minimum" : 1 + }, + "last_name" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + } + }, + "required" : [ "id", "email", "first_name", "last_name" ] }, { "type" : "null" } ] }, - "status" : { - "type" : "string", - "enum" : [ "running", "successful", "errored", "cancelled", "timed-out", "conflict" ] - }, - "error_message" : { + "embedding_hostname" : { "oneOf" : [ { "type" : "string" }, { "type" : "null" } ] }, - "sync_task_type" : { - "type" : "string", - "enum" : [ "import", "export" ] - }, - "version" : { + "summary" : { "oneOf" : [ { "type" : "string" }, { "type" : "null" } ] - } - }, - "required" : [ "id", "sync_task_type", "progress", "started_at", "status" ] - } - } - } - }, - "4XX" : { - "description" : "Client error response" - }, - "5XX" : { - "description" : "Server error response" - } - }, - "tags" : [ "/api/ee/remote-sync" ] - } - }, - "/api/ee/remote-sync/dirty" : { - "get" : { - "operationId" : "get-api-ee-remote-sync-dirty", - "summary" : "GET /api/ee/remote-sync/dirty", - "description" : "Return all models with changes that have not been pushed to the remote sync source in any\n remote-synced collection.", - "parameters" : [ ], - "responses" : { - "2XX" : { - "description" : "Successful response", - "content" : { - "application/json" : { - "schema" : { - "type" : "object", - "properties" : { - "dirty" : { + }, + "feedback" : { "type" : "array", "items" : { "type" : "object", "properties" : { - "table_name" : { + "user_id" : { + "description" : "value must be an integer greater than zero.", + "type" : "integer", + "minimum" : 1 + }, + "positive" : { + "type" : "boolean" + }, + "external_id" : { "oneOf" : [ { "type" : "string" }, { "type" : "null" } ] }, - "model" : { - "type" : "string" - }, - "authority_level" : { + "user" : { "oneOf" : [ { - "type" : "string" + "type" : "object", + "properties" : { + "email" : { + "type" : "string" + }, + "first_name" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "id" : { + "description" : "value must be an integer greater than zero.", + "type" : "integer", + "minimum" : 1 + }, + "last_name" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + } + }, + "required" : [ "id", "email", "first_name", "last_name" ] }, { "type" : "null" } ] }, "id" : { - "type" : "integer" + "description" : "value must be an integer greater than zero.", + "type" : "integer", + "minimum" : 1 }, - "name" : { + "updated_at" : { + "type" : "string", + "format" : "date-time" + }, + "issue_type" : { "oneOf" : [ { "type" : "string" }, { "type" : "null" } ] }, - "updated_at" : { - "oneOf" : [ { }, { - "type" : "null" - } ] + "created_at" : { + "type" : "string", + "format" : "date-time" }, - "table_id" : { + "freeform_feedback" : { "oneOf" : [ { - "type" : "integer", - "minimum" : 1 + "type" : "string" }, { "type" : "null" } ] }, - "query_type" : { + "message_id" : { + "description" : "value must be an integer greater than zero.", + "type" : "integer", + "minimum" : 1 + } + }, + "required" : [ "id", "message_id", "user_id", "external_id", "positive", "issue_type", "freeform_feedback", "created_at", "updated_at" ] + } + }, + "message_count" : { + "description" : "value must be an integer greater or equal to than zero.", + "type" : "integer", + "minimum" : 0 + }, + "profile_id" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "conversation_id" : { + "description" : "value must be a valid UUID.", + "type" : "string", + "pattern" : "[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}" + }, + "created_at" : { + "type" : "string", + "format" : "date-time" + }, + "ip_address" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "search_count" : { + "description" : "value must be an integer greater or equal to than zero.", + "type" : "integer", + "minimum" : 0 + }, + "total_tokens" : { + "description" : "value must be an integer greater or equal to than zero.", + "type" : "integer", + "minimum" : 0 + }, + "query_count" : { + "description" : "value must be an integer greater or equal to than zero.", + "type" : "integer", + "minimum" : 0 + }, + "user_agent" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "chat_messages" : { + "type" : "array", + "items" : { + "type" : "object", + "properties" : { } + } + } + }, + "required" : [ "conversation_id", "created_at", "summary", "user", "message_count", "total_tokens", "profile_id", "slack_permalink", "chat_messages", "queries", "search_count", "query_count", "ip_address", "embedding_hostname", "embedding_path", "user_agent", "sanitized_user_agent", "feedback" ] + } + } + } + }, + "4XX" : { + "description" : "Client error response" + }, + "5XX" : { + "description" : "Server error response" + } + }, + "tags" : [ "/api/ee/metabot-analytics" ] + } + }, + "/api/ee/metabot/usage" : { + "get" : { + "operationId" : "get-api-ee-metabot-usage", + "summary" : "GET /api/ee/metabot/usage", + "description" : "Fetch current Metabot token usage for the current billing period.", + "parameters" : [ ], + "responses" : { + "2XX" : { + "description" : "Successful response", + "content" : { + "application/json" : { + "schema" : { + "type" : "object", + "properties" : { + "is_locked" : { + "oneOf" : [ { + "type" : "boolean" + }, { + "type" : "null" + } ] + }, + "tokens" : { + "oneOf" : [ { + "type" : "integer" + }, { + "type" : "null" + } ] + }, + "updated_at" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + } + }, + "required" : [ "is_locked", "tokens", "updated_at" ] + } + } + } + }, + "4XX" : { + "description" : "Client error response" + }, + "5XX" : { + "description" : "Server error response" + } + }, + "tags" : [ "/api/ee/metabot" ] + } + }, + "/api/ee/permission_debug" : { + "get" : { + "operationId" : "get-api-ee-permission_debug", + "summary" : "GET /api/ee/permission_debug", + "description" : "This endpoint expects a `user_id`, a `model_id` to debug permissions against, and `action_type`.\n The type of model we are debugging against is inferred by the `action_type`.\n\n It will return:\n - `decision`: The overall permission decision (\"allow\", \"denied\", or \"limited\")\n - `model-type`: The type of model being checked (e.g., \"question\")\n - `model-id`: The ID of the model being checked\n - `segment`: A set of segmentation types applied (e.g., \"sandboxed\", \"impersonated\", \"routed\")\n - `message`: A sequence of strings explaining the decision\n - `data`: A map containing details about permissions (table or collection names to group names)\n - `suggestions`: A map of group IDs to group names that could provide access\n\n Example requests:\n - Check if user can read a card: `GET /api/ee/permission_debug?user_id=123&model_id=456&action_type=card/read`\n - Check if user can query a card: `GET /api/ee/permission_debug?user_id=123&model_id=456&action_type=card/query`\n - Check if user can download data: `GET /api/ee/permission_debug?user_id=123&model_id=456&action_type=card/download-data`\n\n Example responses:\n - Allowed access:\n ```json\n {\n \"decision\": \"allow\",\n \"model-type\": \"question\",\n \"model-id\": \"456\",\n \"segment\": [],\n \"message\": [\"User has permission to read this card\"],\n \"data\": {},\n \"suggestions\": {}\n }\n ```\n - Denied access with blocked table:\n ```json\n {\n \"decision\": \"denied\",\n \"model-type\": \"question\",\n \"model-id\": \"456\",\n \"segment\": [],\n \"message\": [\"User does not have permission to query this card\"],\n \"data\": {\"sample-db.PUBLIC.ORDERS\": [\"All Users\"]},\n \"suggestions\": {}\n }\n ```\n - Limited access:\n ```json\n {\n \"decision\": \"limited\",\n \"model-type\": \"question\",\n \"model-id\": \"456\",\n \"segment\": [],\n \"message\": [\"User has permission to download some data from this card\"],\n \"data\": {},\n \"suggestions\": {}\n }\n ```", + "parameters" : [ { + "in" : "query", + "name" : "user_id", + "required" : true, + "schema" : { + "type" : "integer", + "minimum" : 1 + } + }, { + "in" : "query", + "name" : "model_id", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "in" : "query", + "name" : "action_type", + "required" : true, + "schema" : { + "type" : "string", + "enum" : [ "card/read", "card/query", "card/download-data" ] + } + } ], + "responses" : { + "2XX" : { + "description" : "Successful response", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/metabase-enterprise.permission-debug.impl.perm-debug-info" + } + } + } + }, + "4XX" : { + "description" : "Client error response" + }, + "5XX" : { + "description" : "Server error response" + } + }, + "tags" : [ "/api/ee/permission_debug" ] + } + }, + "/api/ee/remote-sync/branches" : { + "get" : { + "operationId" : "get-api-ee-remote-sync-branches", + "summary" : "GET /api/ee/remote-sync/branches", + "description" : "Get list of branches from the configured source.\n\n Returns a JSON object with branch names under the :items key.\n\n Requires superuser permissions.", + "parameters" : [ ], + "responses" : { + "2XX" : { + "description" : "Successful response", + "content" : { + "application/json" : { + "schema" : { + "type" : "object", + "properties" : { + "items" : { + "type" : "array", + "items" : { + "type" : "string" + } + } + }, + "required" : [ "items" ] + } + } + } + }, + "4XX" : { + "description" : "Client error response" + }, + "5XX" : { + "description" : "Server error response" + } + }, + "tags" : [ "/api/ee/remote-sync" ] + } + }, + "/api/ee/remote-sync/create-branch" : { + "post" : { + "operationId" : "post-api-ee-remote-sync-create-branch", + "summary" : "POST /api/ee/remote-sync/create-branch", + "description" : "Create a new branch from the current remote-sync branch and switches the current remote-sync branch to it.\n Requires superuser permissions.", + "parameters" : [ ], + "responses" : { + "2XX" : { + "description" : "Successful response", + "content" : { + "application/json" : { + "schema" : { + "type" : "object", + "properties" : { + "message" : { + "type" : "string" + }, + "status" : { + "type" : "string" + } + }, + "required" : [ "status", "message" ] + } + } + } + }, + "4XX" : { + "description" : "Client error response" + }, + "5XX" : { + "description" : "Server error response" + } + }, + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "type" : "object", + "properties" : { + "name" : { + "type" : "string", + "minLength" : 1 + } + }, + "required" : [ "name" ] + } + } + } + }, + "tags" : [ "/api/ee/remote-sync" ] + } + }, + "/api/ee/remote-sync/current-task" : { + "get" : { + "operationId" : "get-api-ee-remote-sync-current-task", + "summary" : "GET /api/ee/remote-sync/current-task", + "description" : "Get the current sync task", + "parameters" : [ ], + "responses" : { + "2XX" : { + "description" : "Successful response", + "content" : { + "application/json" : { + "schema" : { + "oneOf" : [ { + "type" : "object", + "properties" : { + "progress" : { + "oneOf" : [ { + "type" : "number", + "minimum" : 0.0, + "maximum" : 1.0 + }, { + "type" : "null" + } ] + }, + "conflicts" : { + "oneOf" : [ { + "type" : "array", + "items" : { + "type" : "string" + } + }, { + "type" : "null" + } ] + }, + "last_progress_report_at" : { + "oneOf" : [ { }, { + "type" : "null" + } ] + }, + "id" : { + "type" : "integer", + "minimum" : 1 + }, + "started_at" : { }, + "ended_at" : { + "oneOf" : [ { }, { + "type" : "null" + } ] + }, + "initiated_by" : { + "oneOf" : [ { + "type" : "integer", + "minimum" : 1 + }, { + "type" : "null" + } ] + }, + "cancelled" : { + "oneOf" : [ { + "type" : "boolean" + }, { + "type" : "null" + } ] + }, + "status" : { + "type" : "string", + "enum" : [ "running", "successful", "errored", "cancelled", "timed-out", "conflict" ] + }, + "error_message" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "sync_task_type" : { + "type" : "string", + "enum" : [ "import", "export" ] + }, + "version" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + } + }, + "required" : [ "id", "sync_task_type", "progress", "started_at", "status" ] + }, { + "type" : "null" + } ] + } + } + } + }, + "4XX" : { + "description" : "Client error response" + }, + "5XX" : { + "description" : "Server error response" + } + }, + "tags" : [ "/api/ee/remote-sync" ] + } + }, + "/api/ee/remote-sync/current-task/cancel" : { + "post" : { + "operationId" : "post-api-ee-remote-sync-current-task-cancel", + "summary" : "POST /api/ee/remote-sync/current-task/cancel", + "description" : "Cancels the current task if one is running", + "parameters" : [ ], + "responses" : { + "2XX" : { + "description" : "Successful response", + "content" : { + "application/json" : { + "schema" : { + "type" : "object", + "properties" : { + "progress" : { + "oneOf" : [ { + "type" : "number", + "minimum" : 0.0, + "maximum" : 1.0 + }, { + "type" : "null" + } ] + }, + "conflicts" : { + "oneOf" : [ { + "type" : "array", + "items" : { + "type" : "string" + } + }, { + "type" : "null" + } ] + }, + "last_progress_report_at" : { + "oneOf" : [ { }, { + "type" : "null" + } ] + }, + "id" : { + "type" : "integer", + "minimum" : 1 + }, + "started_at" : { }, + "ended_at" : { + "oneOf" : [ { }, { + "type" : "null" + } ] + }, + "initiated_by" : { + "oneOf" : [ { + "type" : "integer", + "minimum" : 1 + }, { + "type" : "null" + } ] + }, + "cancelled" : { + "oneOf" : [ { + "type" : "boolean" + }, { + "type" : "null" + } ] + }, + "status" : { + "type" : "string", + "enum" : [ "running", "successful", "errored", "cancelled", "timed-out", "conflict" ] + }, + "error_message" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "sync_task_type" : { + "type" : "string", + "enum" : [ "import", "export" ] + }, + "version" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + } + }, + "required" : [ "id", "sync_task_type", "progress", "started_at", "status" ] + } + } + } + }, + "4XX" : { + "description" : "Client error response" + }, + "5XX" : { + "description" : "Server error response" + } + }, + "tags" : [ "/api/ee/remote-sync" ] + } + }, + "/api/ee/remote-sync/dirty" : { + "get" : { + "operationId" : "get-api-ee-remote-sync-dirty", + "summary" : "GET /api/ee/remote-sync/dirty", + "description" : "Return all models with changes that have not been pushed to the remote sync source in any\n remote-synced collection.", + "parameters" : [ ], + "responses" : { + "2XX" : { + "description" : "Successful response", + "content" : { + "application/json" : { + "schema" : { + "type" : "object", + "properties" : { + "dirty" : { + "type" : "array", + "items" : { + "type" : "object", + "properties" : { + "table_name" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "model" : { + "type" : "string" + }, + "authority_level" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "id" : { + "type" : "integer" + }, + "name" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "updated_at" : { + "oneOf" : [ { }, { + "type" : "null" + } ] + }, + "table_id" : { + "oneOf" : [ { + "type" : "integer", + "minimum" : 1 + }, { + "type" : "null" + } ] + }, + "query_type" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "collection_id" : { + "oneOf" : [ { + "type" : "integer", + "minimum" : 1 + }, { + "type" : "null" + } ] + }, + "created_at" : { }, + "display" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "sync_status" : { + "type" : "string" + }, + "description" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + } + }, + "required" : [ "id", "name", "model", "sync_status" ] + } + } + }, + "required" : [ "dirty" ] + } + } + } + }, + "4XX" : { + "description" : "Client error response" + }, + "5XX" : { + "description" : "Server error response" + } + }, + "tags" : [ "/api/ee/remote-sync" ] + } + }, + "/api/ee/remote-sync/export" : { + "post" : { + "operationId" : "post-api-ee-remote-sync-export", + "summary" : "POST /api/ee/remote-sync/export", + "description" : "Export the current state of the Remote Sync collection to a Source.\n\n This endpoint will:\n - Fetch the latest changes from the source\n - Create a branch or subdirectory (depending on source support)\n If no branch is supplied, use the configured export branch\n - Export the Remote Sync collection via serialization to the branch or subdirectory\n - Commit the changes if possible\n - Sync to the source if possible\n\n Requires superuser permissions.", + "parameters" : [ ], + "responses" : { + "2XX" : { + "description" : "Successful response", + "content" : { + "application/json" : { + "schema" : { + "type" : "object", + "properties" : { + "message" : { + "type" : "string" + }, + "task_id" : { + "type" : "integer", + "minimum" : 1 + } + }, + "required" : [ "message", "task_id" ] + } + } + } + }, + "4XX" : { + "description" : "Client error response" + }, + "5XX" : { + "description" : "Server error response" + } + }, + "tags" : [ "/api/ee/remote-sync" ] + } + }, + "/api/ee/remote-sync/has-remote-changes" : { + "get" : { + "operationId" : "get-api-ee-remote-sync-has-remote-changes", + "summary" : "GET /api/ee/remote-sync/has-remote-changes", + "description" : "Check if there are new changes on the remote branch that can be pulled.\n Uses in-memory caching (configurable TTL via remote-sync-check-changes-cache-ttl-seconds setting).\n\n Returns:\n - has_changes: true if remote version differs from last imported version, or if never imported\n - remote_version: current Git SHA on remote branch\n - local_version: Git SHA of last successful import (nil if never imported)\n - cached: true if result was served from cache", + "parameters" : [ { + "in" : "query", + "name" : "force-refresh", + "required" : false, + "schema" : { + "type" : "boolean" + } + } ], + "responses" : { + "2XX" : { + "description" : "Successful response", + "content" : { + "application/json" : { + "schema" : { + "type" : "object", + "properties" : { + "cached" : { + "type" : "boolean" + }, + "has_changes" : { + "type" : "boolean" + }, + "local_version" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "remote_version" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + } + }, + "required" : [ "has_changes", "remote_version", "local_version", "cached" ] + } + } + } + }, + "4XX" : { + "description" : "Client error response" + }, + "5XX" : { + "description" : "Server error response" + } + }, + "tags" : [ "/api/ee/remote-sync" ] + } + }, + "/api/ee/remote-sync/import" : { + "post" : { + "operationId" : "post-api-ee-remote-sync-import", + "summary" : "POST /api/ee/remote-sync/import", + "description" : "Import Metabase content from configured Remote Sync source.\n\n This endpoint will:\n - Fetch the latest changes from the configured source\n - Load the updated content using the serialization/deserialization system\n\n If `force=false` (default) and there are unsaved changes in the Remote Sync collection,\n the import returns a 400 response.\n\n Requires superuser permissions.", + "parameters" : [ ], + "responses" : { + "2XX" : { + "description" : "Successful response", + "content" : { + "application/json" : { + "schema" : { + "type" : "object", + "properties" : { + "message" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "status" : { + "const" : "success" + }, + "task_id" : { + "oneOf" : [ { + "type" : "integer", + "minimum" : 1 + }, { + "type" : "null" + } ] + } + }, + "required" : [ "status", "task_id" ] + } + } + } + }, + "4XX" : { + "description" : "Client error response" + }, + "5XX" : { + "description" : "Server error response" + } + }, + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "type" : "object", + "properties" : { + "branch" : { + "type" : "string", + "minLength" : 1 + }, + "force" : { + "type" : "boolean" + } + } + } + } + } + }, + "tags" : [ "/api/ee/remote-sync" ] + } + }, + "/api/ee/remote-sync/is-dirty" : { + "get" : { + "operationId" : "get-api-ee-remote-sync-is-dirty", + "summary" : "GET /api/ee/remote-sync/is-dirty", + "description" : "Check if any remote-synced collection or collection item has local changes that have not been pushed\n to the remote sync source.", + "parameters" : [ ], + "responses" : { + "2XX" : { + "description" : "Successful response", + "content" : { + "application/json" : { + "schema" : { + "type" : "object", + "properties" : { + "is_dirty" : { + "type" : "boolean" + } + }, + "required" : [ "is_dirty" ] + } + } + } + }, + "4XX" : { + "description" : "Client error response" + }, + "5XX" : { + "description" : "Server error response" + } + }, + "tags" : [ "/api/ee/remote-sync" ] + } + }, + "/api/ee/remote-sync/settings" : { + "put" : { + "operationId" : "put-api-ee-remote-sync-settings", + "summary" : "PUT /api/ee/remote-sync/settings", + "description" : "Update Remote Sync related settings. You must be a superuser to do this.", + "parameters" : [ ], + "responses" : { + "2XX" : { + "description" : "Successful response", + "content" : { + "application/json" : { + "schema" : { + "type" : "object", + "properties" : { + "success" : { + "type" : "boolean" + }, + "task_id" : { + "type" : "integer", + "minimum" : 1 + } + }, + "required" : [ "success" ] + } + } + } + }, + "4XX" : { + "description" : "Client error response" + }, + "5XX" : { + "description" : "Server error response" + } + }, + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "type" : "object", + "properties" : { + "collections" : { + "oneOf" : [ { + "type" : "object", + "additionalProperties" : { + "type" : "boolean" + } + }, { + "type" : "null" + } ] + }, + "remote-sync-auto-import" : { + "oneOf" : [ { + "type" : "boolean" + }, { + "type" : "null" + } ] + }, + "remote-sync-branch" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "remote-sync-token" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "remote-sync-transforms" : { + "oneOf" : [ { + "type" : "boolean" + }, { + "type" : "null" + } ] + }, + "remote-sync-type" : { + "oneOf" : [ { + "type" : "string", + "enum" : [ "read-only", "read-write" ] + }, { + "type" : "null" + } ] + }, + "remote-sync-url" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + } + } + } + } + } + }, + "tags" : [ "/api/ee/remote-sync" ] + } + }, + "/api/ee/remote-sync/stash" : { + "post" : { + "operationId" : "post-api-ee-remote-sync-stash", + "summary" : "POST /api/ee/remote-sync/stash", + "description" : "Stashes changes to a new branch, and changes the current branch to it.\n Requires superuser permissions.", + "parameters" : [ ], + "responses" : { + "2XX" : { + "description" : "Successful response", + "content" : { + "application/json" : { + "schema" : { + "type" : "object", + "properties" : { + "message" : { + "type" : "string" + }, + "status" : { + "type" : "string" + }, + "task_id" : { + "type" : "integer", + "minimum" : 1 + } + }, + "required" : [ "status", "message", "task_id" ] + } + } + } + }, + "4XX" : { + "description" : "Client error response" + }, + "5XX" : { + "description" : "Server error response" + } + }, + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "type" : "object", + "properties" : { + "message" : { + "type" : "string", + "minLength" : 1 + }, + "new_branch" : { + "type" : "string", + "minLength" : 1 + } + }, + "required" : [ "new_branch", "message" ] + } + } + } + }, + "tags" : [ "/api/ee/remote-sync" ] + } + }, + "/api/ee/replacement/check-replace-source" : { + "post" : { + "operationId" : "post-api-ee-replacement-check-replace-source", + "summary" : "POST /api/ee/replacement/check-replace-source", + "description" : "Check whether a source entity can be replaced by a target entity. Returns compatibility\n errors describing column mismatches, type mismatches, primary key mismatches, and foreign\n key mismatches.", + "parameters" : [ ], + "responses" : { + "2XX" : { + "description" : "Successful response", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/metabase-enterprise.replacement.schema.check-replace-source-response" + } + } + } + }, + "4XX" : { + "description" : "Client error response" + }, + "5XX" : { + "description" : "Server error response" + } + }, + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "type" : "object", + "properties" : { + "source_entity_id" : { + "$ref" : "#/components/schemas/metabase-enterprise.replacement.schema.source-entity-id" + }, + "source_entity_type" : { + "$ref" : "#/components/schemas/metabase-enterprise.replacement.schema.source-entity-type" + }, + "target_entity_id" : { + "$ref" : "#/components/schemas/metabase-enterprise.replacement.schema.source-entity-id" + }, + "target_entity_type" : { + "$ref" : "#/components/schemas/metabase-enterprise.replacement.schema.source-entity-type" + } + }, + "required" : [ "source_entity_id", "source_entity_type", "target_entity_id", "target_entity_type" ] + } + } + } + }, + "tags" : [ "/api/ee/replacement" ] + } + }, + "/api/ee/replacement/replace-model-with-transform" : { + "post" : { + "operationId" : "post-api-ee-replacement-replace-model-with-transform", + "summary" : "POST /api/ee/replacement/replace-model-with-transform", + "description" : "Create a transform from a model, execute it, and replace all usages of the model\n with the output table. Un-persists the model and converts it to a saved question.\n Returns 202 with a run_id for polling.\n\n If there is an error during the transform execution, no replacement will be\n performed and the model will remain unchanged.\n\n If there is an error during the source swap, the transform and the output\n table will be retained, and the model will remain unchanged. We cannot delete\n the transform or the output table because they can be used by other queries at\n this point.", + "parameters" : [ ], + "responses" : { + "2XX" : { + "description" : "Successful response", + "content" : { + "application/json" : { + "schema" : { + "type" : "object", + "properties" : { + "body" : { + "type" : "object", + "properties" : { + "run_id" : { + "$ref" : "#/components/schemas/metabase-enterprise.replacement.schema.run-id" + } + }, + "required" : [ "run_id" ], + "additionalProperties" : false + }, + "status" : { + "const" : 202 + } + }, + "required" : [ "status", "body" ] + } + } + } + }, + "4XX" : { + "description" : "Client error response" + }, + "5XX" : { + "description" : "Server error response" + } + }, + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "type" : "object", + "properties" : { + "card_id" : { + "$ref" : "#/components/schemas/metabase-enterprise.replacement.schema.source-entity-id" + }, + "target_collection_id" : { + "oneOf" : [ { + "$ref" : "#/components/schemas/metabase-enterprise.replacement.schema.source-entity-id" + }, { + "type" : "null" + } ] + }, + "transform_name" : { + "type" : "string" + }, + "transform_tag_ids" : { + "oneOf" : [ { + "type" : "array", + "items" : { + "type" : "integer", + "minimum" : 1 + } + }, { + "type" : "null" + } ] + }, + "transform_target" : { + "type" : "object", + "properties" : { } + } + }, + "required" : [ "card_id", "transform_name", "transform_target" ] + } + } + } + }, + "tags" : [ "/api/ee/replacement" ] + } + }, + "/api/ee/replacement/replace-source" : { + "post" : { + "operationId" : "post-api-ee-replacement-replace-source", + "summary" : "POST /api/ee/replacement/replace-source", + "description" : "Replace all usages of a source entity with a target entity asynchronously.\n Returns 202 with a run_id for polling. Returns 409 if a replacement is already running.", + "parameters" : [ ], + "responses" : { + "2XX" : { + "description" : "Successful response", + "content" : { + "application/json" : { + "schema" : { + "type" : "object", + "properties" : { + "body" : { + "type" : "object", + "properties" : { + "run_id" : { + "$ref" : "#/components/schemas/metabase-enterprise.replacement.schema.run-id" + } + }, + "required" : [ "run_id" ], + "additionalProperties" : false + }, + "status" : { + "const" : 202 + } + }, + "required" : [ "status", "body" ] + } + } + } + }, + "4XX" : { + "description" : "Client error response" + }, + "5XX" : { + "description" : "Server error response" + } + }, + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "type" : "object", + "properties" : { + "source_entity_id" : { + "$ref" : "#/components/schemas/metabase-enterprise.replacement.schema.source-entity-id" + }, + "source_entity_type" : { + "$ref" : "#/components/schemas/metabase-enterprise.replacement.schema.source-entity-type" + }, + "target_entity_id" : { + "$ref" : "#/components/schemas/metabase-enterprise.replacement.schema.source-entity-id" + }, + "target_entity_type" : { + "$ref" : "#/components/schemas/metabase-enterprise.replacement.schema.source-entity-type" + } + }, + "required" : [ "source_entity_id", "source_entity_type", "target_entity_id", "target_entity_type" ] + } + } + } + }, + "tags" : [ "/api/ee/replacement" ] + } + }, + "/api/ee/replacement/runs" : { + "get" : { + "operationId" : "get-api-ee-replacement-runs", + "summary" : "GET /api/ee/replacement/runs", + "description" : "List replacement runs, optionally filtered by is-active.", + "parameters" : [ { + "in" : "query", + "name" : "is-active", + "required" : false, + "schema" : { + "oneOf" : [ { + "type" : "boolean" + }, { + "type" : "null" + } ] + } + } ], + "responses" : { + "2XX" : { + "description" : "Successful response", + "content" : { + "application/json" : { + "schema" : { + "type" : "array", + "items" : { + "$ref" : "#/components/schemas/metabase-enterprise.replacement.schema.run" + } + } + } + } + }, + "4XX" : { + "description" : "Client error response" + }, + "5XX" : { + "description" : "Server error response" + } + }, + "tags" : [ "/api/ee/replacement" ] + } + }, + "/api/ee/replacement/runs/{id}" : { + "get" : { + "operationId" : "get-api-ee-replacement-runs-id", + "summary" : "GET /api/ee/replacement/runs/{id}", + "description" : "Get the status of a source replacement run.", + "parameters" : [ { + "in" : "path", + "name" : "id", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/metabase-enterprise.replacement.schema.run-id" + } + } ], + "responses" : { + "2XX" : { + "description" : "Successful response", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/metabase-enterprise.replacement.schema.run" + } + } + } + }, + "4XX" : { + "description" : "Client error response" + }, + "5XX" : { + "description" : "Server error response" + } + }, + "tags" : [ "/api/ee/replacement" ] + } + }, + "/api/ee/replacement/runs/{id}/cancel" : { + "post" : { + "operationId" : "post-api-ee-replacement-runs-id-cancel", + "summary" : "POST /api/ee/replacement/runs/{id}/cancel", + "description" : "Cancel a running source replacement.", + "parameters" : [ { + "in" : "path", + "name" : "id", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/metabase-enterprise.replacement.schema.run-id" + } + } ], + "responses" : { + "2XX" : { + "description" : "Successful response", + "content" : { + "application/json" : { + "schema" : { + "type" : "object", + "properties" : { + "success" : { + "type" : "boolean" + } + }, + "required" : [ "success" ] + } + } + } + }, + "4XX" : { + "description" : "Client error response" + }, + "5XX" : { + "description" : "Server error response" + } + }, + "tags" : [ "/api/ee/replacement" ] + } + }, + "/api/ee/scim/api_key" : { + "get" : { + "operationId" : "get-api-ee-scim-api_key", + "summary" : "GET /api/ee/scim/api_key", + "description" : "Fetch the SCIM API key if one exists. Does *not* return an unmasked key, since we don't have access\n to that after it is created.", + "parameters" : [ ], + "responses" : { + "2XX" : { + "description" : "Successful response" + }, + "4XX" : { + "description" : "Client error response" + }, + "5XX" : { + "description" : "Server error response" + } + }, + "tags" : [ "/api/ee/scim" ] + }, + "post" : { + "operationId" : "post-api-ee-scim-api_key", + "summary" : "POST /api/ee/scim/api_key", + "description" : "Create a new SCIM API key, or refresh one that already exists. When called for the first time,\n this is equivalent to enabling SCIM.", + "parameters" : [ ], + "responses" : { + "2XX" : { + "description" : "Successful response" + }, + "4XX" : { + "description" : "Client error response" + }, + "5XX" : { + "description" : "Server error response" + } + }, + "tags" : [ "/api/ee/scim" ] + } + }, + "/api/ee/scim/v2/Groups" : { + "get" : { + "operationId" : "get-api-ee-scim-v2-Groups", + "summary" : "GET /api/ee/scim/v2/Groups", + "description" : "Fetch a list of groups.", + "parameters" : [ { + "in" : "query", + "name" : "startIndex", + "required" : false, + "schema" : { + "oneOf" : [ { + "description" : "value must be an integer greater than zero.", + "type" : "integer", + "minimum" : 1 + }, { + "type" : "null" + } ] + } + }, { + "in" : "query", + "name" : "count", + "required" : false, + "schema" : { + "oneOf" : [ { + "description" : "value must be an integer greater than zero.", + "type" : "integer", + "minimum" : 1 + }, { + "type" : "null" + } ] + } + }, { + "in" : "query", + "name" : "filter", + "required" : false, + "schema" : { + "oneOf" : [ { + "type" : "string", + "minLength" : 1 + }, { + "type" : "null" + } ] + } + } ], + "responses" : { + "2XX" : { + "description" : "Successful response" + }, + "4XX" : { + "description" : "Client error response" + }, + "5XX" : { + "description" : "Server error response" + } + }, + "tags" : [ "/api/ee/scim/v2" ] + }, + "post" : { + "operationId" : "post-api-ee-scim-v2-Groups", + "summary" : "POST /api/ee/scim/v2/Groups", + "description" : "Create a single group, and populates it if necessary.", + "parameters" : [ ], + "responses" : { + "2XX" : { + "description" : "Successful response" + }, + "4XX" : { + "description" : "Client error response" + }, + "5XX" : { + "description" : "Server error response" + } + }, + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "type" : "object", + "properties" : { + "displayName" : { + "type" : "string", + "minLength" : 1 + }, + "id" : { + "type" : "string", + "minLength" : 1 + }, + "members" : { + "type" : "array", + "items" : { + "type" : "object", + "properties" : { + "$ref" : { + "type" : "string", + "minLength" : 1 + }, + "value" : { + "type" : "string", + "minLength" : 1 + } + }, + "required" : [ "value" ] + } + }, + "schemas" : { + "type" : "array", + "items" : { + "type" : "string", + "minLength" : 1 + } + } + }, + "required" : [ "schemas", "displayName" ] + } + } + } + }, + "tags" : [ "/api/ee/scim/v2" ] + } + }, + "/api/ee/scim/v2/Groups/{id}" : { + "get" : { + "operationId" : "get-api-ee-scim-v2-Groups-id", + "summary" : "GET /api/ee/scim/v2/Groups/{id}", + "description" : "Fetch a single group.", + "parameters" : [ { + "in" : "path", + "name" : "id", + "required" : true, + "schema" : { + "type" : "string", + "minLength" : 1 + } + } ], + "responses" : { + "2XX" : { + "description" : "Successful response" + }, + "4XX" : { + "description" : "Client error response" + }, + "5XX" : { + "description" : "Server error response" + } + }, + "tags" : [ "/api/ee/scim/v2" ] + }, + "put" : { + "operationId" : "put-api-ee-scim-v2-Groups-id", + "summary" : "PUT /api/ee/scim/v2/Groups/{id}", + "description" : "Update a group.", + "parameters" : [ ], + "responses" : { + "2XX" : { + "description" : "Successful response" + }, + "4XX" : { + "description" : "Client error response" + }, + "5XX" : { + "description" : "Server error response" + } + }, + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "type" : "object", + "properties" : { + "displayName" : { + "type" : "string", + "minLength" : 1 + }, + "id" : { + "type" : "string", + "minLength" : 1 + }, + "members" : { + "type" : "array", + "items" : { + "type" : "object", + "properties" : { + "$ref" : { + "type" : "string", + "minLength" : 1 + }, + "value" : { + "type" : "string", + "minLength" : 1 + } + }, + "required" : [ "value" ] + } + }, + "schemas" : { + "type" : "array", + "items" : { + "type" : "string", + "minLength" : 1 + } + } + }, + "required" : [ "schemas", "displayName" ] + } + } + } + }, + "tags" : [ "/api/ee/scim/v2" ] + }, + "delete" : { + "operationId" : "delete-api-ee-scim-v2-Groups-id", + "summary" : "DELETE /api/ee/scim/v2/Groups/{id}", + "description" : "Delete a group.", + "parameters" : [ { + "in" : "path", + "name" : "id", + "required" : true, + "schema" : { + "type" : "string", + "minLength" : 1 + } + } ], + "responses" : { + "2XX" : { + "description" : "Successful response" + }, + "4XX" : { + "description" : "Client error response" + }, + "5XX" : { + "description" : "Server error response" + } + }, + "tags" : [ "/api/ee/scim/v2" ] + } + }, + "/api/ee/scim/v2/Users" : { + "get" : { + "operationId" : "get-api-ee-scim-v2-Users", + "summary" : "GET /api/ee/scim/v2/Users", + "description" : "Fetch a list of users.", + "parameters" : [ { + "in" : "query", + "name" : "startIndex", + "required" : false, + "schema" : { + "oneOf" : [ { + "description" : "value must be an integer greater than zero.", + "type" : "integer", + "minimum" : 1 + }, { + "type" : "null" + } ] + } + }, { + "in" : "query", + "name" : "count", + "required" : false, + "schema" : { + "oneOf" : [ { + "description" : "value must be an integer greater than zero.", + "type" : "integer", + "minimum" : 1 + }, { + "type" : "null" + } ] + } + }, { + "in" : "query", + "name" : "filter", + "required" : false, + "schema" : { + "oneOf" : [ { + "type" : "string", + "minLength" : 1 + }, { + "type" : "null" + } ] + } + } ], + "responses" : { + "2XX" : { + "description" : "Successful response" + }, + "4XX" : { + "description" : "Client error response" + }, + "5XX" : { + "description" : "Server error response" + } + }, + "tags" : [ "/api/ee/scim/v2" ] + }, + "post" : { + "operationId" : "post-api-ee-scim-v2-Users", + "summary" : "POST /api/ee/scim/v2/Users", + "description" : "Create a single user.", + "parameters" : [ ], + "responses" : { + "2XX" : { + "description" : "Successful response" + }, + "4XX" : { + "description" : "Client error response" + }, + "5XX" : { + "description" : "Server error response" + } + }, + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "type" : "object", + "properties" : { + "active" : { + "type" : "boolean" + }, + "emails" : { + "type" : "array", + "items" : { + "type" : "object", + "properties" : { + "primary" : { + "type" : "boolean" + }, + "type" : { + "type" : "string", + "minLength" : 1 + }, + "value" : { + "type" : "string", + "minLength" : 1 + } + }, + "required" : [ "value" ] + } + }, + "groups" : { + "type" : "array", + "items" : { + "type" : "object", + "properties" : { + "$ref" : { + "type" : "string", + "minLength" : 1 + }, + "display" : { + "type" : "string", + "minLength" : 1 + }, + "value" : { + "type" : "string", + "minLength" : 1 + } + }, + "required" : [ "value", "display" ] + } + }, + "id" : { + "type" : "string", + "minLength" : 1 + }, + "locale" : { + "oneOf" : [ { + "type" : "string", + "minLength" : 1 + }, { + "type" : "null" + } ] + }, + "name" : { + "type" : "object", + "properties" : { + "familyName" : { + "type" : "string" + }, + "givenName" : { + "type" : "string" + } + }, + "required" : [ "givenName", "familyName" ] + }, + "schemas" : { + "type" : "array", + "items" : { + "type" : "string", + "minLength" : 1 + } + }, + "userName" : { + "type" : "string", + "minLength" : 1 + } + }, + "required" : [ "schemas", "userName", "name", "emails" ] + } + } + } + }, + "tags" : [ "/api/ee/scim/v2" ] + } + }, + "/api/ee/scim/v2/Users/{id}" : { + "get" : { + "operationId" : "get-api-ee-scim-v2-Users-id", + "summary" : "GET /api/ee/scim/v2/Users/{id}", + "description" : "Fetch a single user.", + "parameters" : [ { + "in" : "path", + "name" : "id", + "required" : true, + "schema" : { + "type" : "string", + "minLength" : 1 + } + } ], + "responses" : { + "2XX" : { + "description" : "Successful response" + }, + "4XX" : { + "description" : "Client error response" + }, + "5XX" : { + "description" : "Server error response" + } + }, + "tags" : [ "/api/ee/scim/v2" ] + }, + "put" : { + "operationId" : "put-api-ee-scim-v2-Users-id", + "summary" : "PUT /api/ee/scim/v2/Users/{id}", + "description" : "Update a user.", + "parameters" : [ ], + "responses" : { + "2XX" : { + "description" : "Successful response" + }, + "4XX" : { + "description" : "Client error response" + }, + "5XX" : { + "description" : "Server error response" + } + }, + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "type" : "object", + "properties" : { + "active" : { + "type" : "boolean" + }, + "emails" : { + "type" : "array", + "items" : { + "type" : "object", + "properties" : { + "primary" : { + "type" : "boolean" + }, + "type" : { + "type" : "string", + "minLength" : 1 + }, + "value" : { + "type" : "string", + "minLength" : 1 + } + }, + "required" : [ "value" ] + } + }, + "groups" : { + "type" : "array", + "items" : { + "type" : "object", + "properties" : { + "$ref" : { + "type" : "string", + "minLength" : 1 + }, + "display" : { + "type" : "string", + "minLength" : 1 + }, + "value" : { + "type" : "string", + "minLength" : 1 + } + }, + "required" : [ "value", "display" ] + } + }, + "id" : { + "type" : "string", + "minLength" : 1 + }, + "locale" : { + "oneOf" : [ { + "type" : "string", + "minLength" : 1 + }, { + "type" : "null" + } ] + }, + "name" : { + "type" : "object", + "properties" : { + "familyName" : { + "type" : "string" + }, + "givenName" : { + "type" : "string" + } + }, + "required" : [ "givenName", "familyName" ] + }, + "schemas" : { + "type" : "array", + "items" : { + "type" : "string", + "minLength" : 1 + } + }, + "userName" : { + "type" : "string", + "minLength" : 1 + } + }, + "required" : [ "schemas", "userName", "name", "emails" ] + } + } + } + }, + "tags" : [ "/api/ee/scim/v2" ] + }, + "patch" : { + "operationId" : "patch-api-ee-scim-v2-Users-id", + "summary" : "PATCH /api/ee/scim/v2/Users/{id}", + "description" : "Activate or deactivate a user. Supports specific replace operations, but not arbitrary patches.", + "parameters" : [ { + "in" : "path", + "name" : "id", + "required" : true, + "schema" : { + "type" : "string", + "minLength" : 1 + } + } ], + "responses" : { + "2XX" : { + "description" : "Successful response" + }, + "4XX" : { + "description" : "Client error response" + }, + "5XX" : { + "description" : "Server error response" + } + }, + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "type" : "object", + "properties" : { + "Operations" : { + "type" : "array", + "items" : { + "type" : "object", + "properties" : { + "op" : { + "type" : "string", + "minLength" : 1 + }, + "value" : { + "anyOf" : [ { + "type" : "object", + "additionalProperties" : { + "anyOf" : [ { + "type" : "string", + "minLength" : 1 + }, { + "type" : "boolean" + } ] + } + }, { + "type" : "string", + "minLength" : 1 + }, { + "type" : "boolean" + } ] + } + }, + "required" : [ "op", "value" ] + } + }, + "schemas" : { + "type" : "array", + "items" : { + "type" : "string", + "minLength" : 1 + } + } + }, + "required" : [ "schemas", "Operations" ] + } + } + } + }, + "tags" : [ "/api/ee/scim/v2" ] + } + }, + "/api/ee/security-center" : { + "get" : { + "operationId" : "get-api-ee-security-center", + "summary" : "GET /api/ee/security-center", + "description" : "List all security advisories with match status.", + "parameters" : [ ], + "responses" : { + "2XX" : { + "description" : "Successful response", + "content" : { + "application/json" : { + "schema" : { + "type" : "object", + "properties" : { + "advisories" : { + "type" : "array", + "items" : { + "type" : "object", + "properties" : { + "published_at" : { + "type" : "string", + "format" : "date-time" + }, + "advisory_url" : { "oneOf" : [ { - "type" : "string" + "type" : "string", + "minLength" : 1 }, { "type" : "null" } ] }, - "collection_id" : { + "last_evaluated_at" : { "oneOf" : [ { - "type" : "integer", - "minimum" : 1 + "type" : "string", + "format" : "date-time" }, { "type" : "null" } ] }, - "created_at" : { }, - "display" : { + "match_status" : { + "$ref" : "#/components/schemas/metabase-enterprise.security-center.schema.match-status" + }, + "acknowledged_by" : { "oneOf" : [ { - "type" : "string" + "type" : "object", + "properties" : { + "common_name" : { + "type" : "string", + "minLength" : 1 + }, + "email" : { + "description" : "value must be a valid email address.", + "type" : "string" + }, + "id" : { + "description" : "value must be an integer greater than zero.", + "type" : "integer", + "minimum" : 1 + } + }, + "required" : [ "id", "common_name", "email" ] }, { "type" : "null" } ] }, - "sync_status" : { - "type" : "string" + "title" : { + "type" : "string", + "minLength" : 1 + }, + "affected_versions" : { + "$ref" : "#/components/schemas/metabase-enterprise.security-center.schema.affected-versions" + }, + "remediation" : { + "type" : "string", + "minLength" : 1 + }, + "advisory_id" : { + "$ref" : "#/components/schemas/metabase-enterprise.security-center.schema.advisory-id" + }, + "severity" : { + "$ref" : "#/components/schemas/metabase-enterprise.security-center.schema.severity" }, "description" : { + "type" : "string", + "minLength" : 1 + }, + "acknowledged_at" : { "oneOf" : [ { - "type" : "string" + "type" : "string", + "format" : "date-time" }, { "type" : "null" } ] } }, - "required" : [ "id", "name", "model", "sync_status" ] + "required" : [ "advisory_id", "title", "severity", "description", "advisory_url", "remediation", "published_at", "match_status", "last_evaluated_at", "acknowledged_by", "acknowledged_at", "affected_versions" ] } + }, + "last_checked_at" : { + "oneOf" : [ { + "type" : "string", + "format" : "date-time" + }, { + "type" : "null" + } ] } }, - "required" : [ "dirty" ] + "required" : [ "last_checked_at", "advisories" ] } } } @@ -26439,14 +29903,14 @@ "description" : "Server error response" } }, - "tags" : [ "/api/ee/remote-sync" ] + "tags" : [ "/api/ee/security-center" ] } }, - "/api/ee/remote-sync/export" : { + "/api/ee/security-center/acknowledge" : { "post" : { - "operationId" : "post-api-ee-remote-sync-export", - "summary" : "POST /api/ee/remote-sync/export", - "description" : "Export the current state of the Remote Sync collection to a Source.\n\n This endpoint will:\n - Fetch the latest changes from the source\n - Create a branch or subdirectory (depending on source support)\n If no branch is supplied, use the configured export branch\n - Export the Remote Sync collection via serialization to the branch or subdirectory\n - Commit the changes if possible\n - Sync to the source if possible\n\n Requires superuser permissions.", + "operationId" : "post-api-ee-security-center-acknowledge", + "summary" : "POST /api/ee/security-center/acknowledge", + "description" : "Acknowledge multiple security advisories. Skips already-acknowledged advisories.", "parameters" : [ ], "responses" : { "2XX" : { @@ -26454,17 +29918,50 @@ "content" : { "application/json" : { "schema" : { - "type" : "object", - "properties" : { - "message" : { - "type" : "string" + "type" : "array", + "items" : { + "type" : "object", + "properties" : { + "acknowledged_at" : { + "oneOf" : [ { + "type" : "string", + "format" : "date-time" + }, { + "type" : "null" + } ] + }, + "acknowledged_by" : { + "oneOf" : [ { + "type" : "object", + "properties" : { + "common_name" : { + "type" : "string", + "minLength" : 1 + }, + "email" : { + "description" : "value must be a valid email address.", + "type" : "string" + }, + "id" : { + "description" : "value must be an integer greater than zero.", + "type" : "integer", + "minimum" : 1 + } + }, + "required" : [ "id", "common_name", "email" ] + }, { + "type" : "null" + } ] + }, + "advisory_id" : { + "$ref" : "#/components/schemas/metabase-enterprise.security-center.schema.advisory-id" + }, + "match_status" : { + "$ref" : "#/components/schemas/metabase-enterprise.security-center.schema.match-status" + } }, - "task_id" : { - "type" : "integer", - "minimum" : 1 - } - }, - "required" : [ "message", "task_id" ] + "required" : [ "advisory_id", "match_status", "acknowledged_by", "acknowledged_at" ] + } } } } @@ -26476,22 +29973,34 @@ "description" : "Server error response" } }, - "tags" : [ "/api/ee/remote-sync" ] + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "type" : "object", + "properties" : { + "advisory_ids" : { + "type" : "array", + "items" : { + "type" : "string", + "minLength" : 1 + } + } + }, + "required" : [ "advisory_ids" ] + } + } + } + }, + "tags" : [ "/api/ee/security-center" ] } }, - "/api/ee/remote-sync/has-remote-changes" : { - "get" : { - "operationId" : "get-api-ee-remote-sync-has-remote-changes", - "summary" : "GET /api/ee/remote-sync/has-remote-changes", - "description" : "Check if there are new changes on the remote branch that can be pulled.\n Uses in-memory caching (configurable TTL via remote-sync-check-changes-cache-ttl-seconds setting).\n\n Returns:\n - has_changes: true if remote version differs from last imported version, or if never imported\n - remote_version: current Git SHA on remote branch\n - local_version: Git SHA of last successful import (nil if never imported)\n - cached: true if result was served from cache", - "parameters" : [ { - "in" : "query", - "name" : "force-refresh", - "required" : false, - "schema" : { - "type" : "boolean" - } - } ], + "/api/ee/security-center/sync" : { + "post" : { + "operationId" : "post-api-ee-security-center-sync", + "summary" : "POST /api/ee/security-center/sync", + "description" : "Trigger an async advisory sync + re-evaluation.\n Returns immediately. If a sync is already running, the request is a no-op.", + "parameters" : [ ], "responses" : { "2XX" : { "description" : "Successful response", @@ -26500,28 +30009,12 @@ "schema" : { "type" : "object", "properties" : { - "cached" : { - "type" : "boolean" - }, - "has_changes" : { - "type" : "boolean" - }, - "local_version" : { - "oneOf" : [ { - "type" : "string" - }, { - "type" : "null" - } ] - }, - "remote_version" : { - "oneOf" : [ { - "type" : "string" - }, { - "type" : "null" - } ] + "status" : { + "type" : "string", + "minLength" : 1 } }, - "required" : [ "has_changes", "remote_version", "local_version", "cached" ] + "required" : [ "status" ] } } } @@ -26533,14 +30026,14 @@ "description" : "Server error response" } }, - "tags" : [ "/api/ee/remote-sync" ] + "tags" : [ "/api/ee/security-center" ] } }, - "/api/ee/remote-sync/import" : { + "/api/ee/security-center/test-notification" : { "post" : { - "operationId" : "post-api-ee-remote-sync-import", - "summary" : "POST /api/ee/remote-sync/import", - "description" : "Import Metabase content from configured Remote Sync source.\n\n This endpoint will:\n - Fetch the latest changes from the configured source\n - Load the updated content using the serialization/deserialization system\n\n If `force=false` (default) and there are unsaved changes in the Remote Sync collection,\n the import returns a 400 response.\n\n Requires superuser permissions.", + "operationId" : "post-api-ee-security-center-test-notification", + "summary" : "POST /api/ee/security-center/test-notification", + "description" : "Send a test notification through the given Security Center channels.\n\n The request body lets callers pass the unsaved notification config from the\n dialog so the test reflects current form state, not the persisted settings.\n Both fields are optional; when omitted, the saved setting is used.", "parameters" : [ ], "responses" : { "2XX" : { @@ -26550,26 +30043,11 @@ "schema" : { "type" : "object", "properties" : { - "message" : { - "oneOf" : [ { - "type" : "string" - }, { - "type" : "null" - } ] - }, - "status" : { - "const" : "success" - }, - "task_id" : { - "oneOf" : [ { - "type" : "integer", - "minimum" : 1 - }, { - "type" : "null" - } ] + "success" : { + "type" : "boolean" } }, - "required" : [ "status", "task_id" ] + "required" : [ "success" ] } } } @@ -26587,27 +30065,45 @@ "schema" : { "type" : "object", "properties" : { - "branch" : { - "type" : "string", - "minLength" : 1 + "email_recipients" : { + "oneOf" : [ { + "type" : "array", + "items" : { + "$ref" : "#/components/schemas/metabase.notification.models.NotificationRecipient" + } + }, { + "type" : "null" + } ] }, - "force" : { - "type" : "boolean" + "slack_channel" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] } } } } } }, - "tags" : [ "/api/ee/remote-sync" ] + "tags" : [ "/api/ee/security-center" ] } }, - "/api/ee/remote-sync/is-dirty" : { - "get" : { - "operationId" : "get-api-ee-remote-sync-is-dirty", - "summary" : "GET /api/ee/remote-sync/is-dirty", - "description" : "Check if any remote-synced collection or collection item has local changes that have not been pushed\n to the remote sync source.", - "parameters" : [ ], + "/api/ee/security-center/{advisory-id}/acknowledge" : { + "post" : { + "operationId" : "post-api-ee-security-center-advisory-id-acknowledge", + "summary" : "POST /api/ee/security-center/{advisory-id}/acknowledge", + "description" : "Acknowledge a security advisory. Stops repeat notifications.", + "parameters" : [ { + "in" : "path", + "name" : "advisory-id", + "required" : true, + "schema" : { + "type" : "string", + "minLength" : 1 + } + } ], "responses" : { "2XX" : { "description" : "Successful response", @@ -26616,11 +30112,45 @@ "schema" : { "type" : "object", "properties" : { - "is_dirty" : { - "type" : "boolean" + "acknowledged_at" : { + "oneOf" : [ { + "type" : "string", + "format" : "date-time" + }, { + "type" : "null" + } ] + }, + "acknowledged_by" : { + "oneOf" : [ { + "type" : "object", + "properties" : { + "common_name" : { + "type" : "string", + "minLength" : 1 + }, + "email" : { + "description" : "value must be a valid email address.", + "type" : "string" + }, + "id" : { + "description" : "value must be an integer greater than zero.", + "type" : "integer", + "minimum" : 1 + } + }, + "required" : [ "id", "common_name", "email" ] + }, { + "type" : "null" + } ] + }, + "advisory_id" : { + "$ref" : "#/components/schemas/metabase-enterprise.security-center.schema.advisory-id" + }, + "match_status" : { + "$ref" : "#/components/schemas/metabase-enterprise.security-center.schema.match-status" } }, - "required" : [ "is_dirty" ] + "required" : [ "advisory_id", "match_status", "acknowledged_by", "acknowledged_at" ] } } } @@ -26632,35 +30162,18 @@ "description" : "Server error response" } }, - "tags" : [ "/api/ee/remote-sync" ] + "tags" : [ "/api/ee/security-center" ] } }, - "/api/ee/remote-sync/settings" : { - "put" : { - "operationId" : "put-api-ee-remote-sync-settings", - "summary" : "PUT /api/ee/remote-sync/settings", - "description" : "Update Remote Sync related settings. You must be a superuser to do this.", + "/api/ee/semantic-search/status" : { + "get" : { + "operationId" : "get-api-ee-semantic-search-status", + "summary" : "GET /api/ee/semantic-search/status", + "description" : "Fetch the indexing status of the currently active semantic search index table.\n\n Returns a map with keys:\n :indexed_count \n :total_est \n\n If no index is active, returns an empty map.", "parameters" : [ ], "responses" : { "2XX" : { - "description" : "Successful response", - "content" : { - "application/json" : { - "schema" : { - "type" : "object", - "properties" : { - "success" : { - "type" : "boolean" - }, - "task_id" : { - "type" : "integer", - "minimum" : 1 - } - }, - "required" : [ "success" ] - } - } - } + "description" : "Successful response" }, "4XX" : { "description" : "Client error response" @@ -26669,102 +30182,111 @@ "description" : "Server error response" } }, - "requestBody" : { - "content" : { - "application/json" : { - "schema" : { - "type" : "object", - "properties" : { - "collections" : { - "oneOf" : [ { - "type" : "object", - "additionalProperties" : { - "type" : "boolean" - } - }, { - "type" : "null" - } ] - }, - "remote-sync-auto-import" : { - "oneOf" : [ { - "type" : "boolean" - }, { - "type" : "null" - } ] - }, - "remote-sync-branch" : { - "oneOf" : [ { - "type" : "string" - }, { - "type" : "null" - } ] - }, - "remote-sync-token" : { - "oneOf" : [ { - "type" : "string" - }, { - "type" : "null" - } ] - }, - "remote-sync-transforms" : { - "oneOf" : [ { - "type" : "boolean" - }, { - "type" : "null" - } ] - }, - "remote-sync-type" : { - "oneOf" : [ { - "type" : "string", - "enum" : [ "read-only", "read-write" ] - }, { - "type" : "null" - } ] - }, - "remote-sync-url" : { - "oneOf" : [ { - "type" : "string" - }, { - "type" : "null" - } ] - } - } - } - } - } - }, - "tags" : [ "/api/ee/remote-sync" ] + "tags" : [ "/api/ee/semantic-search" ] } }, - "/api/ee/remote-sync/stash" : { + "/api/ee/serialization/export" : { "post" : { - "operationId" : "post-api-ee-remote-sync-stash", - "summary" : "POST /api/ee/remote-sync/stash", - "description" : "Stashes changes to a new branch, and changes the current branch to it.\n Requires superuser permissions.", - "parameters" : [ ], + "operationId" : "post-api-ee-serialization-export", + "summary" : "POST /api/ee/serialization/export", + "description" : "Serialize and retrieve Metabase instance.\n\n Outputs `.tar.gz` file with serialization results and an `export.log` file.\n On error outputs serialization logs directly.", + "parameters" : [ { + "in" : "query", + "name" : "dirname", + "required" : false, + "schema" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "description" : "name of directory and archive file (default: `-`)" + }, { + "in" : "query", + "name" : "collection", + "required" : false, + "schema" : { + "oneOf" : [ { + "type" : "array", + "items" : { + "anyOf" : [ { + "description" : "value must be an integer greater than zero.", + "type" : "integer", + "minimum" : 1 + }, { + "type" : "string", + "pattern" : "^.{21}$" + }, { + "type" : "string", + "pattern" : "^eid:.{21}$" + } ] + } + }, { + "type" : "null" + } ] + }, + "description" : "collections' db ids/entity-ids to serialize" + }, { + "in" : "query", + "name" : "all_collections", + "required" : true, + "schema" : { + "default" : true, + "type" : "boolean" + } + }, { + "in" : "query", + "name" : "settings", + "required" : true, + "schema" : { + "default" : true, + "type" : "boolean" + } + }, { + "in" : "query", + "name" : "data_model", + "required" : true, + "schema" : { + "default" : true, + "type" : "boolean" + } + }, { + "in" : "query", + "name" : "field_values", + "required" : true, + "schema" : { + "default" : false, + "type" : "boolean" + } + }, { + "in" : "query", + "name" : "database_secrets", + "required" : true, + "schema" : { + "default" : false, + "type" : "boolean" + } + }, { + "in" : "query", + "name" : "continue_on_error", + "required" : true, + "schema" : { + "default" : false, + "type" : "boolean" + } + }, { + "in" : "query", + "name" : "full_stacktrace", + "required" : true, + "schema" : { + "default" : false, + "type" : "boolean" + } + } ], "responses" : { "2XX" : { - "description" : "Successful response", - "content" : { - "application/json" : { - "schema" : { - "type" : "object", - "properties" : { - "message" : { - "type" : "string" - }, - "status" : { - "type" : "string" - }, - "task_id" : { - "type" : "integer", - "minimum" : 1 - } - }, - "required" : [ "status", "message", "task_id" ] - } - } - } + "description" : "Successful response" }, "4XX" : { "description" : "Client error response" @@ -26773,45 +30295,42 @@ "description" : "Server error response" } }, - "requestBody" : { - "content" : { - "application/json" : { - "schema" : { - "type" : "object", - "properties" : { - "message" : { - "type" : "string", - "minLength" : 1 - }, - "new_branch" : { - "type" : "string", - "minLength" : 1 - } - }, - "required" : [ "new_branch", "message" ] - } - } - } - }, - "tags" : [ "/api/ee/remote-sync" ] + "tags" : [ "/api/ee/serialization" ] } }, - "/api/ee/replacement/check-replace-source" : { + "/api/ee/serialization/import" : { "post" : { - "operationId" : "post-api-ee-replacement-check-replace-source", - "summary" : "POST /api/ee/replacement/check-replace-source", - "description" : "Check whether a source entity can be replaced by a target entity. Returns compatibility\n errors describing column mismatches, type mismatches, primary key mismatches, and foreign\n key mismatches.", - "parameters" : [ ], + "operationId" : "post-api-ee-serialization-import", + "summary" : "POST /api/ee/serialization/import", + "description" : "Deserialize Metabase instance from an archive generated by /export.\n\n Parameters:\n - `file`: archive encoded as `multipart/form-data` (required).\n\n Returns logs of deserialization.", + "parameters" : [ { + "in" : "query", + "name" : "continue_on_error", + "required" : true, + "schema" : { + "default" : false, + "type" : "boolean" + } + }, { + "in" : "query", + "name" : "full_stacktrace", + "required" : true, + "schema" : { + "default" : false, + "type" : "boolean" + } + }, { + "in" : "query", + "name" : "reindex", + "required" : true, + "schema" : { + "default" : true, + "type" : "boolean" + } + } ], "responses" : { "2XX" : { - "description" : "Successful response", - "content" : { - "application/json" : { - "schema" : { - "$ref" : "#/components/schemas/metabase-enterprise.replacement.schema.check-replace-source-response" - } - } - } + "description" : "Successful response" }, "4XX" : { "description" : "Client error response" @@ -26822,60 +30341,86 @@ }, "requestBody" : { "content" : { - "application/json" : { + "multipart/form-data" : { "schema" : { "type" : "object", "properties" : { - "source_entity_id" : { - "$ref" : "#/components/schemas/metabase-enterprise.replacement.schema.source-entity-id" - }, - "source_entity_type" : { - "$ref" : "#/components/schemas/metabase-enterprise.replacement.schema.source-entity-type" - }, - "target_entity_id" : { - "$ref" : "#/components/schemas/metabase-enterprise.replacement.schema.source-entity-id" - }, - "target_entity_type" : { - "$ref" : "#/components/schemas/metabase-enterprise.replacement.schema.source-entity-type" + "file" : { + "description" : ".tgz with serialization data", + "type" : "object", + "properties" : { + "content-type" : { + "type" : "string" + }, + "filename" : { + "type" : "string" + }, + "size" : { + "type" : "integer" + }, + "tempfile" : { } + }, + "required" : [ "content-type", "filename", "size", "tempfile" ], + "additionalProperties" : false } }, - "required" : [ "source_entity_id", "source_entity_type", "target_entity_id", "target_entity_type" ] + "required" : [ "file" ] } } } }, - "tags" : [ "/api/ee/replacement" ] + "tags" : [ "/api/ee/serialization" ] } }, - "/api/ee/replacement/replace-model-with-transform" : { + "/api/ee/serialization/metadata/export" : { "post" : { - "operationId" : "post-api-ee-replacement-replace-model-with-transform", - "summary" : "POST /api/ee/replacement/replace-model-with-transform", - "description" : "Create a transform from a model, execute it, and replace all usages of the model\n with the output table. Un-persists the model and converts it to a saved question.\n Returns 202 with a run_id for polling.\n\n If there is an error during the transform execution, no replacement will be\n performed and the model will remain unchanged.\n\n If there is an error during the source swap, the transform and the output\n table will be retained, and the model will remain unchanged. We cannot delete\n the transform or the output table because they can be used by other queries at\n this point.", - "parameters" : [ ], + "operationId" : "post-api-ee-serialization-metadata-export", + "summary" : "POST /api/ee/serialization/metadata/export", + "description" : "Get warehouse metadata (databases, tables, and fields) for all databases visible to the\n current user. References between rows are emitted as raw numeric ids (`db_id`,\n `table_id`, `parent_id`, `fk_target_field_id`).\n\n Sections must be opted into with the `with-databases`, `with-tables`, and `with-fields`\n query parameters — they all default to `false`. The response is streamed for efficiency\n with large schemas.\n\n Requires `View data` → `Can view` and `Create queries` → `Query builder only` (or\n `Query builder and native`) permissions on each database and table.", + "parameters" : [ { + "in" : "query", + "name" : "with-databases", + "required" : true, + "schema" : { + "default" : false, + "oneOf" : [ { + "type" : "boolean" + }, { + "type" : "null" + } ] + } + }, { + "in" : "query", + "name" : "with-tables", + "required" : true, + "schema" : { + "default" : false, + "oneOf" : [ { + "type" : "boolean" + }, { + "type" : "null" + } ] + } + }, { + "in" : "query", + "name" : "with-fields", + "required" : true, + "schema" : { + "default" : false, + "oneOf" : [ { + "type" : "boolean" + }, { + "type" : "null" + } ] + } + } ], "responses" : { "2XX" : { "description" : "Successful response", "content" : { "application/json" : { "schema" : { - "type" : "object", - "properties" : { - "body" : { - "type" : "object", - "properties" : { - "run_id" : { - "$ref" : "#/components/schemas/metabase-enterprise.replacement.schema.run-id" - } - }, - "required" : [ "run_id" ], - "additionalProperties" : false - }, - "status" : { - "const" : 202 - } - }, - "required" : [ "status", "body" ] + "$ref" : "#/components/schemas/metabase-enterprise.serialization.schema.export-metadata-response" } } } @@ -26887,54 +30432,14 @@ "description" : "Server error response" } }, - "requestBody" : { - "content" : { - "application/json" : { - "schema" : { - "type" : "object", - "properties" : { - "card_id" : { - "$ref" : "#/components/schemas/metabase-enterprise.replacement.schema.source-entity-id" - }, - "target_collection_id" : { - "oneOf" : [ { - "$ref" : "#/components/schemas/metabase-enterprise.replacement.schema.source-entity-id" - }, { - "type" : "null" - } ] - }, - "transform_name" : { - "type" : "string" - }, - "transform_tag_ids" : { - "oneOf" : [ { - "type" : "array", - "items" : { - "type" : "integer", - "minimum" : 1 - } - }, { - "type" : "null" - } ] - }, - "transform_target" : { - "type" : "object", - "properties" : { } - } - }, - "required" : [ "card_id", "transform_name", "transform_target" ] - } - } - } - }, - "tags" : [ "/api/ee/replacement" ] + "tags" : [ "/api/ee/serialization" ] } }, - "/api/ee/replacement/replace-source" : { + "/api/ee/serialization/metadata/import" : { "post" : { - "operationId" : "post-api-ee-replacement-replace-source", - "summary" : "POST /api/ee/replacement/replace-source", - "description" : "Replace all usages of a source entity with a target entity asynchronously.\n Returns 202 with a run_id for polling. Returns 409 if a replacement is already running.", + "operationId" : "post-api-ee-serialization-metadata-import", + "summary" : "POST /api/ee/serialization/metadata/import", + "description" : "Import warehouse metadata previously emitted by `POST /metadata/export`. The\n request body is the JSON document `{databases, tables, fields}`; sections are\n parsed incrementally so memory stays bounded regardless of payload size.\n\n To bypass the JSON-parsing request middleware, send with `Content-Type:\n application/octet-stream`. Restricted to superusers.\n\n Returns `202` immediately with an `:import-id`; the import runs\n asynchronously. Poll `GET /metadata/import/:id` for its outcome.", "parameters" : [ ], "responses" : { "2XX" : { @@ -26947,11 +30452,14 @@ "body" : { "type" : "object", "properties" : { - "run_id" : { - "$ref" : "#/components/schemas/metabase-enterprise.replacement.schema.run-id" + "import-id" : { + "type" : "string" + }, + "queued" : { + "type" : "boolean" } }, - "required" : [ "run_id" ], + "required" : [ "queued", "import-id" ], "additionalProperties" : false }, "status" : { @@ -26970,49 +30478,23 @@ "description" : "Server error response" } }, - "requestBody" : { - "content" : { - "application/json" : { - "schema" : { - "type" : "object", - "properties" : { - "source_entity_id" : { - "$ref" : "#/components/schemas/metabase-enterprise.replacement.schema.source-entity-id" - }, - "source_entity_type" : { - "$ref" : "#/components/schemas/metabase-enterprise.replacement.schema.source-entity-type" - }, - "target_entity_id" : { - "$ref" : "#/components/schemas/metabase-enterprise.replacement.schema.source-entity-id" - }, - "target_entity_type" : { - "$ref" : "#/components/schemas/metabase-enterprise.replacement.schema.source-entity-type" - } - }, - "required" : [ "source_entity_id", "source_entity_type", "target_entity_id", "target_entity_type" ] - } - } - } - }, - "tags" : [ "/api/ee/replacement" ] + "tags" : [ "/api/ee/serialization" ] } }, - "/api/ee/replacement/runs" : { + "/api/ee/serialization/metadata/import/{id}" : { "get" : { - "operationId" : "get-api-ee-replacement-runs", - "summary" : "GET /api/ee/replacement/runs", - "description" : "List replacement runs, optionally filtered by is-active.", + "operationId" : "get-api-ee-serialization-metadata-import-id", + "summary" : "GET /api/ee/serialization/metadata/import/{id}", + "description" : "Status of a metadata import previously started by `POST /metadata/import`.\n Status is retained in-memory and is not durable across server restarts.\n Restricted to superusers.", "parameters" : [ { - "in" : "query", - "name" : "is-active", - "required" : false, + "in" : "path", + "name" : "id", + "required" : true, "schema" : { - "oneOf" : [ { - "type" : "boolean" - }, { - "type" : "null" - } ] - } + "type" : "string", + "pattern" : "[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}" + }, + "description" : "value must be a valid UUID." } ], "responses" : { "2XX" : { @@ -27020,10 +30502,7 @@ "content" : { "application/json" : { "schema" : { - "type" : "array", - "items" : { - "$ref" : "#/components/schemas/metabase-enterprise.replacement.schema.run" - } + "$ref" : "#/components/schemas/metabase-enterprise.serialization.schema.import-status-response" } } } @@ -27035,32 +30514,68 @@ "description" : "Server error response" } }, - "tags" : [ "/api/ee/replacement" ] + "tags" : [ "/api/ee/serialization" ] } }, - "/api/ee/replacement/runs/{id}" : { + "/api/ee/stale/{id}" : { "get" : { - "operationId" : "get-api-ee-replacement-runs-id", - "summary" : "GET /api/ee/replacement/runs/{id}", - "description" : "Get the status of a source replacement run.", + "operationId" : "get-api-ee-stale-id", + "summary" : "GET /api/ee/stale/{id}", + "description" : "A flexible endpoint that returns stale entities, in the same shape as collections/items, with the following options:\n - `before_date` - only return entities that were last edited before this date (default: 6 months ago)\n - `is_recursive` - if true, return entities from all children of the collection, not just the direct children (default: false)\n - `sort_column` - the column to sort by (default: name)\n - `sort_direction` - the direction to sort by (default: asc)", "parameters" : [ { "in" : "path", "name" : "id", "required" : true, "schema" : { - "$ref" : "#/components/schemas/metabase-enterprise.replacement.schema.run-id" + "anyOf" : [ { + "description" : "value must be an integer greater than zero.", + "type" : "integer", + "minimum" : 1 + }, { + "const" : "root" + } ] + } + }, { + "in" : "query", + "name" : "before_date", + "required" : false, + "schema" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + } + }, { + "in" : "query", + "name" : "is_recursive", + "required" : true, + "schema" : { + "default" : false, + "type" : "boolean" + } + }, { + "in" : "query", + "name" : "sort_column", + "required" : true, + "schema" : { + "default" : "name", + "type" : "string", + "enum" : [ "name", "last_used_at" ] + } + }, { + "in" : "query", + "name" : "sort_direction", + "required" : true, + "schema" : { + "default" : "asc", + "type" : "string", + "enum" : [ "asc", "desc" ] } } ], "responses" : { "2XX" : { - "description" : "Successful response", - "content" : { - "application/json" : { - "schema" : { - "$ref" : "#/components/schemas/metabase-enterprise.replacement.schema.run" - } - } - } + "description" : "Successful response" }, "4XX" : { "description" : "Client error response" @@ -27069,35 +30584,22 @@ "description" : "Server error response" } }, - "tags" : [ "/api/ee/replacement" ] + "tags" : [ "/api/ee/stale" ] } }, - "/api/ee/replacement/runs/{id}/cancel" : { + "/api/ee/support-access-grant" : { "post" : { - "operationId" : "post-api-ee-replacement-runs-id-cancel", - "summary" : "POST /api/ee/replacement/runs/{id}/cancel", - "description" : "Cancel a running source replacement.", - "parameters" : [ { - "in" : "path", - "name" : "id", - "required" : true, - "schema" : { - "$ref" : "#/components/schemas/metabase-enterprise.replacement.schema.run-id" - } - } ], + "operationId" : "post-api-ee-support-access-grant", + "summary" : "POST /api/ee/support-access-grant", + "description" : "Create a new support access grant.\n\n Requires superuser permissions. Only one active grant can exist at a time.", + "parameters" : [ ], "responses" : { "2XX" : { "description" : "Successful response", "content" : { "application/json" : { "schema" : { - "type" : "object", - "properties" : { - "success" : { - "type" : "boolean" - } - }, - "required" : [ "success" ] + "$ref" : "#/components/schemas/metabase-enterprise.support-access-grants.schema.grant-response" } } } @@ -27109,68 +30611,35 @@ "description" : "Server error response" } }, - "tags" : [ "/api/ee/replacement" ] - } - }, - "/api/ee/scim/api_key" : { - "get" : { - "operationId" : "get-api-ee-scim-api_key", - "summary" : "GET /api/ee/scim/api_key", - "description" : "Fetch the SCIM API key if one exists. Does *not* return an unmasked key, since we don't have access\n to that after it is created.", - "parameters" : [ ], - "responses" : { - "2XX" : { - "description" : "Successful response" - }, - "4XX" : { - "description" : "Client error response" - }, - "5XX" : { - "description" : "Server error response" + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/metabase-enterprise.support-access-grants.schema.create-grant-request" + } + } } }, - "tags" : [ "/api/ee/scim" ] + "tags" : [ "/api/ee/support-access-grant" ] }, - "post" : { - "operationId" : "post-api-ee-scim-api_key", - "summary" : "POST /api/ee/scim/api_key", - "description" : "Create a new SCIM API key, or refresh one that already exists. When called for the first time,\n this is equivalent to enabling SCIM.", - "parameters" : [ ], - "responses" : { - "2XX" : { - "description" : "Successful response" - }, - "4XX" : { - "description" : "Client error response" - }, - "5XX" : { - "description" : "Server error response" - } - }, - "tags" : [ "/api/ee/scim" ] - } - }, - "/api/ee/scim/v2/Groups" : { "get" : { - "operationId" : "get-api-ee-scim-v2-Groups", - "summary" : "GET /api/ee/scim/v2/Groups", - "description" : "Fetch a list of groups.", + "operationId" : "get-api-ee-support-access-grant", + "summary" : "GET /api/ee/support-access-grant", + "description" : "List support access grants with optional filtering and pagination.\n\n Requires superuser permissions.\n\n Query parameters:\n - ticket-number: Filter by ticket number\n - user-id: Filter by user who created the grant\n - include-revoked: Include revoked grants (default false)", "parameters" : [ { "in" : "query", - "name" : "startIndex", + "name" : "ticket-number", "required" : false, "schema" : { "oneOf" : [ { - "description" : "value must be an integer greater than zero.", - "type" : "integer", - "minimum" : 1 + "type" : "string" }, { "type" : "null" } ] } }, { "in" : "query", - "name" : "count", + "name" : "user-id", "required" : false, "schema" : { "oneOf" : [ { @@ -27183,12 +30652,11 @@ } }, { "in" : "query", - "name" : "filter", + "name" : "include-revoked", "required" : false, "schema" : { "oneOf" : [ { - "type" : "string", - "minLength" : 1 + "type" : "boolean" }, { "type" : "null" } ] @@ -27196,97 +30664,77 @@ } ], "responses" : { "2XX" : { - "description" : "Successful response" - }, - "4XX" : { - "description" : "Client error response" - }, - "5XX" : { - "description" : "Server error response" - } - }, - "tags" : [ "/api/ee/scim/v2" ] - }, - "post" : { - "operationId" : "post-api-ee-scim-v2-Groups", - "summary" : "POST /api/ee/scim/v2/Groups", - "description" : "Create a single group, and populates it if necessary.", - "parameters" : [ ], - "responses" : { - "2XX" : { - "description" : "Successful response" - }, - "4XX" : { - "description" : "Client error response" - }, - "5XX" : { - "description" : "Server error response" - } - }, - "requestBody" : { - "content" : { - "application/json" : { - "schema" : { - "type" : "object", - "properties" : { - "displayName" : { - "type" : "string", - "minLength" : 1 - }, - "id" : { - "type" : "string", - "minLength" : 1 - }, - "members" : { - "type" : "array", - "items" : { - "type" : "object", - "properties" : { - "$ref" : { - "type" : "string", - "minLength" : 1 - }, - "value" : { - "type" : "string", - "minLength" : 1 - } - }, - "required" : [ "value" ] - } - }, - "schemas" : { - "type" : "array", - "items" : { - "type" : "string", - "minLength" : 1 - } - } - }, - "required" : [ "schemas", "displayName" ] + "description" : "Successful response", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/metabase-enterprise.support-access-grants.schema.list-grants-response" + } } } + }, + "4XX" : { + "description" : "Client error response" + }, + "5XX" : { + "description" : "Server error response" } }, - "tags" : [ "/api/ee/scim/v2" ] + "tags" : [ "/api/ee/support-access-grant" ] } }, - "/api/ee/scim/v2/Groups/{id}" : { + "/api/ee/support-access-grant/current" : { "get" : { - "operationId" : "get-api-ee-scim-v2-Groups-id", - "summary" : "GET /api/ee/scim/v2/Groups/{id}", - "description" : "Fetch a single group.", + "operationId" : "get-api-ee-support-access-grant-current", + "summary" : "GET /api/ee/support-access-grant/current", + "description" : "Get the currently active support access grant, if one exists.\n\n Requires superuser permissions.", + "parameters" : [ ], + "responses" : { + "2XX" : { + "description" : "Successful response", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/metabase-enterprise.support-access-grants.schema.current-grant-response" + } + } + } + }, + "4XX" : { + "description" : "Client error response" + }, + "5XX" : { + "description" : "Server error response" + } + }, + "tags" : [ "/api/ee/support-access-grant" ] + } + }, + "/api/ee/support-access-grant/{id}/revoke" : { + "put" : { + "operationId" : "put-api-ee-support-access-grant-id-revoke", + "summary" : "PUT /api/ee/support-access-grant/{id}/revoke", + "description" : "Revoke an existing support access grant.\n\n Requires superuser permissions. Any admin can revoke any grant.", "parameters" : [ { "in" : "path", "name" : "id", "required" : true, "schema" : { - "type" : "string", - "minLength" : 1 - } + "type" : "integer", + "minimum" : 1 + }, + "description" : "value must be an integer greater than zero." } ], "responses" : { "2XX" : { - "description" : "Successful response" + "description" : "Successful response", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/metabase-enterprise.support-access-grants.schema.grant-response" + } + } + } }, "4XX" : { "description" : "Client error response" @@ -27295,16 +30743,65 @@ "description" : "Server error response" } }, - "tags" : [ "/api/ee/scim/v2" ] - }, - "put" : { - "operationId" : "put-api-ee-scim-v2-Groups-id", - "summary" : "PUT /api/ee/scim/v2/Groups/{id}", - "description" : "Update a group.", + "tags" : [ "/api/ee/support-access-grant" ] + } + }, + "/api/ee/tenant" : { + "post" : { + "operationId" : "post-api-ee-tenant", + "summary" : "POST /api/ee/tenant", + "description" : "Create a new Tenant", "parameters" : [ ], "responses" : { "2XX" : { - "description" : "Successful response" + "description" : "Successful response", + "content" : { + "application/json" : { + "schema" : { + "type" : "object", + "properties" : { + "attributes" : { + "oneOf" : [ { + "type" : "object", + "additionalProperties" : { + "type" : "string" + } + }, { + "type" : "null" + } ] + }, + "id" : { + "description" : "value must be an integer greater than zero.", + "type" : "integer", + "minimum" : 1 + }, + "is_active" : { + "type" : "boolean" + }, + "member_count" : { + "description" : "value must be an integer.", + "type" : "integer" + }, + "name" : { + "type" : "string", + "minLength" : 1 + }, + "slug" : { + "description" : "invalid slug", + "type" : "string", + "pattern" : "^[-_a-z0-9]{1,255}$" + }, + "tenant_collection_id" : { + "description" : "value must be an integer greater than zero.", + "type" : "integer", + "minimum" : 1 + } + }, + "required" : [ "id", "name", "slug", "is_active", "member_count", "attributes", "tenant_collection_id" ], + "additionalProperties" : false + } + } + } }, "4XX" : { "description" : "Client error response" @@ -27319,62 +30816,106 @@ "schema" : { "type" : "object", "properties" : { - "displayName" : { - "type" : "string", - "minLength" : 1 + "attributes" : { + "oneOf" : [ { + "type" : "object", + "additionalProperties" : { } + }, { + "type" : "null" + } ] }, - "id" : { + "name" : { "type" : "string", "minLength" : 1 }, - "members" : { - "type" : "array", - "items" : { - "type" : "object", - "properties" : { - "$ref" : { - "type" : "string", - "minLength" : 1 - }, - "value" : { - "type" : "string", - "minLength" : 1 - } - }, - "required" : [ "value" ] - } - }, - "schemas" : { - "type" : "array", - "items" : { - "type" : "string", - "minLength" : 1 - } + "slug" : { + "description" : "invalid slug", + "type" : "string", + "pattern" : "^[-_a-z0-9]{1,255}$" } }, - "required" : [ "schemas", "displayName" ] + "required" : [ "name", "slug" ], + "additionalProperties" : false } } } }, - "tags" : [ "/api/ee/scim/v2" ] + "tags" : [ "/api/ee/tenant" ] }, - "delete" : { - "operationId" : "delete-api-ee-scim-v2-Groups-id", - "summary" : "DELETE /api/ee/scim/v2/Groups/{id}", - "description" : "Delete a group.", + "get" : { + "operationId" : "get-api-ee-tenant", + "summary" : "GET /api/ee/tenant", + "description" : "Get all tenants", "parameters" : [ { - "in" : "path", - "name" : "id", + "in" : "query", + "name" : "status", "required" : true, "schema" : { + "default" : "all", "type" : "string", - "minLength" : 1 + "enum" : [ "all", "deactivated", "active" ] } } ], "responses" : { "2XX" : { - "description" : "Successful response" + "description" : "Successful response", + "content" : { + "application/json" : { + "schema" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "array", + "items" : { + "type" : "object", + "properties" : { + "attributes" : { + "oneOf" : [ { + "type" : "object", + "additionalProperties" : { + "type" : "string" + } + }, { + "type" : "null" + } ] + }, + "id" : { + "description" : "value must be an integer greater than zero.", + "type" : "integer", + "minimum" : 1 + }, + "is_active" : { + "type" : "boolean" + }, + "member_count" : { + "description" : "value must be an integer.", + "type" : "integer" + }, + "name" : { + "type" : "string", + "minLength" : 1 + }, + "slug" : { + "description" : "invalid slug", + "type" : "string", + "pattern" : "^[-_a-z0-9]{1,255}$" + }, + "tenant_collection_id" : { + "description" : "value must be an integer greater than zero.", + "type" : "integer", + "minimum" : 1 + } + }, + "required" : [ "id", "name", "slug", "is_active", "member_count", "attributes", "tenant_collection_id" ], + "additionalProperties" : false + } + } + }, + "required" : [ "data" ], + "additionalProperties" : false + } + } + } }, "4XX" : { "description" : "Client error response" @@ -27383,74 +30924,74 @@ "description" : "Server error response" } }, - "tags" : [ "/api/ee/scim/v2" ] + "tags" : [ "/api/ee/tenant" ] } }, - "/api/ee/scim/v2/Users" : { - "get" : { - "operationId" : "get-api-ee-scim-v2-Users", - "summary" : "GET /api/ee/scim/v2/Users", - "description" : "Fetch a list of users.", + "/api/ee/tenant/{id}" : { + "put" : { + "operationId" : "put-api-ee-tenant-id", + "summary" : "PUT /api/ee/tenant/{id}", + "description" : "Update a tenant, can set name, attributes, or whether this tenant is active.", "parameters" : [ { - "in" : "query", - "name" : "startIndex", - "required" : false, - "schema" : { - "oneOf" : [ { - "description" : "value must be an integer greater than zero.", - "type" : "integer", - "minimum" : 1 - }, { - "type" : "null" - } ] - } - }, { - "in" : "query", - "name" : "count", - "required" : false, - "schema" : { - "oneOf" : [ { - "description" : "value must be an integer greater than zero.", - "type" : "integer", - "minimum" : 1 - }, { - "type" : "null" - } ] - } - }, { - "in" : "query", - "name" : "filter", - "required" : false, + "in" : "path", + "name" : "id", + "required" : true, "schema" : { - "oneOf" : [ { - "type" : "string", - "minLength" : 1 - }, { - "type" : "null" - } ] - } - } ], - "responses" : { - "2XX" : { - "description" : "Successful response" - }, - "4XX" : { - "description" : "Client error response" + "type" : "integer", + "minimum" : 1 }, - "5XX" : { - "description" : "Server error response" - } - }, - "tags" : [ "/api/ee/scim/v2" ] - }, - "post" : { - "operationId" : "post-api-ee-scim-v2-Users", - "summary" : "POST /api/ee/scim/v2/Users", - "description" : "Create a single user.", - "parameters" : [ ], + "description" : "value must be an integer greater than zero." + } ], "responses" : { "2XX" : { - "description" : "Successful response" + "description" : "Successful response", + "content" : { + "application/json" : { + "schema" : { + "type" : "object", + "properties" : { + "attributes" : { + "oneOf" : [ { + "type" : "object", + "additionalProperties" : { + "type" : "string" + } + }, { + "type" : "null" + } ] + }, + "id" : { + "description" : "value must be an integer greater than zero.", + "type" : "integer", + "minimum" : 1 + }, + "is_active" : { + "type" : "boolean" + }, + "member_count" : { + "description" : "value must be an integer.", + "type" : "integer" + }, + "name" : { + "type" : "string", + "minLength" : 1 + }, + "slug" : { + "description" : "invalid slug", + "type" : "string", + "pattern" : "^[-_a-z0-9]{1,255}$" + }, + "tenant_collection_id" : { + "description" : "value must be an integer greater than zero.", + "type" : "integer", + "minimum" : 1 + } + }, + "required" : [ "id", "name", "slug", "is_active", "member_count", "attributes", "tenant_collection_id" ], + "additionalProperties" : false + } + } + } }, "4XX" : { "description" : "Client error response" @@ -27465,102 +31006,120 @@ "schema" : { "type" : "object", "properties" : { - "active" : { - "type" : "boolean" - }, - "emails" : { - "type" : "array", - "items" : { - "type" : "object", - "properties" : { - "primary" : { - "type" : "boolean" - }, - "type" : { - "type" : "string", - "minLength" : 1 - }, - "value" : { - "type" : "string", - "minLength" : 1 - } - }, - "required" : [ "value" ] - } - }, - "groups" : { - "type" : "array", - "items" : { + "attributes" : { + "oneOf" : [ { "type" : "object", - "properties" : { - "$ref" : { - "type" : "string", - "minLength" : 1 - }, - "display" : { - "type" : "string", - "minLength" : 1 - }, - "value" : { - "type" : "string", - "minLength" : 1 - } - }, - "required" : [ "value", "display" ] - } + "additionalProperties" : { } + }, { + "type" : "null" + } ] }, - "id" : { - "type" : "string", - "minLength" : 1 + "is_active" : { + "oneOf" : [ { + "type" : "boolean" + }, { + "type" : "null" + } ] }, - "locale" : { + "name" : { "oneOf" : [ { "type" : "string", "minLength" : 1 }, { "type" : "null" } ] - }, - "name" : { - "type" : "object", - "properties" : { - "familyName" : { - "type" : "string" - }, - "givenName" : { - "type" : "string" - } + } + }, + "additionalProperties" : false + } + } + } + }, + "tags" : [ "/api/ee/tenant" ] + }, + "get" : { + "operationId" : "get-api-ee-tenant-id", + "summary" : "GET /api/ee/tenant/{id}", + "description" : "Get info about a tenant", + "parameters" : [ { + "in" : "path", + "name" : "id", + "required" : true, + "schema" : { + "type" : "integer", + "minimum" : 1 + }, + "description" : "value must be an integer greater than zero." + } ], + "responses" : { + "2XX" : { + "description" : "Successful response", + "content" : { + "application/json" : { + "schema" : { + "type" : "object", + "properties" : { + "attributes" : { + "oneOf" : [ { + "type" : "object", + "additionalProperties" : { + "type" : "string" + } + }, { + "type" : "null" + } ] }, - "required" : [ "givenName", "familyName" ] - }, - "schemas" : { - "type" : "array", - "items" : { + "id" : { + "description" : "value must be an integer greater than zero.", + "type" : "integer", + "minimum" : 1 + }, + "is_active" : { + "type" : "boolean" + }, + "member_count" : { + "description" : "value must be an integer.", + "type" : "integer" + }, + "name" : { "type" : "string", "minLength" : 1 + }, + "slug" : { + "description" : "invalid slug", + "type" : "string", + "pattern" : "^[-_a-z0-9]{1,255}$" + }, + "tenant_collection_id" : { + "description" : "value must be an integer greater than zero.", + "type" : "integer", + "minimum" : 1 } }, - "userName" : { - "type" : "string", - "minLength" : 1 - } - }, - "required" : [ "schemas", "userName", "name", "emails" ] + "required" : [ "id", "name", "slug", "is_active", "member_count", "attributes", "tenant_collection_id" ], + "additionalProperties" : false + } } } + }, + "4XX" : { + "description" : "Client error response" + }, + "5XX" : { + "description" : "Server error response" } }, - "tags" : [ "/api/ee/scim/v2" ] + "tags" : [ "/api/ee/tenant" ] } }, - "/api/ee/scim/v2/Users/{id}" : { + "/api/ee/transforms-python/library/{path}" : { "get" : { - "operationId" : "get-api-ee-scim-v2-Users-id", - "summary" : "GET /api/ee/scim/v2/Users/{id}", - "description" : "Fetch a single user.", + "operationId" : "get-api-ee-transforms-python-library-path", + "summary" : "GET /api/ee/transforms-python/library/{path}", + "description" : "Get the Python library for user modules.", "parameters" : [ { "in" : "path", - "name" : "id", + "name" : "path", "required" : true, "schema" : { "type" : "string", @@ -27578,13 +31137,21 @@ "description" : "Server error response" } }, - "tags" : [ "/api/ee/scim/v2" ] + "tags" : [ "/api/ee/transforms-python" ] }, "put" : { - "operationId" : "put-api-ee-scim-v2-Users-id", - "summary" : "PUT /api/ee/scim/v2/Users/{id}", - "description" : "Update a user.", - "parameters" : [ ], + "operationId" : "put-api-ee-transforms-python-library-path", + "summary" : "PUT /api/ee/transforms-python/library/{path}", + "description" : "Update the Python library source code for user modules.", + "parameters" : [ { + "in" : "path", + "name" : "path", + "required" : true, + "schema" : { + "type" : "string", + "minLength" : 1 + } + } ], "responses" : { "2XX" : { "description" : "Successful response" @@ -27602,101 +31169,181 @@ "schema" : { "type" : "object", "properties" : { - "active" : { - "type" : "boolean" - }, - "emails" : { - "type" : "array", - "items" : { + "source" : { + "type" : "string" + } + }, + "required" : [ "source" ], + "additionalProperties" : false + } + } + } + }, + "tags" : [ "/api/ee/transforms-python" ] + } + }, + "/api/ee/transforms-python/test-run" : { + "post" : { + "operationId" : "post-api-ee-transforms-python-test-run", + "summary" : "POST /api/ee/transforms-python/test-run", + "description" : "Evaluate an ad-hoc python transform on a sample of input data.\n Intended for short runs for early feedback. Input/output/timeout limits apply.", + "parameters" : [ ], + "responses" : { + "2XX" : { + "description" : "Successful response", + "content" : { + "application/json" : { + "schema" : { + "type" : "object", + "properties" : { + "error" : { "type" : "object", "properties" : { - "primary" : { - "type" : "boolean" - }, - "type" : { - "type" : "string", - "minLength" : 1 - }, - "value" : { - "type" : "string", - "minLength" : 1 + "message" : { + "anyOf" : [ { }, { } ] } }, - "required" : [ "value" ] - } - }, - "groups" : { - "type" : "array", - "items" : { + "required" : [ "message" ] + }, + "logs" : { + "type" : "string" + }, + "output" : { "type" : "object", "properties" : { - "$ref" : { - "type" : "string", - "minLength" : 1 - }, - "display" : { - "type" : "string", - "minLength" : 1 + "cols" : { + "type" : "array", + "items" : { + "type" : "object", + "properties" : { + "name" : { + "type" : "string" + } + }, + "required" : [ "name" ] + } }, - "value" : { - "type" : "string", - "minLength" : 1 + "rows" : { + "type" : "array", + "items" : { } } }, - "required" : [ "value", "display" ] + "required" : [ "cols", "rows" ] } }, - "id" : { - "type" : "string", - "minLength" : 1 + "required" : [ "logs" ] + } + } + } + }, + "4XX" : { + "description" : "Client error response" + }, + "5XX" : { + "description" : "Server error response" + } + }, + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "type" : "object", + "properties" : { + "code" : { + "type" : "string" }, - "locale" : { - "oneOf" : [ { - "type" : "string", - "minLength" : 1 + "output_row_limit" : { + "allOf" : [ { + "type" : "integer" }, { - "type" : "null" + "type" : "number", + "exclusiveMinimum" : 1 + }, { + "type" : "number", + "maximum" : 100 } ] }, - "name" : { - "type" : "object", - "properties" : { - "familyName" : { - "type" : "string" - }, - "givenName" : { - "type" : "string" - } - }, - "required" : [ "givenName", "familyName" ] + "per_input_row_limit" : { + "allOf" : [ { + "type" : "integer" + }, { + "type" : "number", + "exclusiveMinimum" : 1 + }, { + "type" : "number", + "maximum" : 100 + } ] }, - "schemas" : { + "source_tables" : { "type" : "array", "items" : { - "type" : "string", - "minLength" : 1 - } - }, - "userName" : { - "type" : "string", - "minLength" : 1 + "$ref" : "#/components/schemas/metabase.transforms-base.util.source-table-entry" + }, + "minItems" : 1 } }, - "required" : [ "schemas", "userName", "name", "emails" ] + "required" : [ "code", "source_tables" ] } } } }, - "tags" : [ "/api/ee/scim/v2" ] - }, - "patch" : { - "operationId" : "patch-api-ee-scim-v2-Users-id", - "summary" : "PATCH /api/ee/scim/v2/Users/{id}", - "description" : "Activate or deactivate a user. Supports specific replace operations, but not arbitrary patches.", + "tags" : [ "/api/ee/transforms-python" ] + } + }, + "/api/ee/transforms/{id}/inspect" : { + "get" : { + "operationId" : "get-api-ee-transforms-id-inspect", + "summary" : "GET /api/ee/transforms/{id}/inspect", + "description" : "Phase 1: Discover available lenses for a transform.\n Returns structural metadata and available lens types.", + "parameters" : [ { + "in" : "path", + "name" : "id", + "required" : true, + "schema" : { + "type" : "integer", + "minimum" : 1 + }, + "description" : "value must be an integer greater than zero." + } ], + "responses" : { + "2XX" : { + "description" : "Successful response", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/metabase-enterprise.transforms-inspector.schema.discovery-response" + } + } + } + }, + "4XX" : { + "description" : "Client error response" + }, + "5XX" : { + "description" : "Server error response" + } + }, + "tags" : [ "/api/ee/transforms" ] + } + }, + "/api/ee/transforms/{id}/inspect/{lens-id}" : { + "get" : { + "operationId" : "get-api-ee-transforms-id-inspect-lens-id", + "summary" : "GET /api/ee/transforms/{id}/inspect/{lens-id}", + "description" : "Phase 2: Get full lens contents for a transform.\n Returns sections, cards with dataset_query, and trigger definitions.\n Accepts optional params for drill lenses as query params.", "parameters" : [ { "in" : "path", "name" : "id", "required" : true, + "schema" : { + "type" : "integer", + "minimum" : 1 + }, + "description" : "value must be an integer greater than zero." + }, { + "in" : "path", + "name" : "lens-id", + "required" : true, "schema" : { "type" : "string", "minLength" : 1 @@ -27704,7 +31351,58 @@ } ], "responses" : { "2XX" : { - "description" : "Successful response" + "description" : "Successful response", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/metabase-enterprise.transforms-inspector.schema.lens" + } + } + } + }, + "4XX" : { + "description" : "Client error response" + }, + "5XX" : { + "description" : "Server error response" + } + }, + "tags" : [ "/api/ee/transforms" ] + } + }, + "/api/ee/transforms/{id}/inspect/{lens-id}/query" : { + "post" : { + "operationId" : "post-api-ee-transforms-id-inspect-lens-id-query", + "summary" : "POST /api/ee/transforms/{id}/inspect/{lens-id}/query", + "description" : "Execute a query in the context of a transform inspector lens.", + "parameters" : [ { + "in" : "path", + "name" : "id", + "required" : true, + "schema" : { + "type" : "integer", + "minimum" : 1 + }, + "description" : "value must be an integer greater than zero." + }, { + "in" : "path", + "name" : "lens-id", + "required" : true, + "schema" : { + "type" : "string", + "minLength" : 1 + } + } ], + "responses" : { + "2XX" : { + "description" : "Successful response", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/metabase.query-processor.schema.query-result" + } + } + } }, "4XX" : { "description" : "Client error response" @@ -27719,58 +31417,101 @@ "schema" : { "type" : "object", "properties" : { - "Operations" : { - "type" : "array", - "items" : { + "lens_params" : { + "oneOf" : [ { "type" : "object", - "properties" : { - "op" : { - "type" : "string", - "minLength" : 1 - }, - "value" : { - "anyOf" : [ { - "type" : "object", - "additionalProperties" : { - "anyOf" : [ { - "type" : "string", - "minLength" : 1 - }, { - "type" : "boolean" - } ] - } - }, { - "type" : "string", - "minLength" : 1 - }, { - "type" : "boolean" - } ] - } - }, - "required" : [ "op", "value" ] - } + "additionalProperties" : { } + }, { + "type" : "null" + } ] }, - "schemas" : { - "type" : "array", - "items" : { - "type" : "string", - "minLength" : 1 + "query" : { + "type" : "object", + "properties" : { + "database" : { + "oneOf" : [ { + "type" : "integer" + }, { + "type" : "null" + } ] + } } } }, - "required" : [ "schemas", "Operations" ] + "required" : [ "query" ] } } } }, - "tags" : [ "/api/ee/scim/v2" ] + "tags" : [ "/api/ee/transforms" ] } }, - "/api/ee/security-center" : { + "/api/ee/upload-management/tables" : { "get" : { - "operationId" : "get-api-ee-security-center", - "summary" : "GET /api/ee/security-center", - "description" : "List all security advisories with match status.", + "operationId" : "get-api-ee-upload-management-tables", + "summary" : "GET /api/ee/upload-management/tables", + "description" : "Get all `Tables` visible to the current user which were created by uploading a file.", + "parameters" : [ ], + "responses" : { + "2XX" : { + "description" : "Successful response" + }, + "4XX" : { + "description" : "Client error response" + }, + "5XX" : { + "description" : "Server error response" + } + }, + "tags" : [ "/api/ee/upload-management" ] + } + }, + "/api/ee/upload-management/tables/{id}" : { + "delete" : { + "operationId" : "delete-api-ee-upload-management-tables-id", + "summary" : "DELETE /api/ee/upload-management/tables/{id}", + "description" : "Delete the uploaded table from the database, optionally archiving cards for which it is the primary source.", + "parameters" : [ { + "in" : "path", + "name" : "id", + "required" : true, + "schema" : { + "type" : "integer", + "minimum" : 1 + }, + "description" : "value must be an integer greater than zero." + }, { + "in" : "query", + "name" : "archive-cards", + "required" : false, + "schema" : { + "default" : false, + "oneOf" : [ { + "type" : "boolean" + }, { + "type" : "null" + } ] + } + } ], + "responses" : { + "2XX" : { + "description" : "Successful response" + }, + "4XX" : { + "description" : "Client error response" + }, + "5XX" : { + "description" : "Server error response" + } + }, + "tags" : [ "/api/ee/upload-management" ] + } + }, + "/api/ee/workspace-instance/current" : { + "get" : { + "operationId" : "get-api-ee-workspace-instance-current", + "summary" : "GET /api/ee/workspace-instance/current", + "description" : "Read-only summary of the workspace loaded on this instance, wrapped in a\n `{:data ...}` envelope.\n\n Reads from the `instance-workspace` setting populated at boot by the `:workspace`\n section of `config.yml`, or at runtime by `POST /current`. `:data` is `null`\n when no workspace was loaded — i.e. this is a manager-only instance, or no\n `config.yml` was present at boot and `POST /current` hasn't been called.\n The envelope avoids an empty JSON body for the `nil` case.", "parameters" : [ ], "responses" : { "2XX" : { @@ -27780,100 +31521,56 @@ "schema" : { "type" : "object", "properties" : { - "advisories" : { - "type" : "array", - "items" : { + "data" : { + "oneOf" : [ { "type" : "object", "properties" : { - "published_at" : { - "type" : "string", - "format" : "date-time" - }, - "advisory_url" : { - "oneOf" : [ { - "type" : "string", - "minLength" : 1 - }, { - "type" : "null" - } ] - }, - "last_evaluated_at" : { - "oneOf" : [ { - "type" : "string", - "format" : "date-time" - }, { - "type" : "null" - } ] - }, - "match_status" : { - "$ref" : "#/components/schemas/metabase-enterprise.security-center.schema.match-status" - }, - "acknowledged_by" : { - "oneOf" : [ { + "databases" : { + "type" : "object", + "additionalProperties" : { "type" : "object", "properties" : { - "common_name" : { - "type" : "string", - "minLength" : 1 - }, - "email" : { - "description" : "value must be a valid email address.", - "type" : "string" + "input_schemas" : { + "type" : "array", + "items" : { + "type" : "string" + } }, - "id" : { - "description" : "value must be an integer greater than zero.", - "type" : "integer", - "minimum" : 1 + "output" : { + "type" : "object", + "properties" : { + "db" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "schema" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + } + } } }, - "required" : [ "id", "common_name", "email" ] - }, { - "type" : "null" - } ] - }, - "title" : { - "type" : "string", - "minLength" : 1 - }, - "affected_versions" : { - "$ref" : "#/components/schemas/metabase-enterprise.security-center.schema.affected-versions" - }, - "remediation" : { - "type" : "string", - "minLength" : 1 - }, - "advisory_id" : { - "$ref" : "#/components/schemas/metabase-enterprise.security-center.schema.advisory-id" - }, - "severity" : { - "$ref" : "#/components/schemas/metabase-enterprise.security-center.schema.severity" + "required" : [ "input_schemas", "output" ] + } }, - "description" : { + "name" : { "type" : "string", - "minLength" : 1 - }, - "acknowledged_at" : { - "oneOf" : [ { - "type" : "string", - "format" : "date-time" - }, { - "type" : "null" - } ] - } - }, - "required" : [ "advisory_id", "title", "severity", "description", "advisory_url", "remediation", "published_at", "match_status", "last_evaluated_at", "acknowledged_by", "acknowledged_at", "affected_versions" ] - } - }, - "last_checked_at" : { - "oneOf" : [ { - "type" : "string", - "format" : "date-time" + "minLength" : 1 + } + }, + "required" : [ "name", "databases" ] }, { "type" : "null" } ] } }, - "required" : [ "last_checked_at", "advisories" ] + "required" : [ "data" ] } } } @@ -27885,14 +31582,12 @@ "description" : "Server error response" } }, - "tags" : [ "/api/ee/security-center" ] - } - }, - "/api/ee/security-center/acknowledge" : { + "tags" : [ "/api/ee/workspace-instance" ] + }, "post" : { - "operationId" : "post-api-ee-security-center-acknowledge", - "summary" : "POST /api/ee/security-center/acknowledge", - "description" : "Acknowledge multiple security advisories. Skips already-acknowledged advisories.", + "operationId" : "post-api-ee-workspace-instance-current", + "summary" : "POST /api/ee/workspace-instance/current", + "description" : "Install a workspace config on this instance at runtime. Accepts the same shape\n `GET /current` returns and persists it via the `instance-workspace` setting so\n it survives restarts. Use this on a running instance to enter workspace mode\n without restarting from `config.yml`.", "parameters" : [ ], "responses" : { "2XX" : { @@ -27900,50 +31595,48 @@ "content" : { "application/json" : { "schema" : { - "type" : "array", - "items" : { - "type" : "object", - "properties" : { - "acknowledged_at" : { - "oneOf" : [ { - "type" : "string", - "format" : "date-time" - }, { - "type" : "null" - } ] - }, - "acknowledged_by" : { - "oneOf" : [ { - "type" : "object", - "properties" : { - "common_name" : { - "type" : "string", - "minLength" : 1 - }, - "email" : { - "description" : "value must be a valid email address.", + "type" : "object", + "properties" : { + "databases" : { + "type" : "object", + "additionalProperties" : { + "type" : "object", + "properties" : { + "input_schemas" : { + "type" : "array", + "items" : { "type" : "string" - }, - "id" : { - "description" : "value must be an integer greater than zero.", - "type" : "integer", - "minimum" : 1 } }, - "required" : [ "id", "common_name", "email" ] - }, { - "type" : "null" - } ] - }, - "advisory_id" : { - "$ref" : "#/components/schemas/metabase-enterprise.security-center.schema.advisory-id" - }, - "match_status" : { - "$ref" : "#/components/schemas/metabase-enterprise.security-center.schema.match-status" + "output" : { + "type" : "object", + "properties" : { + "db" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "schema" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + } + } + } + }, + "required" : [ "input_schemas", "output" ] } }, - "required" : [ "advisory_id", "match_status", "acknowledged_by", "acknowledged_at" ] - } + "name" : { + "type" : "string", + "minLength" : 1 + } + }, + "required" : [ "name", "databases" ] } } } @@ -27959,29 +31652,17 @@ "content" : { "application/json" : { "schema" : { - "type" : "object", - "properties" : { - "advisory_ids" : { - "type" : "array", - "items" : { - "type" : "string", - "minLength" : 1 - } - } - }, - "required" : [ "advisory_ids" ] + "$ref" : "#/components/schemas/metabase.workspaces.core.workspace-instance-config" } } } }, - "tags" : [ "/api/ee/security-center" ] - } - }, - "/api/ee/security-center/sync" : { - "post" : { - "operationId" : "post-api-ee-security-center-sync", - "summary" : "POST /api/ee/security-center/sync", - "description" : "Trigger an async advisory sync + re-evaluation.\n Returns immediately. If a sync is already running, the request is a no-op.", + "tags" : [ "/api/ee/workspace-instance" ] + }, + "delete" : { + "operationId" : "delete-api-ee-workspace-instance-current", + "summary" : "DELETE /api/ee/workspace-instance/current", + "description" : "Clear the workspace config on this instance. After this returns, the instance\n is no longer in workspace mode and `GET /current` returns `nil`. Also drops\n every `TableRemapping` row, since stale mappings from the prior workspace\n would otherwise keep rewriting queries on the now-unmanaged databases.", "parameters" : [ ], "responses" : { "2XX" : { @@ -27989,14 +31670,7 @@ "content" : { "application/json" : { "schema" : { - "type" : "object", - "properties" : { - "status" : { - "type" : "string", - "minLength" : 1 - } - }, - "required" : [ "status" ] + "type" : "null" } } } @@ -28008,14 +31682,14 @@ "description" : "Server error response" } }, - "tags" : [ "/api/ee/security-center" ] + "tags" : [ "/api/ee/workspace-instance" ] } }, - "/api/ee/security-center/test-notification" : { - "post" : { - "operationId" : "post-api-ee-security-center-test-notification", - "summary" : "POST /api/ee/security-center/test-notification", - "description" : "Send a test notification through the configured Security Center channels.", + "/api/ee/workspace-instance/table-remappings" : { + "get" : { + "operationId" : "get-api-ee-workspace-instance-table-remappings", + "summary" : "GET /api/ee/workspace-instance/table-remappings", + "description" : "Return all table remappings, ordered by id.", "parameters" : [ ], "responses" : { "2XX" : { @@ -28023,13 +31697,58 @@ "content" : { "application/json" : { "schema" : { - "type" : "object", - "properties" : { - "success" : { - "type" : "boolean" - } - }, - "required" : [ "success" ] + "type" : "array", + "items" : { + "type" : "object", + "properties" : { + "from_db" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "to_table_name" : { + "type" : "string", + "minLength" : 1 + }, + "id" : { + "description" : "value must be an integer greater than zero.", + "type" : "integer", + "minimum" : 1 + }, + "database_id" : { + "$ref" : "#/components/schemas/metabase.lib.schema.id.database" + }, + "to_db" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "created_at" : { }, + "from_schema" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "from_table_name" : { + "type" : "string", + "minLength" : 1 + }, + "to_schema" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + } + }, + "required" : [ "id", "database_id", "from_db", "from_schema", "from_table_name", "to_db", "to_schema", "to_table_name", "created_at" ] + } } } } @@ -28041,23 +31760,130 @@ "description" : "Server error response" } }, - "tags" : [ "/api/ee/security-center" ] + "tags" : [ "/api/ee/workspace-instance" ] } }, - "/api/ee/security-center/{advisory-id}/acknowledge" : { - "post" : { - "operationId" : "post-api-ee-security-center-advisory-id-acknowledge", - "summary" : "POST /api/ee/security-center/{advisory-id}/acknowledge", - "description" : "Acknowledge a security advisory. Stops repeat notifications.", - "parameters" : [ { - "in" : "path", - "name" : "advisory-id", - "required" : true, - "schema" : { - "type" : "string", - "minLength" : 1 + "/api/ee/workspace-manager" : { + "get" : { + "operationId" : "get-api-ee-workspace-manager", + "summary" : "GET /api/ee/workspace-manager", + "description" : "List all Workspaces.", + "parameters" : [ ], + "responses" : { + "2XX" : { + "description" : "Successful response", + "content" : { + "application/json" : { + "schema" : { + "type" : "array", + "items" : { + "type" : "object", + "properties" : { + "created_at" : { + "anyOf" : [ { }, { } ] + }, + "creator" : { + "oneOf" : [ { + "type" : "object", + "properties" : { + "common_name" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "email" : { + "type" : "string", + "minLength" : 1 + }, + "first_name" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "id" : { + "description" : "value must be an integer greater than zero.", + "type" : "integer", + "minimum" : 1 + }, + "last_name" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + } + }, + "required" : [ "id", "first_name", "last_name", "email" ], + "additionalProperties" : false + }, { + "type" : "null" + } ] + }, + "databases" : { + "type" : "array", + "items" : { + "type" : "object", + "properties" : { + "database_id" : { + "$ref" : "#/components/schemas/metabase.lib.schema.id.database" + }, + "input_schemas" : { + "type" : "array", + "items" : { + "type" : "string", + "minLength" : 1 + } + }, + "output_namespace" : { + "type" : "string" + }, + "status" : { + "type" : "string", + "enum" : [ "unprovisioned", "provisioning", "provisioned", "deprovisioning" ] + } + }, + "required" : [ "database_id", "input_schemas", "output_namespace", "status" ], + "additionalProperties" : false + } + }, + "id" : { + "description" : "value must be an integer greater than zero.", + "type" : "integer", + "minimum" : 1 + }, + "name" : { + "type" : "string", + "minLength" : 1 + }, + "updated_at" : { + "anyOf" : [ { }, { } ] + } + }, + "required" : [ "id", "name", "creator", "created_at", "updated_at" ], + "additionalProperties" : false + } + } + } + } + }, + "4XX" : { + "description" : "Client error response" + }, + "5XX" : { + "description" : "Server error response" } - } ], + }, + "tags" : [ "/api/ee/workspace-manager" ] + }, + "post" : { + "operationId" : "post-api-ee-workspace-manager", + "summary" : "POST /api/ee/workspace-manager", + "description" : "Create a new Workspace (name only, no databases).", + "parameters" : [ ], "responses" : { "2XX" : { "description" : "Successful response", @@ -28066,225 +31892,95 @@ "schema" : { "type" : "object", "properties" : { - "acknowledged_at" : { - "oneOf" : [ { - "type" : "string", - "format" : "date-time" - }, { - "type" : "null" - } ] + "created_at" : { + "anyOf" : [ { }, { } ] }, - "acknowledged_by" : { + "creator" : { "oneOf" : [ { "type" : "object", "properties" : { "common_name" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "email" : { "type" : "string", "minLength" : 1 }, - "email" : { - "description" : "value must be a valid email address.", - "type" : "string" + "first_name" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] }, "id" : { "description" : "value must be an integer greater than zero.", "type" : "integer", "minimum" : 1 + }, + "last_name" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] } }, - "required" : [ "id", "common_name", "email" ] + "required" : [ "id", "first_name", "last_name", "email" ], + "additionalProperties" : false }, { "type" : "null" } ] }, - "advisory_id" : { - "$ref" : "#/components/schemas/metabase-enterprise.security-center.schema.advisory-id" - }, - "match_status" : { - "$ref" : "#/components/schemas/metabase-enterprise.security-center.schema.match-status" - } - }, - "required" : [ "advisory_id", "match_status", "acknowledged_by", "acknowledged_at" ] - } - } - } - }, - "4XX" : { - "description" : "Client error response" - }, - "5XX" : { - "description" : "Server error response" - } - }, - "tags" : [ "/api/ee/security-center" ] - } - }, - "/api/ee/semantic-search/status" : { - "get" : { - "operationId" : "get-api-ee-semantic-search-status", - "summary" : "GET /api/ee/semantic-search/status", - "description" : "Fetch the indexing status of the currently active semantic search index table.\n\n Returns a map with keys:\n :indexed_count \n :total_est \n\n If no index is active, returns an empty map.", - "parameters" : [ ], - "responses" : { - "2XX" : { - "description" : "Successful response" - }, - "4XX" : { - "description" : "Client error response" - }, - "5XX" : { - "description" : "Server error response" - } - }, - "tags" : [ "/api/ee/semantic-search" ] - } - }, - "/api/ee/serialization/export" : { - "post" : { - "operationId" : "post-api-ee-serialization-export", - "summary" : "POST /api/ee/serialization/export", - "description" : "Serialize and retrieve Metabase instance.\n\n Outputs `.tar.gz` file with serialization results and an `export.log` file.\n On error outputs serialization logs directly.", - "parameters" : [ { - "in" : "query", - "name" : "dirname", - "required" : false, - "schema" : { - "oneOf" : [ { - "type" : "string" - }, { - "type" : "null" - } ] - }, - "description" : "name of directory and archive file (default: `-`)" - }, { - "in" : "query", - "name" : "collection", - "required" : false, - "schema" : { - "oneOf" : [ { - "type" : "array", - "items" : { - "anyOf" : [ { - "description" : "value must be an integer greater than zero.", - "type" : "integer", - "minimum" : 1 - }, { - "type" : "string", - "pattern" : "^.{21}$" - }, { - "type" : "string", - "pattern" : "^eid:.{21}$" - } ] - } - }, { - "type" : "null" - } ] - }, - "description" : "collections' db ids/entity-ids to serialize" - }, { - "in" : "query", - "name" : "all_collections", - "required" : true, - "schema" : { - "default" : true, - "type" : "boolean" - } - }, { - "in" : "query", - "name" : "settings", - "required" : true, - "schema" : { - "default" : true, - "type" : "boolean" - } - }, { - "in" : "query", - "name" : "data_model", - "required" : true, - "schema" : { - "default" : true, - "type" : "boolean" - } - }, { - "in" : "query", - "name" : "field_values", - "required" : true, - "schema" : { - "default" : false, - "type" : "boolean" - } - }, { - "in" : "query", - "name" : "database_secrets", - "required" : true, - "schema" : { - "default" : false, - "type" : "boolean" - } - }, { - "in" : "query", - "name" : "continue_on_error", - "required" : true, - "schema" : { - "default" : false, - "type" : "boolean" - } - }, { - "in" : "query", - "name" : "full_stacktrace", - "required" : true, - "schema" : { - "default" : false, - "type" : "boolean" - } - } ], - "responses" : { - "2XX" : { - "description" : "Successful response" - }, - "4XX" : { - "description" : "Client error response" - }, - "5XX" : { - "description" : "Server error response" - } - }, - "tags" : [ "/api/ee/serialization" ] - } - }, - "/api/ee/serialization/import" : { - "post" : { - "operationId" : "post-api-ee-serialization-import", - "summary" : "POST /api/ee/serialization/import", - "description" : "Deserialize Metabase instance from an archive generated by /export.\n\n Parameters:\n - `file`: archive encoded as `multipart/form-data` (required).\n\n Returns logs of deserialization.", - "parameters" : [ { - "in" : "query", - "name" : "continue_on_error", - "required" : true, - "schema" : { - "default" : false, - "type" : "boolean" - } - }, { - "in" : "query", - "name" : "full_stacktrace", - "required" : true, - "schema" : { - "default" : false, - "type" : "boolean" - } - }, { - "in" : "query", - "name" : "reindex", - "required" : true, - "schema" : { - "default" : true, - "type" : "boolean" - } - } ], - "responses" : { - "2XX" : { - "description" : "Successful response" + "databases" : { + "type" : "array", + "items" : { + "type" : "object", + "properties" : { + "database_id" : { + "$ref" : "#/components/schemas/metabase.lib.schema.id.database" + }, + "input_schemas" : { + "type" : "array", + "items" : { + "type" : "string", + "minLength" : 1 + } + }, + "output_namespace" : { + "type" : "string" + }, + "status" : { + "type" : "string", + "enum" : [ "unprovisioned", "provisioning", "provisioned", "deprovisioning" ] + } + }, + "required" : [ "database_id", "input_schemas", "output_namespace", "status" ], + "additionalProperties" : false + } + }, + "id" : { + "description" : "value must be an integer greater than zero.", + "type" : "integer", + "minimum" : 1 + }, + "name" : { + "type" : "string", + "minLength" : 1 + }, + "updated_at" : { + "anyOf" : [ { }, { } ] + } + }, + "required" : [ "id", "name", "creator", "created_at", "updated_at" ], + "additionalProperties" : false + } + } + } }, "4XX" : { "description" : "Client error response" @@ -28295,96 +31991,136 @@ }, "requestBody" : { "content" : { - "multipart/form-data" : { + "application/json" : { "schema" : { "type" : "object", "properties" : { - "file" : { - "description" : ".tgz with serialization data", - "type" : "object", - "properties" : { - "content-type" : { - "type" : "string" - }, - "filename" : { - "type" : "string" - }, - "size" : { - "type" : "integer" - }, - "tempfile" : { } - }, - "required" : [ "content-type", "filename", "size", "tempfile" ], - "additionalProperties" : false + "name" : { + "type" : "string", + "minLength" : 1 } }, - "required" : [ "file" ] + "required" : [ "name" ], + "additionalProperties" : false } } } }, - "tags" : [ "/api/ee/serialization" ] + "tags" : [ "/api/ee/workspace-manager" ] } }, - "/api/ee/stale/{id}" : { + "/api/ee/workspace-manager/{id}" : { "get" : { - "operationId" : "get-api-ee-stale-id", - "summary" : "GET /api/ee/stale/{id}", - "description" : "A flexible endpoint that returns stale entities, in the same shape as collections/items, with the following options:\n - `before_date` - only return entities that were last edited before this date (default: 6 months ago)\n - `is_recursive` - if true, return entities from all children of the collection, not just the direct children (default: false)\n - `sort_column` - the column to sort by (default: name)\n - `sort_direction` - the direction to sort by (default: asc)", + "operationId" : "get-api-ee-workspace-manager-id", + "summary" : "GET /api/ee/workspace-manager/{id}", + "description" : "Get a single Workspace by id.", "parameters" : [ { "in" : "path", "name" : "id", "required" : true, "schema" : { - "anyOf" : [ { - "description" : "value must be an integer greater than zero.", - "type" : "integer", - "minimum" : 1 - }, { - "const" : "root" - } ] - } - }, { - "in" : "query", - "name" : "before_date", - "required" : false, - "schema" : { - "oneOf" : [ { - "type" : "string" - }, { - "type" : "null" - } ] - } - }, { - "in" : "query", - "name" : "is_recursive", - "required" : true, - "schema" : { - "default" : false, - "type" : "boolean" - } - }, { - "in" : "query", - "name" : "sort_column", - "required" : true, - "schema" : { - "default" : "name", - "type" : "string", - "enum" : [ "name", "last_used_at" ] - } - }, { - "in" : "query", - "name" : "sort_direction", - "required" : true, - "schema" : { - "default" : "asc", - "type" : "string", - "enum" : [ "asc", "desc" ] - } + "type" : "integer", + "minimum" : 1 + }, + "description" : "value must be an integer greater than zero." } ], "responses" : { "2XX" : { - "description" : "Successful response" + "description" : "Successful response", + "content" : { + "application/json" : { + "schema" : { + "type" : "object", + "properties" : { + "created_at" : { + "anyOf" : [ { }, { } ] + }, + "creator" : { + "oneOf" : [ { + "type" : "object", + "properties" : { + "common_name" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "email" : { + "type" : "string", + "minLength" : 1 + }, + "first_name" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "id" : { + "description" : "value must be an integer greater than zero.", + "type" : "integer", + "minimum" : 1 + }, + "last_name" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + } + }, + "required" : [ "id", "first_name", "last_name", "email" ], + "additionalProperties" : false + }, { + "type" : "null" + } ] + }, + "databases" : { + "type" : "array", + "items" : { + "type" : "object", + "properties" : { + "database_id" : { + "$ref" : "#/components/schemas/metabase.lib.schema.id.database" + }, + "input_schemas" : { + "type" : "array", + "items" : { + "type" : "string", + "minLength" : 1 + } + }, + "output_namespace" : { + "type" : "string" + }, + "status" : { + "type" : "string", + "enum" : [ "unprovisioned", "provisioning", "provisioned", "deprovisioning" ] + } + }, + "required" : [ "database_id", "input_schemas", "output_namespace", "status" ], + "additionalProperties" : false + } + }, + "id" : { + "description" : "value must be an integer greater than zero.", + "type" : "integer", + "minimum" : 1 + }, + "name" : { + "type" : "string", + "minLength" : 1 + }, + "updated_at" : { + "anyOf" : [ { }, { } ] + } + }, + "required" : [ "id", "name", "creator", "created_at", "updated_at" ], + "additionalProperties" : false + } + } + } }, "4XX" : { "description" : "Client error response" @@ -28393,22 +32129,116 @@ "description" : "Server error response" } }, - "tags" : [ "/api/ee/stale" ] - } - }, - "/api/ee/support-access-grant" : { - "post" : { - "operationId" : "post-api-ee-support-access-grant", - "summary" : "POST /api/ee/support-access-grant", - "description" : "Create a new support access grant.\n\n Requires superuser permissions. Only one active grant can exist at a time.", - "parameters" : [ ], + "tags" : [ "/api/ee/workspace-manager" ] + }, + "put" : { + "operationId" : "put-api-ee-workspace-manager-id", + "summary" : "PUT /api/ee/workspace-manager/{id}", + "description" : "Update a workspace's name.", + "parameters" : [ { + "in" : "path", + "name" : "id", + "required" : true, + "schema" : { + "type" : "integer", + "minimum" : 1 + }, + "description" : "value must be an integer greater than zero." + } ], "responses" : { "2XX" : { "description" : "Successful response", "content" : { "application/json" : { "schema" : { - "$ref" : "#/components/schemas/metabase-enterprise.support-access-grants.schema.grant-response" + "type" : "object", + "properties" : { + "created_at" : { + "anyOf" : [ { }, { } ] + }, + "creator" : { + "oneOf" : [ { + "type" : "object", + "properties" : { + "common_name" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "email" : { + "type" : "string", + "minLength" : 1 + }, + "first_name" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "id" : { + "description" : "value must be an integer greater than zero.", + "type" : "integer", + "minimum" : 1 + }, + "last_name" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + } + }, + "required" : [ "id", "first_name", "last_name", "email" ], + "additionalProperties" : false + }, { + "type" : "null" + } ] + }, + "databases" : { + "type" : "array", + "items" : { + "type" : "object", + "properties" : { + "database_id" : { + "$ref" : "#/components/schemas/metabase.lib.schema.id.database" + }, + "input_schemas" : { + "type" : "array", + "items" : { + "type" : "string", + "minLength" : 1 + } + }, + "output_namespace" : { + "type" : "string" + }, + "status" : { + "type" : "string", + "enum" : [ "unprovisioned", "provisioning", "provisioned", "deprovisioning" ] + } + }, + "required" : [ "database_id", "input_schemas", "output_namespace", "status" ], + "additionalProperties" : false + } + }, + "id" : { + "description" : "value must be an integer greater than zero.", + "type" : "integer", + "minimum" : 1 + }, + "name" : { + "type" : "string", + "minLength" : 1 + }, + "updated_at" : { + "anyOf" : [ { }, { } ] + } + }, + "required" : [ "id", "name", "creator", "created_at", "updated_at" ], + "additionalProperties" : false } } } @@ -28424,52 +32254,33 @@ "content" : { "application/json" : { "schema" : { - "$ref" : "#/components/schemas/metabase-enterprise.support-access-grants.schema.create-grant-request" + "type" : "object", + "properties" : { + "name" : { + "type" : "string", + "minLength" : 1 + } + }, + "additionalProperties" : false } } } }, - "tags" : [ "/api/ee/support-access-grant" ] + "tags" : [ "/api/ee/workspace-manager" ] }, - "get" : { - "operationId" : "get-api-ee-support-access-grant", - "summary" : "GET /api/ee/support-access-grant", - "description" : "List support access grants with optional filtering and pagination.\n\n Requires superuser permissions.\n\n Query parameters:\n - ticket-number: Filter by ticket number\n - user-id: Filter by user who created the grant\n - include-revoked: Include revoked grants (default false)", + "delete" : { + "operationId" : "delete-api-ee-workspace-manager-id", + "summary" : "DELETE /api/ee/workspace-manager/{id}", + "description" : "Delete a Workspace. Deprovisions all databases first (blocking).", "parameters" : [ { - "in" : "query", - "name" : "ticket-number", - "required" : false, - "schema" : { - "oneOf" : [ { - "type" : "string" - }, { - "type" : "null" - } ] - } - }, { - "in" : "query", - "name" : "user-id", - "required" : false, - "schema" : { - "oneOf" : [ { - "description" : "value must be an integer greater than zero.", - "type" : "integer", - "minimum" : 1 - }, { - "type" : "null" - } ] - } - }, { - "in" : "query", - "name" : "include-revoked", - "required" : false, + "in" : "path", + "name" : "id", + "required" : true, "schema" : { - "oneOf" : [ { - "type" : "boolean" - }, { - "type" : "null" - } ] - } + "type" : "integer", + "minimum" : 1 + }, + "description" : "value must be an integer greater than zero." } ], "responses" : { "2XX" : { @@ -28477,7 +32288,18 @@ "content" : { "application/json" : { "schema" : { - "$ref" : "#/components/schemas/metabase-enterprise.support-access-grants.schema.list-grants-response" + "type" : "object", + "properties" : { + "deleted" : { + "type" : "boolean" + }, + "id" : { + "description" : "value must be an integer greater than zero.", + "type" : "integer", + "minimum" : 1 + } + }, + "required" : [ "id", "deleted" ] } } } @@ -28489,22 +32311,46 @@ "description" : "Server error response" } }, - "tags" : [ "/api/ee/support-access-grant" ] + "tags" : [ "/api/ee/workspace-manager" ] } }, - "/api/ee/support-access-grant/current" : { + "/api/ee/workspace-manager/{id}/config" : { "get" : { - "operationId" : "get-api-ee-support-access-grant-current", - "summary" : "GET /api/ee/support-access-grant/current", - "description" : "Get the currently active support access grant, if one exists.\n\n Requires superuser permissions.", - "parameters" : [ ], + "operationId" : "get-api-ee-workspace-manager-id-config", + "summary" : "GET /api/ee/workspace-manager/{id}/config", + "description" : "Download the workspace's developer-instance config as a YAML file. 409 if any\n of the workspace's databases is not `:provisioned`.", + "parameters" : [ { + "in" : "path", + "name" : "id", + "required" : true, + "schema" : { + "type" : "integer", + "minimum" : 1 + }, + "description" : "value must be an integer greater than zero." + } ], "responses" : { "2XX" : { "description" : "Successful response", "content" : { "application/json" : { "schema" : { - "$ref" : "#/components/schemas/metabase-enterprise.support-access-grants.schema.current-grant-response" + "type" : "object", + "properties" : { + "body" : { + "type" : "string" + }, + "headers" : { + "type" : "object", + "additionalProperties" : { + "type" : "string" + } + }, + "status" : { + "const" : 200 + } + }, + "required" : [ "status", "headers", "body" ] } } } @@ -28516,14 +32362,14 @@ "description" : "Server error response" } }, - "tags" : [ "/api/ee/support-access-grant" ] + "tags" : [ "/api/ee/workspace-manager" ] } }, - "/api/ee/support-access-grant/{id}/revoke" : { - "put" : { - "operationId" : "put-api-ee-support-access-grant-id-revoke", - "summary" : "PUT /api/ee/support-access-grant/{id}/revoke", - "description" : "Revoke an existing support access grant.\n\n Requires superuser permissions. Any admin can revoke any grant.", + "/api/ee/workspace-manager/{id}/database" : { + "post" : { + "operationId" : "post-api-ee-workspace-manager-id-database", + "summary" : "POST /api/ee/workspace-manager/{id}/database", + "description" : "Add a database to a workspace and provision it immediately (blocking).", "parameters" : [ { "in" : "path", "name" : "id", @@ -28540,7 +32386,94 @@ "content" : { "application/json" : { "schema" : { - "$ref" : "#/components/schemas/metabase-enterprise.support-access-grants.schema.grant-response" + "type" : "object", + "properties" : { + "created_at" : { + "anyOf" : [ { }, { } ] + }, + "creator" : { + "oneOf" : [ { + "type" : "object", + "properties" : { + "common_name" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "email" : { + "type" : "string", + "minLength" : 1 + }, + "first_name" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "id" : { + "description" : "value must be an integer greater than zero.", + "type" : "integer", + "minimum" : 1 + }, + "last_name" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + } + }, + "required" : [ "id", "first_name", "last_name", "email" ], + "additionalProperties" : false + }, { + "type" : "null" + } ] + }, + "databases" : { + "type" : "array", + "items" : { + "type" : "object", + "properties" : { + "database_id" : { + "$ref" : "#/components/schemas/metabase.lib.schema.id.database" + }, + "input_schemas" : { + "type" : "array", + "items" : { + "type" : "string", + "minLength" : 1 + } + }, + "output_namespace" : { + "type" : "string" + }, + "status" : { + "type" : "string", + "enum" : [ "unprovisioned", "provisioning", "provisioned", "deprovisioning" ] + } + }, + "required" : [ "database_id", "input_schemas", "output_namespace", "status" ], + "additionalProperties" : false + } + }, + "id" : { + "description" : "value must be an integer greater than zero.", + "type" : "integer", + "minimum" : 1 + }, + "name" : { + "type" : "string", + "minLength" : 1 + }, + "updated_at" : { + "anyOf" : [ { }, { } ] + } + }, + "required" : [ "id", "name", "creator", "created_at", "updated_at" ], + "additionalProperties" : false } } } @@ -28548,19 +32481,60 @@ "4XX" : { "description" : "Client error response" }, - "5XX" : { - "description" : "Server error response" - } - }, - "tags" : [ "/api/ee/support-access-grant" ] - } - }, - "/api/ee/tenant" : { - "post" : { - "operationId" : "post-api-ee-tenant", - "summary" : "POST /api/ee/tenant", - "description" : "Create a new Tenant", - "parameters" : [ ], + "5XX" : { + "description" : "Server error response" + } + }, + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "type" : "object", + "properties" : { + "database_id" : { + "$ref" : "#/components/schemas/metabase.lib.schema.id.database" + }, + "input_schemas" : { + "type" : "array", + "items" : { + "type" : "string", + "minLength" : 1 + } + } + }, + "required" : [ "database_id", "input_schemas" ], + "additionalProperties" : false + } + } + } + }, + "tags" : [ "/api/ee/workspace-manager" ] + } + }, + "/api/ee/workspace-manager/{id}/database/{db-id}" : { + "put" : { + "operationId" : "put-api-ee-workspace-manager-id-database-db-id", + "summary" : "PUT /api/ee/workspace-manager/{id}/database/{db-id}", + "description" : "Update a database's input namespaces. Deprovisions the old config and reprovisions\n with the new one (blocking).", + "parameters" : [ { + "in" : "path", + "name" : "id", + "required" : true, + "schema" : { + "type" : "integer", + "minimum" : 1 + }, + "description" : "value must be an integer greater than zero." + }, { + "in" : "path", + "name" : "db-id", + "required" : true, + "schema" : { + "type" : "integer", + "minimum" : 1 + }, + "description" : "value must be an integer greater than zero." + } ], "responses" : { "2XX" : { "description" : "Successful response", @@ -28569,44 +32543,91 @@ "schema" : { "type" : "object", "properties" : { - "attributes" : { + "created_at" : { + "anyOf" : [ { }, { } ] + }, + "creator" : { "oneOf" : [ { "type" : "object", - "additionalProperties" : { - "type" : "string" - } + "properties" : { + "common_name" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "email" : { + "type" : "string", + "minLength" : 1 + }, + "first_name" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "id" : { + "description" : "value must be an integer greater than zero.", + "type" : "integer", + "minimum" : 1 + }, + "last_name" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + } + }, + "required" : [ "id", "first_name", "last_name", "email" ], + "additionalProperties" : false }, { "type" : "null" } ] }, + "databases" : { + "type" : "array", + "items" : { + "type" : "object", + "properties" : { + "database_id" : { + "$ref" : "#/components/schemas/metabase.lib.schema.id.database" + }, + "input_schemas" : { + "type" : "array", + "items" : { + "type" : "string", + "minLength" : 1 + } + }, + "output_namespace" : { + "type" : "string" + }, + "status" : { + "type" : "string", + "enum" : [ "unprovisioned", "provisioning", "provisioned", "deprovisioning" ] + } + }, + "required" : [ "database_id", "input_schemas", "output_namespace", "status" ], + "additionalProperties" : false + } + }, "id" : { "description" : "value must be an integer greater than zero.", "type" : "integer", "minimum" : 1 }, - "is_active" : { - "type" : "boolean" - }, - "member_count" : { - "description" : "value must be an integer.", - "type" : "integer" - }, "name" : { "type" : "string", "minLength" : 1 }, - "slug" : { - "description" : "invalid slug", - "type" : "string", - "pattern" : "^[-_a-z0-9]{1,255}$" - }, - "tenant_collection_id" : { - "description" : "value must be an integer greater than zero.", - "type" : "integer", - "minimum" : 1 + "updated_at" : { + "anyOf" : [ { }, { } ] } }, - "required" : [ "id", "name", "slug", "is_active", "member_count", "attributes", "tenant_collection_id" ], + "required" : [ "id", "name", "creator", "created_at", "updated_at" ], "additionalProperties" : false } } @@ -28625,45 +32646,44 @@ "schema" : { "type" : "object", "properties" : { - "attributes" : { - "oneOf" : [ { - "type" : "object", - "additionalProperties" : { } - }, { - "type" : "null" - } ] - }, - "name" : { - "type" : "string", - "minLength" : 1 - }, - "slug" : { - "description" : "invalid slug", - "type" : "string", - "pattern" : "^[-_a-z0-9]{1,255}$" + "input_schemas" : { + "type" : "array", + "items" : { + "type" : "string", + "minLength" : 1 + } } }, - "required" : [ "name", "slug" ], + "required" : [ "input_schemas" ], "additionalProperties" : false } } } }, - "tags" : [ "/api/ee/tenant" ] + "tags" : [ "/api/ee/workspace-manager" ] }, - "get" : { - "operationId" : "get-api-ee-tenant", - "summary" : "GET /api/ee/tenant", - "description" : "Get all tenants", + "delete" : { + "operationId" : "delete-api-ee-workspace-manager-id-database-db-id", + "summary" : "DELETE /api/ee/workspace-manager/{id}/database/{db-id}", + "description" : "Deprovision and remove a database from a workspace (blocking).", "parameters" : [ { - "in" : "query", - "name" : "status", + "in" : "path", + "name" : "id", "required" : true, "schema" : { - "default" : "all", - "type" : "string", - "enum" : [ "all", "deactivated", "active" ] - } + "type" : "integer", + "minimum" : 1 + }, + "description" : "value must be an integer greater than zero." + }, { + "in" : "path", + "name" : "db-id", + "required" : true, + "schema" : { + "type" : "integer", + "minimum" : 1 + }, + "description" : "value must be an integer greater than zero." } ], "responses" : { "2XX" : { @@ -28673,17 +32693,27 @@ "schema" : { "type" : "object", "properties" : { - "data" : { - "type" : "array", - "items" : { + "created_at" : { + "anyOf" : [ { }, { } ] + }, + "creator" : { + "oneOf" : [ { "type" : "object", "properties" : { - "attributes" : { + "common_name" : { "oneOf" : [ { - "type" : "object", - "additionalProperties" : { - "type" : "string" - } + "type" : "string" + }, { + "type" : "null" + } ] + }, + "email" : { + "type" : "string", + "minLength" : 1 + }, + "first_name" : { + "oneOf" : [ { + "type" : "string" }, { "type" : "null" } ] @@ -28693,34 +32723,61 @@ "type" : "integer", "minimum" : 1 }, - "is_active" : { - "type" : "boolean" + "last_name" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + } + }, + "required" : [ "id", "first_name", "last_name", "email" ], + "additionalProperties" : false + }, { + "type" : "null" + } ] + }, + "databases" : { + "type" : "array", + "items" : { + "type" : "object", + "properties" : { + "database_id" : { + "$ref" : "#/components/schemas/metabase.lib.schema.id.database" }, - "member_count" : { - "description" : "value must be an integer.", - "type" : "integer" + "input_schemas" : { + "type" : "array", + "items" : { + "type" : "string", + "minLength" : 1 + } }, - "name" : { - "type" : "string", - "minLength" : 1 + "output_namespace" : { + "type" : "string" }, - "slug" : { - "description" : "invalid slug", + "status" : { "type" : "string", - "pattern" : "^[-_a-z0-9]{1,255}$" - }, - "tenant_collection_id" : { - "description" : "value must be an integer greater than zero.", - "type" : "integer", - "minimum" : 1 + "enum" : [ "unprovisioned", "provisioning", "provisioned", "deprovisioning" ] } }, - "required" : [ "id", "name", "slug", "is_active", "member_count", "attributes", "tenant_collection_id" ], + "required" : [ "database_id", "input_schemas", "output_namespace", "status" ], "additionalProperties" : false } + }, + "id" : { + "description" : "value must be an integer greater than zero.", + "type" : "integer", + "minimum" : 1 + }, + "name" : { + "type" : "string", + "minLength" : 1 + }, + "updated_at" : { + "anyOf" : [ { }, { } ] } }, - "required" : [ "data" ], + "required" : [ "id", "name", "creator", "created_at", "updated_at" ], "additionalProperties" : false } } @@ -28733,14 +32790,14 @@ "description" : "Server error response" } }, - "tags" : [ "/api/ee/tenant" ] + "tags" : [ "/api/ee/workspace-manager" ] } }, - "/api/ee/tenant/{id}" : { - "put" : { - "operationId" : "put-api-ee-tenant-id", - "summary" : "PUT /api/ee/tenant/{id}", - "description" : "Update a tenant, can set name, attributes, or whether this tenant is active.", + "/api/ee/workspace-manager/{id}/metadata/export" : { + "get" : { + "operationId" : "get-api-ee-workspace-manager-id-metadata-export", + "summary" : "GET /api/ee/workspace-manager/{id}/metadata/export", + "description" : "Stream the warehouse metadata (databases, tables, fields) for the workspace's databases,\n scoped to each database's `:input` namespaces. Same flag semantics as\n `/api/ee/serialization/metadata/export` — sections must be opted into via the\n `with-databases` / `with-tables` / `with-fields` query parameters.", "parameters" : [ { "in" : "path", "name" : "id", @@ -28750,6 +32807,42 @@ "minimum" : 1 }, "description" : "value must be an integer greater than zero." + }, { + "in" : "query", + "name" : "with-databases", + "required" : true, + "schema" : { + "default" : false, + "oneOf" : [ { + "type" : "boolean" + }, { + "type" : "null" + } ] + } + }, { + "in" : "query", + "name" : "with-tables", + "required" : true, + "schema" : { + "default" : false, + "oneOf" : [ { + "type" : "boolean" + }, { + "type" : "null" + } ] + } + }, { + "in" : "query", + "name" : "with-fields", + "required" : true, + "schema" : { + "default" : false, + "oneOf" : [ { + "type" : "boolean" + }, { + "type" : "null" + } ] + } } ], "responses" : { "2XX" : { @@ -28757,47 +32850,7 @@ "content" : { "application/json" : { "schema" : { - "type" : "object", - "properties" : { - "attributes" : { - "oneOf" : [ { - "type" : "object", - "additionalProperties" : { - "type" : "string" - } - }, { - "type" : "null" - } ] - }, - "id" : { - "description" : "value must be an integer greater than zero.", - "type" : "integer", - "minimum" : 1 - }, - "is_active" : { - "type" : "boolean" - }, - "member_count" : { - "description" : "value must be an integer.", - "type" : "integer" - }, - "name" : { - "type" : "string", - "minLength" : 1 - }, - "slug" : { - "description" : "invalid slug", - "type" : "string", - "pattern" : "^[-_a-z0-9]{1,255}$" - }, - "tenant_collection_id" : { - "description" : "value must be an integer greater than zero.", - "type" : "integer", - "minimum" : 1 - } - }, - "required" : [ "id", "name", "slug", "is_active", "member_count", "attributes", "tenant_collection_id" ], - "additionalProperties" : false + "$ref" : "#/components/schemas/metabase-enterprise.serialization.schema.export-metadata-response" } } } @@ -28809,107 +32862,118 @@ "description" : "Server error response" } }, + "tags" : [ "/api/ee/workspace-manager" ] + } + }, + "/api/eid-translation/translate" : { + "post" : { + "operationId" : "post-api-eid-translation-translate", + "summary" : "POST /api/eid-translation/translate", + "description" : "Translate entity IDs to model IDs.", + "parameters" : [ ], + "responses" : { + "2XX" : { + "description" : "Successful response" + }, + "4XX" : { + "description" : "Client error response" + }, + "5XX" : { + "description" : "Server error response" + } + }, + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "type" : "object", + "properties" : { + "entity_ids" : { + "type" : "object", + "properties" : { } + } + }, + "required" : [ "entity_ids" ] + } + } + } + }, + "tags" : [ "/api/eid-translation" ] + } + }, + "/api/email" : { + "put" : { + "operationId" : "put-api-email", + "summary" : "PUT /api/email", + "description" : "Update multiple email Settings. You must be a superuser or have `setting` permission to do this.", + "parameters" : [ ], + "responses" : { + "2XX" : { + "description" : "Successful response" + }, + "4XX" : { + "description" : "Client error response" + }, + "5XX" : { + "description" : "Server error response" + } + }, "requestBody" : { "content" : { "application/json" : { "schema" : { "type" : "object", "properties" : { - "attributes" : { - "oneOf" : [ { - "type" : "object", - "additionalProperties" : { } + "email-smtp-host" : { + "anyOf" : [ { + "type" : "string" }, { "type" : "null" } ] }, - "is_active" : { - "oneOf" : [ { - "type" : "boolean" + "email-smtp-password" : { + "anyOf" : [ { + "type" : "string" }, { "type" : "null" } ] }, - "name" : { - "oneOf" : [ { - "type" : "string", - "minLength" : 1 + "email-smtp-port" : { + "anyOf" : [ { + "type" : "integer" + }, { + "type" : "null" + } ] + }, + "email-smtp-security" : { + "anyOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "email-smtp-username" : { + "anyOf" : [ { + "type" : "string" }, { "type" : "null" } ] } - }, - "additionalProperties" : false + } } } } }, - "tags" : [ "/api/ee/tenant" ] + "tags" : [ "/api/email" ] }, - "get" : { - "operationId" : "get-api-ee-tenant-id", - "summary" : "GET /api/ee/tenant/{id}", - "description" : "Get info about a tenant", - "parameters" : [ { - "in" : "path", - "name" : "id", - "required" : true, - "schema" : { - "type" : "integer", - "minimum" : 1 - }, - "description" : "value must be an integer greater than zero." - } ], + "delete" : { + "operationId" : "delete-api-email", + "summary" : "DELETE /api/email", + "description" : "Clear all email related settings. You must be a superuser or have `setting` permission to do this.", + "parameters" : [ ], "responses" : { "2XX" : { - "description" : "Successful response", - "content" : { - "application/json" : { - "schema" : { - "type" : "object", - "properties" : { - "attributes" : { - "oneOf" : [ { - "type" : "object", - "additionalProperties" : { - "type" : "string" - } - }, { - "type" : "null" - } ] - }, - "id" : { - "description" : "value must be an integer greater than zero.", - "type" : "integer", - "minimum" : 1 - }, - "is_active" : { - "type" : "boolean" - }, - "member_count" : { - "description" : "value must be an integer.", - "type" : "integer" - }, - "name" : { - "type" : "string", - "minLength" : 1 - }, - "slug" : { - "description" : "invalid slug", - "type" : "string", - "pattern" : "^[-_a-z0-9]{1,255}$" - }, - "tenant_collection_id" : { - "description" : "value must be an integer greater than zero.", - "type" : "integer", - "minimum" : 1 - } - }, - "required" : [ "id", "name", "slug", "is_active", "member_count", "attributes", "tenant_collection_id" ], - "additionalProperties" : false - } - } - } + "description" : "Successful response" }, "4XX" : { "description" : "Client error response" @@ -28918,23 +32982,15 @@ "description" : "Server error response" } }, - "tags" : [ "/api/ee/tenant" ] + "tags" : [ "/api/email" ] } }, - "/api/ee/transforms-python/library/{path}" : { - "get" : { - "operationId" : "get-api-ee-transforms-python-library-path", - "summary" : "GET /api/ee/transforms-python/library/{path}", - "description" : "Get the Python library for user modules.", - "parameters" : [ { - "in" : "path", - "name" : "path", - "required" : true, - "schema" : { - "type" : "string", - "minLength" : 1 - } - } ], + "/api/email/test" : { + "post" : { + "operationId" : "post-api-email-test", + "summary" : "POST /api/email/test", + "description" : "Send a test email using the SMTP Settings. You must be a superuser or have `setting` permission to do this.\n Returns `{:ok true}` if we were able to send the message successfully, otherwise a standard 400 error response.", + "parameters" : [ ], "responses" : { "2XX" : { "description" : "Successful response" @@ -28946,21 +33002,15 @@ "description" : "Server error response" } }, - "tags" : [ "/api/ee/transforms-python" ] - }, - "put" : { - "operationId" : "put-api-ee-transforms-python-library-path", - "summary" : "PUT /api/ee/transforms-python/library/{path}", - "description" : "Update the Python library source code for user modules.", - "parameters" : [ { - "in" : "path", - "name" : "path", - "required" : true, - "schema" : { - "type" : "string", - "minLength" : 1 - } - } ], + "tags" : [ "/api/email" ] + } + }, + "/api/embed-mcp/drills" : { + "post" : { + "operationId" : "post-api-embed-mcp-drills", + "summary" : "POST /api/embed-mcp/drills", + "description" : "Stash a base64-encoded MBQL query for the iframe's pending drill-through and\n return a handle UUID the iframe will thread into the agent message so the\n `render_drill_through` tool can fetch it.", + "parameters" : [ ], "responses" : { "2XX" : { "description" : "Successful response" @@ -28978,24 +33028,24 @@ "schema" : { "type" : "object", "properties" : { - "source" : { - "type" : "string" + "encodedQuery" : { + "type" : "string", + "minLength" : 1 } }, - "required" : [ "source" ], - "additionalProperties" : false + "required" : [ "encodedQuery" ] } } } }, - "tags" : [ "/api/ee/transforms-python" ] + "tags" : [ "/api/embed-mcp" ] } }, - "/api/ee/transforms-python/test-run" : { + "/api/embed-mcp/feedback" : { "post" : { - "operationId" : "post-api-ee-transforms-python-test-run", - "summary" : "POST /api/ee/transforms-python/test-run", - "description" : "Evaluate an ad-hoc python transform on a sample of input data.\n Intended for short runs for early feedback. Input/output/timeout limits apply.", + "operationId" : "post-api-embed-mcp-feedback", + "summary" : "POST /api/embed-mcp/feedback", + "description" : "Proxy MCP Apps visualization feedback to Harbormaster.", "parameters" : [ ], "responses" : { "2XX" : { @@ -29005,42 +33055,14 @@ "schema" : { "type" : "object", "properties" : { - "error" : { - "type" : "object", - "properties" : { - "message" : { - "anyOf" : [ { }, { } ] - } - }, - "required" : [ "message" ] - }, - "logs" : { - "type" : "string" + "body" : { + "type" : "null" }, - "output" : { - "type" : "object", - "properties" : { - "cols" : { - "type" : "array", - "items" : { - "type" : "object", - "properties" : { - "name" : { - "type" : "string" - } - }, - "required" : [ "name" ] - } - }, - "rows" : { - "type" : "array", - "items" : { } - } - }, - "required" : [ "cols", "rows" ] + "status" : { + "const" : 204 } }, - "required" : [ "logs" ] + "required" : [ "status", "body" ] } } } @@ -29058,69 +33080,84 @@ "schema" : { "type" : "object", "properties" : { - "code" : { - "type" : "string" - }, - "output_row_limit" : { - "allOf" : [ { - "type" : "integer" - }, { - "type" : "number", - "exclusiveMinimum" : 1 - }, { - "type" : "number", - "maximum" : 100 - } ] - }, - "per_input_row_limit" : { - "allOf" : [ { - "type" : "integer" - }, { - "type" : "number", - "exclusiveMinimum" : 1 - }, { - "type" : "number", - "maximum" : 100 - } ] + "conversation_data" : { + "type" : "object", + "properties" : { + "prompt" : { + "oneOf" : [ { + "type" : "string", + "maxLength" : 10000 + }, { + "type" : "null" + } ] + }, + "query" : { + "oneOf" : [ { + "type" : "string", + "maxLength" : 10000 + }, { + "type" : "null" + } ] + }, + "source" : { + "const" : "mcp" + } + }, + "required" : [ "source" ] }, - "source_tables" : { - "type" : "array", - "items" : { - "$ref" : "#/components/schemas/metabase.transforms-base.util.source-table-entry" + "feedback" : { + "type" : "object", + "properties" : { + "freeform_feedback" : { + "oneOf" : [ { + "type" : "string", + "maxLength" : 10000 + }, { + "type" : "null" + } ] + }, + "issue_type" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "message_id" : { + "type" : "string", + "minLength" : 1 + }, + "positive" : { + "type" : "boolean" + } }, - "minItems" : 1 + "required" : [ "message_id", "positive" ] } }, - "required" : [ "code", "source_tables" ] + "required" : [ "feedback", "conversation_data" ] } } } }, - "tags" : [ "/api/ee/transforms-python" ] + "tags" : [ "/api/embed-mcp" ] } }, - "/api/ee/transforms/{id}/inspect" : { + "/api/embed-theme" : { "get" : { - "operationId" : "get-api-ee-transforms-id-inspect", - "summary" : "GET /api/ee/transforms/{id}/inspect", - "description" : "Phase 1: Discover available lenses for a transform.\n Returns structural metadata and available lens types.", - "parameters" : [ { - "in" : "path", - "name" : "id", - "required" : true, - "schema" : { - "type" : "integer", - "minimum" : 1 - }, - "description" : "value must be an integer greater than zero." - } ], + "operationId" : "get-api-embed-theme", + "summary" : "GET /api/embed-theme", + "description" : "Fetch a list of all embedding themes.", + "parameters" : [ ], "responses" : { "2XX" : { "description" : "Successful response", "content" : { "application/json" : { "schema" : { - "$ref" : "#/components/schemas/metabase-enterprise.transforms-inspector.schema.discovery-response" + "type" : "array", + "items" : { + "$ref" : "#/components/schemas/metabase.embedding-rest.api.theme.EmbeddingTheme" + } } } } @@ -29132,39 +33169,20 @@ "description" : "Server error response" } }, - "tags" : [ "/api/ee/transforms" ] - } - }, - "/api/ee/transforms/{id}/inspect/{lens-id}" : { - "get" : { - "operationId" : "get-api-ee-transforms-id-inspect-lens-id", - "summary" : "GET /api/ee/transforms/{id}/inspect/{lens-id}", - "description" : "Phase 2: Get full lens contents for a transform.\n Returns sections, cards with dataset_query, and trigger definitions.\n Accepts optional params for drill lenses as query params.", - "parameters" : [ { - "in" : "path", - "name" : "id", - "required" : true, - "schema" : { - "type" : "integer", - "minimum" : 1 - }, - "description" : "value must be an integer greater than zero." - }, { - "in" : "path", - "name" : "lens-id", - "required" : true, - "schema" : { - "type" : "string", - "minLength" : 1 - } - } ], + "tags" : [ "/api/embed-theme" ] + }, + "post" : { + "operationId" : "post-api-embed-theme", + "summary" : "POST /api/embed-theme", + "description" : "Create a new embedding theme.", + "parameters" : [ ], "responses" : { "2XX" : { "description" : "Successful response", "content" : { "application/json" : { "schema" : { - "$ref" : "#/components/schemas/metabase-enterprise.transforms-inspector.schema.lens" + "$ref" : "#/components/schemas/metabase.embedding-rest.api.theme.EmbeddingTheme" } } } @@ -29176,39 +33194,42 @@ "description" : "Server error response" } }, - "tags" : [ "/api/ee/transforms" ] + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "type" : "object", + "properties" : { + "name" : { + "type" : "string", + "minLength" : 1 + }, + "settings" : { + "type" : "object", + "properties" : { } + } + }, + "required" : [ "name", "settings" ] + } + } + } + }, + "tags" : [ "/api/embed-theme" ] } }, - "/api/ee/transforms/{id}/inspect/{lens-id}/query" : { + "/api/embed-theme/seed-defaults" : { "post" : { - "operationId" : "post-api-ee-transforms-id-inspect-lens-id-query", - "summary" : "POST /api/ee/transforms/{id}/inspect/{lens-id}/query", - "description" : "Execute a query in the context of a transform inspector lens.", - "parameters" : [ { - "in" : "path", - "name" : "id", - "required" : true, - "schema" : { - "type" : "integer", - "minimum" : 1 - }, - "description" : "value must be an integer greater than zero." - }, { - "in" : "path", - "name" : "lens-id", - "required" : true, - "schema" : { - "type" : "string", - "minLength" : 1 - } - } ], + "operationId" : "post-api-embed-theme-seed-defaults", + "summary" : "POST /api/embed-theme/seed-defaults", + "description" : "Seed default embedding themes on first call, using the payloads built by the frontend from the\n `METABASE_LIGHT_THEME` / `METABASE_DARK_THEME` constants.\n\n Idempotent: guarded by the `default-embedding-themes-seeded` setting. Once flipped, subsequent calls\n are no-ops even if the admin has since deleted the seeded themes, so deletions are preserved.", + "parameters" : [ ], "responses" : { "2XX" : { "description" : "Successful response", "content" : { "application/json" : { "schema" : { - "$ref" : "#/components/schemas/metabase.query-processor.schema.query-result" + "type" : "null" } } } @@ -29226,60 +33247,37 @@ "schema" : { "type" : "object", "properties" : { - "lens_params" : { - "oneOf" : [ { + "themes" : { + "type" : "array", + "items" : { "type" : "object", - "additionalProperties" : { } - }, { - "type" : "null" - } ] - }, - "query" : { - "type" : "object", - "properties" : { - "database" : { - "oneOf" : [ { - "type" : "integer" - }, { - "type" : "null" - } ] - } + "properties" : { + "name" : { + "type" : "string", + "minLength" : 1 + }, + "settings" : { + "type" : "object", + "properties" : { } + } + }, + "required" : [ "name", "settings" ] } } }, - "required" : [ "query" ] + "required" : [ "themes" ] } } } }, - "tags" : [ "/api/ee/transforms" ] + "tags" : [ "/api/embed-theme" ] } }, - "/api/ee/upload-management/tables" : { + "/api/embed-theme/{id}" : { "get" : { - "operationId" : "get-api-ee-upload-management-tables", - "summary" : "GET /api/ee/upload-management/tables", - "description" : "Get all `Tables` visible to the current user which were created by uploading a file.", - "parameters" : [ ], - "responses" : { - "2XX" : { - "description" : "Successful response" - }, - "4XX" : { - "description" : "Client error response" - }, - "5XX" : { - "description" : "Server error response" - } - }, - "tags" : [ "/api/ee/upload-management" ] - } - }, - "/api/ee/upload-management/tables/{id}" : { - "delete" : { - "operationId" : "delete-api-ee-upload-management-tables-id", - "summary" : "DELETE /api/ee/upload-management/tables/{id}", - "description" : "Delete the uploaded table from the database, optionally archiving cards for which it is the primary source.", + "operationId" : "get-api-embed-theme-id", + "summary" : "GET /api/embed-theme/{id}", + "description" : "Fetch a single embedding theme by ID.", "parameters" : [ { "in" : "path", "name" : "id", @@ -29289,22 +33287,17 @@ "minimum" : 1 }, "description" : "value must be an integer greater than zero." - }, { - "in" : "query", - "name" : "archive-cards", - "required" : false, - "schema" : { - "default" : false, - "oneOf" : [ { - "type" : "boolean" - }, { - "type" : "null" - } ] - } } ], "responses" : { "2XX" : { - "description" : "Successful response" + "description" : "Successful response", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/metabase.embedding-rest.api.theme.EmbeddingTheme" + } + } + } }, "4XX" : { "description" : "Client error response" @@ -29313,54 +33306,32 @@ "description" : "Server error response" } }, - "tags" : [ "/api/ee/upload-management" ] - } - }, - "/api/eid-translation/translate" : { - "post" : { - "operationId" : "post-api-eid-translation-translate", - "summary" : "POST /api/eid-translation/translate", - "description" : "Translate entity IDs to model IDs.", - "parameters" : [ ], + "tags" : [ "/api/embed-theme" ] + }, + "put" : { + "operationId" : "put-api-embed-theme-id", + "summary" : "PUT /api/embed-theme/{id}", + "description" : "Update an embedding theme.", + "parameters" : [ { + "in" : "path", + "name" : "id", + "required" : true, + "schema" : { + "type" : "integer", + "minimum" : 1 + }, + "description" : "value must be an integer greater than zero." + } ], "responses" : { "2XX" : { - "description" : "Successful response" - }, - "4XX" : { - "description" : "Client error response" - }, - "5XX" : { - "description" : "Server error response" - } - }, - "requestBody" : { - "content" : { - "application/json" : { - "schema" : { - "type" : "object", - "properties" : { - "entity_ids" : { - "type" : "object", - "properties" : { } - } - }, - "required" : [ "entity_ids" ] + "description" : "Successful response", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/metabase.embedding-rest.api.theme.EmbeddingTheme" + } } } - } - }, - "tags" : [ "/api/eid-translation" ] - } - }, - "/api/email" : { - "put" : { - "operationId" : "put-api-email", - "summary" : "PUT /api/email", - "description" : "Update multiple email Settings. You must be a superuser or have `setting` permission to do this.", - "parameters" : [ ], - "responses" : { - "2XX" : { - "description" : "Successful response" }, "4XX" : { "description" : "Client error response" @@ -29375,37 +33346,18 @@ "schema" : { "type" : "object", "properties" : { - "email-smtp-host" : { - "anyOf" : [ { - "type" : "string" - }, { - "type" : "null" - } ] - }, - "email-smtp-password" : { - "anyOf" : [ { - "type" : "string" - }, { - "type" : "null" - } ] - }, - "email-smtp-port" : { - "anyOf" : [ { - "type" : "integer" - }, { - "type" : "null" - } ] - }, - "email-smtp-security" : { - "anyOf" : [ { - "type" : "string" + "name" : { + "oneOf" : [ { + "type" : "string", + "minLength" : 1 }, { "type" : "null" } ] }, - "email-smtp-username" : { - "anyOf" : [ { - "type" : "string" + "settings" : { + "oneOf" : [ { + "type" : "object", + "properties" : { } }, { "type" : "null" } ] @@ -29415,16 +33367,32 @@ } } }, - "tags" : [ "/api/email" ] + "tags" : [ "/api/embed-theme" ] }, "delete" : { - "operationId" : "delete-api-email", - "summary" : "DELETE /api/email", - "description" : "Clear all email related settings. You must be a superuser or have `setting` permission to do this.", - "parameters" : [ ], + "operationId" : "delete-api-embed-theme-id", + "summary" : "DELETE /api/embed-theme/{id}", + "description" : "Delete an embedding theme.", + "parameters" : [ { + "in" : "path", + "name" : "id", + "required" : true, + "schema" : { + "type" : "integer", + "minimum" : 1 + }, + "description" : "value must be an integer greater than zero." + } ], "responses" : { "2XX" : { - "description" : "Successful response" + "description" : "Successful response", + "content" : { + "application/json" : { + "schema" : { + "type" : "null" + } + } + } }, "4XX" : { "description" : "Client error response" @@ -29433,18 +33401,34 @@ "description" : "Server error response" } }, - "tags" : [ "/api/email" ] + "tags" : [ "/api/embed-theme" ] } }, - "/api/email/test" : { + "/api/embed-theme/{id}/copy" : { "post" : { - "operationId" : "post-api-email-test", - "summary" : "POST /api/email/test", - "description" : "Send a test email using the SMTP Settings. You must be a superuser or have `setting` permission to do this.\n Returns `{:ok true}` if we were able to send the message successfully, otherwise a standard 400 error response.", - "parameters" : [ ], + "operationId" : "post-api-embed-theme-id-copy", + "summary" : "POST /api/embed-theme/{id}/copy", + "description" : "Copy an embedding theme.", + "parameters" : [ { + "in" : "path", + "name" : "id", + "required" : true, + "schema" : { + "type" : "integer", + "minimum" : 1 + }, + "description" : "value must be an integer greater than zero." + } ], "responses" : { "2XX" : { - "description" : "Successful response" + "description" : "Successful response", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/metabase.embedding-rest.api.theme.EmbeddingTheme" + } + } + } }, "4XX" : { "description" : "Client error response" @@ -29453,7 +33437,7 @@ "description" : "Server error response" } }, - "tags" : [ "/api/email" ] + "tags" : [ "/api/embed-theme" ] } }, "/api/embed/card/{token}" : { @@ -30078,86 +34062,124 @@ "tags" : [ "/api/embed" ] } }, - "/api/embed/tiles/dashboard/{token}/dashcard/{dashcard-id}/card/{card-id}/{zoom}/{x}/{y}" : { - "get" : { - "operationId" : "get-api-embed-tiles-dashboard-token-dashcard-dashcard-id-card-card-id-zoom-x-y", - "summary" : "GET /api/embed/tiles/dashboard/{token}/dashcard/{dashcard-id}/card/{card-id}/{zoom}/{x}/{y}", - "description" : "Generates a single tile image for a Card on an embedded Dashboard using the map visualization.", - "parameters" : [ { - "in" : "path", - "name" : "token", - "required" : true, - "schema" : { - "type" : "string" - } - }, { - "in" : "path", - "name" : "dashcard-id", - "required" : true, - "schema" : { - "type" : "integer", - "minimum" : 1 - }, - "description" : "value must be an integer greater than zero." - }, { - "in" : "path", - "name" : "card-id", - "required" : true, - "schema" : { - "type" : "integer", - "minimum" : 1 - }, - "description" : "value must be an integer greater than zero." - }, { - "in" : "path", - "name" : "zoom", - "required" : true, - "schema" : { - "type" : "integer" - }, - "description" : "value must be an integer." - }, { - "in" : "path", - "name" : "x", - "required" : true, - "schema" : { - "type" : "integer" - }, - "description" : "value must be an integer." - }, { - "in" : "path", - "name" : "y", - "required" : true, - "schema" : { - "type" : "integer" - }, - "description" : "value must be an integer." - }, { - "in" : "query", - "name" : "parameters", - "required" : false, - "schema" : { - "type" : "string" - }, - "description" : "value must be a valid JSON string." - }, { - "in" : "query", - "name" : "latField", - "required" : true, - "schema" : { - "type" : "string" - } - }, { - "in" : "query", - "name" : "lonField", - "required" : true, - "schema" : { - "type" : "string" - } - } ], + "/api/embed/tiles/dashboard/{token}/dashcard/{dashcard-id}/card/{card-id}/{zoom}/{x}/{y}" : { + "get" : { + "operationId" : "get-api-embed-tiles-dashboard-token-dashcard-dashcard-id-card-card-id-zoom-x-y", + "summary" : "GET /api/embed/tiles/dashboard/{token}/dashcard/{dashcard-id}/card/{card-id}/{zoom}/{x}/{y}", + "description" : "Generates a single tile image for a Card on an embedded Dashboard using the map visualization.", + "parameters" : [ { + "in" : "path", + "name" : "token", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "in" : "path", + "name" : "dashcard-id", + "required" : true, + "schema" : { + "type" : "integer", + "minimum" : 1 + }, + "description" : "value must be an integer greater than zero." + }, { + "in" : "path", + "name" : "card-id", + "required" : true, + "schema" : { + "type" : "integer", + "minimum" : 1 + }, + "description" : "value must be an integer greater than zero." + }, { + "in" : "path", + "name" : "zoom", + "required" : true, + "schema" : { + "type" : "integer" + }, + "description" : "value must be an integer." + }, { + "in" : "path", + "name" : "x", + "required" : true, + "schema" : { + "type" : "integer" + }, + "description" : "value must be an integer." + }, { + "in" : "path", + "name" : "y", + "required" : true, + "schema" : { + "type" : "integer" + }, + "description" : "value must be an integer." + }, { + "in" : "query", + "name" : "parameters", + "required" : false, + "schema" : { + "type" : "string" + }, + "description" : "value must be a valid JSON string." + }, { + "in" : "query", + "name" : "latField", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "in" : "query", + "name" : "lonField", + "required" : true, + "schema" : { + "type" : "string" + } + } ], + "responses" : { + "2XX" : { + "description" : "Successful response" + }, + "4XX" : { + "description" : "Client error response" + }, + "5XX" : { + "description" : "Server error response" + } + }, + "tags" : [ "/api/embed" ] + } + }, + "/api/field/table-ids" : { + "post" : { + "operationId" : "post-api-field-table-ids", + "summary" : "POST /api/field/table-ids", + "description" : "Get unique Table IDs for a list of Field IDs.", + "parameters" : [ ], "responses" : { "2XX" : { - "description" : "Successful response" + "description" : "Successful response", + "content" : { + "application/json" : { + "schema" : { + "type" : "object", + "properties" : { + "table_ids" : { + "type" : "array", + "items" : { + "description" : "value must be an integer greater than zero.", + "type" : "integer", + "minimum" : 1 + } + } + }, + "required" : [ "table_ids" ] + } + } + } }, "4XX" : { "description" : "Client error response" @@ -30166,7 +34188,27 @@ "description" : "Server error response" } }, - "tags" : [ "/api/embed" ] + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "type" : "object", + "properties" : { + "field_ids" : { + "type" : "array", + "items" : { + "description" : "value must be an integer greater than zero.", + "type" : "integer", + "minimum" : 1 + } + } + }, + "required" : [ "field_ids" ] + } + } + } + }, + "tags" : [ "/api/field" ] } }, "/api/field/{id}" : { @@ -31054,11 +35096,11 @@ "tags" : [ "/api/ldap" ] } }, - "/api/llm/extract-tables" : { + "/api/llm/extract-sources" : { "post" : { - "operationId" : "post-api-llm-extract-tables", - "summary" : "POST /api/llm/extract-tables", - "description" : "Parse SQL and return referenced tables with their columns.\n\n Uses Macaw to parse the SQL, resolves table names to IDs,\n and returns permission-filtered tables with column metadata.\n\n This is a lightweight endpoint that does not trigger fingerprinting\n or field value fetching.", + "operationId" : "post-api-llm-extract-sources", + "summary" : "POST /api/llm/extract-sources", + "description" : "Parse native query sources and return referenced tables and cards/models.\n\n Uses Macaw to parse the SQL, resolves table names to IDs,\n and returns permission-filtered tables with column metadata. Card and model\n references are extracted from native query template tags.\n\n This is a lightweight endpoint that does not trigger fingerprinting\n or field value fetching.", "parameters" : [ ], "responses" : { "2XX" : { @@ -31068,6 +35110,13 @@ "schema" : { "type" : "object", "properties" : { + "card_ids" : { + "type" : "array", + "items" : { + "type" : "integer", + "minimum" : 1 + } + }, "tables" : { "type" : "array", "items" : { @@ -31155,7 +35204,7 @@ } } }, - "required" : [ "tables" ] + "required" : [ "tables", "card_ids" ] } } } @@ -31179,6 +35228,22 @@ }, "sql" : { "type" : "string" + }, + "template_tags" : { + "type" : "object", + "additionalProperties" : { + "type" : "object", + "properties" : { + "card-id" : { + "type" : "integer", + "minimum" : 1 + }, + "type" : { + "type" : "string" + } + }, + "required" : [ "type" ] + } } }, "required" : [ "database_id", "sql" ] @@ -32006,6 +36071,169 @@ "tags" : [ "/api/metabot" ] } }, + "/api/metabot/conversations" : { + "get" : { + "operationId" : "get-api-metabot-conversations", + "summary" : "GET /api/metabot/conversations", + "description" : "List conversations visible in the current user's history, most-recent first.\n\n New conversations are participation-based (the user authored at least one\n message); legacy conversations created before message authors were stamped\n fall back to the conversation originator.", + "parameters" : [ ], + "responses" : { + "2XX" : { + "description" : "Successful response", + "content" : { + "application/json" : { + "schema" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "array", + "items" : { + "type" : "object", + "properties" : { + "conversation_id" : { + "description" : "value must be a valid UUID.", + "type" : "string", + "pattern" : "[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}" + }, + "created_at" : { + "type" : "string", + "format" : "date-time" + }, + "last_message_at" : { + "oneOf" : [ { + "type" : "string", + "format" : "date-time" + }, { + "type" : "null" + } ] + }, + "message_count" : { + "description" : "value must be an integer greater or equal to than zero.", + "type" : "integer", + "minimum" : 0 + }, + "summary" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "user_id" : { + "oneOf" : [ { + "description" : "value must be an integer greater than zero.", + "type" : "integer", + "minimum" : 1 + }, { + "type" : "null" + } ] + } + }, + "required" : [ "conversation_id", "created_at", "summary", "user_id", "message_count", "last_message_at" ] + } + }, + "limit" : { + "description" : "value must be an integer greater or equal to than zero.", + "type" : "integer", + "minimum" : 0 + }, + "offset" : { + "description" : "value must be an integer greater or equal to than zero.", + "type" : "integer", + "minimum" : 0 + }, + "total" : { + "description" : "value must be an integer greater or equal to than zero.", + "type" : "integer", + "minimum" : 0 + } + }, + "required" : [ "data", "total", "limit", "offset" ] + } + } + } + }, + "4XX" : { + "description" : "Client error response" + }, + "5XX" : { + "description" : "Server error response" + } + }, + "tags" : [ "/api/metabot/conversations" ] + } + }, + "/api/metabot/conversations/{id}" : { + "get" : { + "operationId" : "get-api-metabot-conversations-id", + "summary" : "GET /api/metabot/conversations/{id}", + "description" : "Return a single conversation with its flattened chat messages.\n\n Accessible to any participant in the conversation or to any superuser.", + "parameters" : [ { + "in" : "path", + "name" : "id", + "required" : true, + "schema" : { + "type" : "string", + "pattern" : "[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}" + }, + "description" : "value must be a valid UUID." + } ], + "responses" : { + "2XX" : { + "description" : "Successful response", + "content" : { + "application/json" : { + "schema" : { + "type" : "object", + "properties" : { + "chat_messages" : { + "type" : "array", + "items" : { + "type" : "object", + "properties" : { } + } + }, + "conversation_id" : { + "description" : "value must be a valid UUID.", + "type" : "string", + "pattern" : "[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}" + }, + "created_at" : { + "type" : "string", + "format" : "date-time" + }, + "summary" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "user_id" : { + "oneOf" : [ { + "description" : "value must be an integer greater than zero.", + "type" : "integer", + "minimum" : 1 + }, { + "type" : "null" + } ] + } + }, + "required" : [ "conversation_id", "created_at", "summary", "user_id", "chat_messages" ] + } + } + } + }, + "4XX" : { + "description" : "Client error response" + }, + "5XX" : { + "description" : "Server error response" + } + }, + "tags" : [ "/api/metabot/conversations" ] + } + }, "/api/metabot/document/generate-content" : { "post" : { "operationId" : "post-api-metabot-document-generate-content", @@ -32118,11 +36346,27 @@ "post" : { "operationId" : "post-api-metabot-feedback", "summary" : "POST /api/metabot/feedback", - "description" : "Proxy Metabot feedback to Harbormaster, adding the premium embedding token.", + "description" : "Persist Metabot feedback.", "parameters" : [ ], "responses" : { "2XX" : { - "description" : "Successful response" + "description" : "Successful response", + "content" : { + "application/json" : { + "schema" : { + "type" : "object", + "properties" : { + "body" : { + "type" : "null" + }, + "status" : { + "const" : 204 + } + }, + "required" : [ "status", "body" ] + } + } + } }, "4XX" : { "description" : "Client error response" @@ -32136,7 +36380,35 @@ "application/json" : { "schema" : { "type" : "object", - "properties" : { } + "properties" : { + "freeform_feedback" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "issue_type" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "message_id" : { + "type" : "string", + "minLength" : 1 + }, + "metabot_id" : { + "description" : "value must be an integer greater than zero.", + "type" : "integer", + "minimum" : 1 + }, + "positive" : { + "type" : "boolean" + } + }, + "required" : [ "metabot_id", "message_id", "positive" ] } } } @@ -32784,6 +37056,75 @@ "tags" : [ "/api/metabot/slack" ] } }, + "/api/metabot/source-feedback" : { + "post" : { + "operationId" : "post-api-metabot-source-feedback", + "summary" : "POST /api/metabot/source-feedback", + "description" : "Persist Metabot source feedback.", + "parameters" : [ ], + "responses" : { + "2XX" : { + "description" : "Successful response", + "content" : { + "application/json" : { + "schema" : { + "type" : "object", + "properties" : { + "body" : { + "type" : "null" + }, + "status" : { + "const" : 204 + } + }, + "required" : [ "status", "body" ] + } + } + } + }, + "4XX" : { + "description" : "Client error response" + }, + "5XX" : { + "description" : "Server error response" + } + }, + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "type" : "object", + "properties" : { + "message_id" : { + "type" : "string", + "minLength" : 1 + }, + "metabot_id" : { + "description" : "value must be an integer greater than zero.", + "type" : "integer", + "minimum" : 1 + }, + "positive" : { + "type" : "boolean" + }, + "source_id" : { + "description" : "value must be an integer greater than zero.", + "type" : "integer", + "minimum" : 1 + }, + "source_type" : { + "type" : "string", + "enum" : [ "table", "card", "model" ] + } + }, + "required" : [ "metabot_id", "message_id", "source_id", "source_type", "positive" ] + } + } + } + }, + "tags" : [ "/api/metabot" ] + } + }, "/api/metric" : { "get" : { "operationId" : "get-api-metric", @@ -39235,14 +43576,237 @@ "type" : "null" } ] }, - "ids" : { - "type" : "array", - "items" : { - "description" : "value must be an integer greater than zero.", - "type" : "integer", - "minimum" : 1 - } - }, + "ids" : { + "type" : "array", + "items" : { + "description" : "value must be an integer greater than zero.", + "type" : "integer", + "minimum" : 1 + } + }, + "display_name" : { + "oneOf" : [ { + "type" : "string", + "minLength" : 1 + }, { + "type" : "null" + } ] + }, + "data_source" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "caveats" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "entity_type" : { + "oneOf" : [ { + "description" : "value must be a valid entity type (keyword or string)." + }, { + "type" : "null" + } ] + }, + "description" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + } + }, + "required" : [ "ids" ] + } + } + } + }, + "tags" : [ "/api/table" ] + } + }, + "/api/table/card__:id/fks" : { + "get" : { + "operationId" : "get-api-table-card__:id-fks", + "summary" : "GET /api/table/card__:id/fks", + "description" : "Return FK info for the 'virtual' table for a Card. This is always empty, so this endpoint\n serves mainly as a placeholder to avoid having to change anything on the frontend.", + "parameters" : [ { + "in" : "path", + "name" : "id", + "required" : true, + "schema" : { + "type" : "integer", + "minimum" : 1 + }, + "description" : "value must be an integer greater than zero." + } ], + "responses" : { + "2XX" : { + "description" : "Successful response" + }, + "4XX" : { + "description" : "Client error response" + }, + "5XX" : { + "description" : "Server error response" + } + }, + "tags" : [ "/api/table" ] + } + }, + "/api/table/card__:id/query_metadata" : { + "get" : { + "operationId" : "get-api-table-card__:id-query_metadata", + "summary" : "GET /api/table/card__:id/query_metadata", + "description" : "Return metadata for the 'virtual' table for a Card.", + "parameters" : [ { + "in" : "path", + "name" : "id", + "required" : true, + "schema" : { + "type" : "integer", + "minimum" : 1 + }, + "description" : "value must be an integer greater than zero." + } ], + "responses" : { + "2XX" : { + "description" : "Successful response" + }, + "4XX" : { + "description" : "Client error response" + }, + "5XX" : { + "description" : "Server error response" + } + }, + "tags" : [ "/api/table" ] + } + }, + "/api/table/{id}" : { + "get" : { + "operationId" : "get-api-table-id", + "summary" : "GET /api/table/{id}", + "description" : "Get `Table` with ID.", + "parameters" : [ { + "in" : "path", + "name" : "id", + "required" : true, + "schema" : { + "type" : "integer", + "minimum" : 1 + }, + "description" : "value must be an integer greater than zero." + }, { + "in" : "query", + "name" : "include_editable_data_model", + "required" : false, + "schema" : { + "oneOf" : [ { + "type" : "boolean" + }, { + "type" : "null" + } ] + } + } ], + "responses" : { + "2XX" : { + "description" : "Successful response" + }, + "4XX" : { + "description" : "Client error response" + }, + "5XX" : { + "description" : "Server error response" + } + }, + "tags" : [ "/api/table" ] + }, + "put" : { + "operationId" : "put-api-table-id", + "summary" : "PUT /api/table/{id}", + "description" : "Update `Table` with ID.", + "parameters" : [ { + "in" : "path", + "name" : "id", + "required" : true, + "schema" : { + "type" : "integer", + "minimum" : 1 + }, + "description" : "value must be an integer greater than zero." + } ], + "responses" : { + "2XX" : { + "description" : "Successful response" + }, + "4XX" : { + "description" : "Client error response" + }, + "5XX" : { + "description" : "Server error response" + } + }, + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "type" : "object", + "properties" : { + "points_of_interest" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "visibility_type" : { + "oneOf" : [ { + "type" : "string", + "enum" : [ "technical", "hidden", "cruft" ] + }, { + "type" : "null" + } ] + }, + "data_authority" : { + "oneOf" : [ { + "$ref" : "#/components/schemas/metabase.warehouse-schema-rest.api.table.data-authority-write" + }, { + "type" : "null" + } ] + }, + "data_layer" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "show_in_getting_started" : { + "oneOf" : [ { + "type" : "boolean" + }, { + "type" : "null" + } ] + }, + "owner_email" : { + "oneOf" : [ { + "type" : "string" + }, { + "type" : "null" + } ] + }, + "owner_user_id" : { + "oneOf" : [ { + "type" : "integer" + }, { + "type" : "null" + } ] + }, "display_name" : { "oneOf" : [ { "type" : "string", @@ -39251,225 +43815,11 @@ "type" : "null" } ] }, - "data_source" : { - "oneOf" : [ { - "type" : "string" - }, { - "type" : "null" - } ] - }, - "caveats" : { - "oneOf" : [ { - "type" : "string" - }, { - "type" : "null" - } ] - }, - "entity_type" : { - "oneOf" : [ { - "description" : "value must be a valid entity type (keyword or string)." - }, { - "type" : "null" - } ] - }, - "description" : { - "oneOf" : [ { - "type" : "string" - }, { - "type" : "null" - } ] - } - }, - "required" : [ "ids" ] - } - } - } - }, - "tags" : [ "/api/table" ] - } - }, - "/api/table/card__:id/fks" : { - "get" : { - "operationId" : "get-api-table-card__:id-fks", - "summary" : "GET /api/table/card__:id/fks", - "description" : "Return FK info for the 'virtual' table for a Card. This is always empty, so this endpoint\n serves mainly as a placeholder to avoid having to change anything on the frontend.", - "parameters" : [ { - "in" : "path", - "name" : "id", - "required" : true, - "schema" : { - "type" : "integer", - "minimum" : 1 - }, - "description" : "value must be an integer greater than zero." - } ], - "responses" : { - "2XX" : { - "description" : "Successful response" - }, - "4XX" : { - "description" : "Client error response" - }, - "5XX" : { - "description" : "Server error response" - } - }, - "tags" : [ "/api/table" ] - } - }, - "/api/table/card__:id/query_metadata" : { - "get" : { - "operationId" : "get-api-table-card__:id-query_metadata", - "summary" : "GET /api/table/card__:id/query_metadata", - "description" : "Return metadata for the 'virtual' table for a Card.", - "parameters" : [ { - "in" : "path", - "name" : "id", - "required" : true, - "schema" : { - "type" : "integer", - "minimum" : 1 - }, - "description" : "value must be an integer greater than zero." - } ], - "responses" : { - "2XX" : { - "description" : "Successful response" - }, - "4XX" : { - "description" : "Client error response" - }, - "5XX" : { - "description" : "Server error response" - } - }, - "tags" : [ "/api/table" ] - } - }, - "/api/table/{id}" : { - "get" : { - "operationId" : "get-api-table-id", - "summary" : "GET /api/table/{id}", - "description" : "Get `Table` with ID.", - "parameters" : [ { - "in" : "path", - "name" : "id", - "required" : true, - "schema" : { - "type" : "integer", - "minimum" : 1 - }, - "description" : "value must be an integer greater than zero." - }, { - "in" : "query", - "name" : "include_editable_data_model", - "required" : false, - "schema" : { - "oneOf" : [ { - "type" : "boolean" - }, { - "type" : "null" - } ] - } - } ], - "responses" : { - "2XX" : { - "description" : "Successful response" - }, - "4XX" : { - "description" : "Client error response" - }, - "5XX" : { - "description" : "Server error response" - } - }, - "tags" : [ "/api/table" ] - }, - "put" : { - "operationId" : "put-api-table-id", - "summary" : "PUT /api/table/{id}", - "description" : "Update `Table` with ID.", - "parameters" : [ { - "in" : "path", - "name" : "id", - "required" : true, - "schema" : { - "type" : "integer", - "minimum" : 1 - }, - "description" : "value must be an integer greater than zero." - } ], - "responses" : { - "2XX" : { - "description" : "Successful response" - }, - "4XX" : { - "description" : "Client error response" - }, - "5XX" : { - "description" : "Server error response" - } - }, - "requestBody" : { - "content" : { - "application/json" : { - "schema" : { - "type" : "object", - "properties" : { - "points_of_interest" : { - "oneOf" : [ { - "type" : "string" - }, { - "type" : "null" - } ] - }, - "visibility_type" : { - "oneOf" : [ { - "type" : "string", - "enum" : [ "technical", "hidden", "cruft" ] - }, { - "type" : "null" - } ] - }, - "data_authority" : { - "oneOf" : [ { - "$ref" : "#/components/schemas/metabase.warehouse-schema-rest.api.table.data-authority-write" - }, { - "type" : "null" - } ] - }, - "data_layer" : { - "oneOf" : [ { - "type" : "string" - }, { - "type" : "null" - } ] - }, - "show_in_getting_started" : { - "oneOf" : [ { - "type" : "boolean" - }, { - "type" : "null" - } ] - }, - "owner_email" : { - "oneOf" : [ { - "type" : "string" - }, { - "type" : "null" - } ] - }, - "owner_user_id" : { - "oneOf" : [ { - "type" : "integer" - }, { - "type" : "null" - } ] - }, - "display_name" : { + "collection_id" : { "oneOf" : [ { - "type" : "string", - "minLength" : 1 + "description" : "value must be an integer greater than zero.", + "type" : "integer", + "minimum" : 1 }, { "type" : "null" } ] @@ -41892,6 +46242,9 @@ } }, "created_at" : { }, + "active" : { + "type" : "boolean" + }, "description" : { "oneOf" : [ { "anyOf" : [ { @@ -41904,7 +46257,7 @@ } ] } }, - "required" : [ "id", "name", "description", "schedule", "ui_display_type", "entity_id", "created_at", "updated_at" ], + "required" : [ "id", "name", "description", "schedule", "ui_display_type", "active", "entity_id", "created_at", "updated_at" ], "additionalProperties" : false } } @@ -42131,6 +46484,9 @@ } }, "created_at" : { }, + "active" : { + "type" : "boolean" + }, "description" : { "oneOf" : [ { "anyOf" : [ { @@ -42143,7 +46499,7 @@ } ] } }, - "required" : [ "id", "name", "description", "schedule", "ui_display_type", "entity_id", "created_at", "updated_at" ], + "required" : [ "id", "name", "description", "schedule", "ui_display_type", "active", "entity_id", "created_at", "updated_at" ], "additionalProperties" : false } } @@ -42160,6 +46516,58 @@ "tags" : [ "/api/transform-job" ] } }, + "/api/transform-job/active" : { + "put" : { + "operationId" : "put-api-transform-job-active", + "summary" : "PUT /api/transform-job/active", + "description" : "Activate or deactivate every transform job. Inactive jobs do not run on schedule. Manual runs\n via `POST /api/transform-job/:job-id/run` ignore this flag.\n\n Reports per-job outcome counts: `:updated` (successfully flipped) and `:failed` (raised an\n error during the flip — the row update or Quartz write failed and was logged).", + "parameters" : [ ], + "responses" : { + "2XX" : { + "description" : "Successful response", + "content" : { + "application/json" : { + "schema" : { + "type" : "object", + "properties" : { + "failed" : { + "type" : "integer" + }, + "updated" : { + "type" : "integer" + } + }, + "required" : [ "updated", "failed" ], + "additionalProperties" : false + } + } + } + }, + "4XX" : { + "description" : "Client error response" + }, + "5XX" : { + "description" : "Server error response" + } + }, + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "type" : "object", + "properties" : { + "active" : { + "type" : "boolean" + } + }, + "required" : [ "active" ] + } + } + } + }, + "tags" : [ "/api/transform-job" ] + } + }, "/api/transform-job/{job-id}" : { "put" : { "operationId" : "put-api-transform-job-job-id", @@ -42284,6 +46692,9 @@ } }, "created_at" : { }, + "active" : { + "type" : "boolean" + }, "description" : { "oneOf" : [ { "anyOf" : [ { @@ -42296,7 +46707,7 @@ } ] } }, - "required" : [ "id", "name", "description", "schedule", "ui_display_type", "entity_id", "created_at", "updated_at" ], + "required" : [ "id", "name", "description", "schedule", "ui_display_type", "active", "entity_id", "created_at", "updated_at" ], "additionalProperties" : false } } @@ -42315,6 +46726,9 @@ "schema" : { "type" : "object", "properties" : { + "active" : { + "type" : "boolean" + }, "description" : { "oneOf" : [ { "type" : "string", @@ -42500,6 +46914,9 @@ } }, "created_at" : { }, + "active" : { + "type" : "boolean" + }, "description" : { "oneOf" : [ { "anyOf" : [ { @@ -42512,7 +46929,7 @@ } ] } }, - "required" : [ "id", "name", "description", "schedule", "ui_display_type", "entity_id", "created_at", "updated_at" ], + "required" : [ "id", "name", "description", "schedule", "ui_display_type", "active", "entity_id", "created_at", "updated_at" ], "additionalProperties" : false } } diff --git a/_docs/master/configuring-metabase/caching.md b/_docs/master/configuring-metabase/caching.md index eb8a8c735e..87f3c56f8c 100644 --- a/_docs/master/configuring-metabase/caching.md +++ b/_docs/master/configuring-metabase/caching.md @@ -104,7 +104,7 @@ For example, let's say you have a dashboard with a category filter (default valu ### Automatic caching logs -To view the queries Metabase ran to automatically refresh the cache, check out the [query log](../usage-and-performance-tools/usage-analytics#query-log-model) and filter the `Query source` by `cache-refresh`. +To view the queries Metabase ran to automatically refresh the cache, check out the [query log](../usage-and-performance-tools/usage-analytics-reference#query-log) and filter the `Query source` by `cache-refresh`. ## Set caching policies for dashboards, questions, and databases diff --git a/_docs/master/configuring-metabase/config-file.md b/_docs/master/configuring-metabase/config-file.md index 0f9fb16fa5..0c5bfb1b45 100644 --- a/_docs/master/configuring-metabase/config-file.md +++ b/_docs/master/configuring-metabase/config-file.md @@ -16,7 +16,7 @@ layout: new-docs On self-hosted [Pro](/product/pro) and [Enterprise](/product/enterprise) plans, Metabase supports initialization on launch from a config file named `config.yml`. The config file should be located at: - The current directory (the directory where the running Metabase JAR is located). -- The path specified by the `MB_CONFIG_FILE_PATH` [environment variable](./environment-variables). +- The path specified by the [`MB_CONFIG_FILE_PATH`](./environment-variables#mb_config_file_path) environment variable. The settings in the config file work the same as if you'd set the settings in the Admin Settings in your Metabase. Settings defined in this configuration file will update any existing settings. If, for example, a database already exists (that is, you'd already added it via the initial set up or **Admin settings** > **Databases**, Metabase will update the database entry based on the data in the config file). Which means: if you define a setting in the config file, and then later change that setting in your Metabase application, keep in mind that the config file will overwrite that change whenever Metabase restarts. Let's reiterate that in a blockquote: @@ -283,7 +283,7 @@ But you can set any of the Admin settings with the config file (for a list of se ## Loading a new Metabase from a config file -Since loading from a config file is a Pro/Enterprise feature: for new installations, you'll need to supply Metabase with a token using the `MB_PREMIUM_EMBEDDING_TOKEN` environment variable. +Since loading from a config file is a Pro/Enterprise feature: for new installations, you'll need to supply Metabase with a token using the [`MB_PREMIUM_EMBEDDING_TOKEN`](./environment-variables#mb_premium_embedding_token) environment variable. ```sh MB_PREMIUM_EMBEDDING_TOKEN="[your token]" java --add-opens java.base/java.nio=ALL-UNNAMED -jar metabase.jar diff --git a/_docs/master/configuring-metabase/config-template.md b/_docs/master/configuring-metabase/config-template.md index 64644204a3..410c61e1a3 100644 --- a/_docs/master/configuring-metabase/config-template.md +++ b/_docs/master/configuring-metabase/config-template.md @@ -76,6 +76,8 @@ config: settings: admin-email: null aggregated-query-row-limit: null + ai-features-enabled: true + ai-usage-max-retention-days: null allowed-iframe-hosts: |- youtube.com, youtu.be, @@ -99,6 +101,7 @@ config: linkedin.com, twitter.com, x.com + analytics-pii-retention-enabled: false anon-tracking-enabled: true api-key: null application-colors: {} @@ -122,10 +125,12 @@ config: custom-geojson-enabled: true custom-homepage: false custom-homepage-dashboard: null + custom-viz-enabled: false dashboards-save-last-used-parameters: true db-connection-timeout-ms: 10000 db-query-timeout-minutes: 20 default-maps-enabled: true + disable-auto-sync: false disable-cors-on-localhost: false download-row-limit: null email-from-address: notifications@metabase.com @@ -143,6 +148,7 @@ config: email-smtp-security-override: ssl email-smtp-username: null email-smtp-username-override: null + embedded-metabot-enabled: true embedding-app-origins-interactive: null embedding-app-origins-sdk: '' embedding-homepage: hidden @@ -205,6 +211,8 @@ config: ldap-user-filter: (&(objectClass=inetOrgPerson)(|(uid={login})(mail={login}))) ldap-user-provisioning-enabled: true license-token-missing-banner-dismissal-timestamp: [] + llm-anthropic-api-key: null + llm-metabot-provider: anthropic/claude-sonnet-4-6 load-analytics-content: true loading-message: doing-science login-page-illustration: default @@ -212,6 +220,7 @@ config: map-tile-server-url: https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png mcp-apps-cors-custom-origins: '' mcp-apps-cors-enabled-clients: [] + metabot-enabled: true metabot-slack-signing-secret: null native-query-autocomplete-match-style: substring nested-field-columns-value-length-limit: 50000 @@ -236,9 +245,13 @@ config: redirect-all-requests-to-https: false remote-sync-auto-import: false remote-sync-auto-import-rate: 5 + remote-sync-branch: null remote-sync-check-changes-cache-ttl-seconds: 60 remote-sync-task-time-limit-ms: 300000 + remote-sync-token: null remote-sync-transforms: false + remote-sync-type: read-only + remote-sync-url: null report-timezone: null reset-token-ttl-hours: 48 retry-initial-interval: 500 @@ -304,6 +317,7 @@ config: sync-leaf-fields-limit: 1000 synchronous-batch-updates: false thread-interrupt-escalation-timeout-ms: 0 + transform-run-job-sql-concurrency: 3 transform-timeout: 240 transforms-enabled: false unaggregated-query-row-limit: null diff --git a/_docs/master/configuring-metabase/environment-variables.md b/_docs/master/configuring-metabase/environment-variables.md index 1fb5eda81a..5b0d65f997 100644 --- a/_docs/master/configuring-metabase/environment-variables.md +++ b/_docs/master/configuring-metabase/environment-variables.md @@ -78,6 +78,33 @@ Maximum number of rows to return for aggregated queries via the API. Must be less than 1048575. See also MB_UNAGGREGATED_QUERY_ROW_LIMIT. +### `MB_AI_FEATURES_ENABLED` + +- Type: boolean +- Default: `true` +- [Exported as](../installation-and-operation/serialization): `ai-features-enabled`. +- [Configuration file name](./config-file): `ai-features-enabled` + +Whether AI features are enabled. + +### `MB_AI_USAGE_MAX_RETENTION_DAYS` + +- Type: integer +- Default: `null` +- [Exported as](../installation-and-operation/serialization): `ai-usage-max-retention-days`. +- [Configuration file name](./config-file): `ai-usage-max-retention-days` + +Number of days to retain rows in the ai_usage_log, metabot_conversation, and metabot_message tables. Minimum value is 30; set to 0 to retain data indefinitely. + +Sets the maximum number of days Metabase preserves rows for the following application database tables: + +- `ai_usage_log` +- `metabot_conversation` +- `metabot_message` + +Once a day, Metabase deletes rows older than this threshold. The minimum value is 30 days (Metabase will treat entered values of 1 to 29 the same as 30). +If set to 0, Metabase will keep all rows. + ### `MB_ALLOWED_IFRAME_HOSTS` - Type: string @@ -108,13 +135,24 @@ x.com` Allowed iframe hosts. +### `MB_ANALYTICS_PII_RETENTION_ENABLED` + +> Only available on Metabase [Pro](/product/pro) and [Enterprise](/product/enterprise) plans. + +- Type: boolean +- Default: `false` +- [Exported as](../installation-and-operation/serialization): `analytics-pii-retention-enabled`. +- [Configuration file name](./config-file): `analytics-pii-retention-enabled` + +Enable logging of embed path, query parameters, user agent, IP address, and Metabot conversation metadata for users of your internal data and embeds. This information will be shown in your usage analytics. + ### `MB_ANON_TRACKING_ENABLED` - Type: boolean - Default: `true` - [Configuration file name](./config-file): `anon-tracking-enabled` -Enable the collection of anonymous usage data in order to help us improve. +Enable the collection of anonymous usage data in order to help Metabase improve.. ### `MB_API_KEY` @@ -377,6 +415,17 @@ Pick one of your dashboards to serve as homepage. Users without dashboard access ID of dashboard to use as a homepage. +### `MB_CUSTOM_VIZ_ENABLED` + +> Only available on Metabase [Pro](/product/pro) and [Enterprise](/product/enterprise) plans. + +- Type: boolean +- Default: `false` +- [Exported as](../installation-and-operation/serialization): `custom-viz-enabled`. +- [Configuration file name](./config-file): `custom-viz-enabled` + +Should custom visualizations be enabled for this instance? + ### `MB_DASHBOARDS_SAVE_LAST_USED_PARAMETERS` - Type: boolean @@ -407,8 +456,7 @@ By default, this is 20 minutes. Timeout in minutes for the database's query execution, both for the Metabase application database and any data connections. If you have long-running queries, you might consider increasing this value. Adjusting the timeout does not impact Metabase’s frontend. - This setting also applies to individual queries executed within transforms, so make sure the duration is long enough - that it doesn't timeout any long-running queries in your transforms. + This setting does not apply to queries executed within transforms; those are governed by MB_TRANSFORM_TIMEOUT instead. Please be aware that other services (like Nginx) may still drop long-running queries. @@ -421,6 +469,13 @@ Timeout in minutes for the database's query execution, both for the Metabase app Whether or not the default GeoJSON maps are enabled. +### `MB_DISABLE_AUTO_SYNC` + +- Type: boolean +- Default: `false` + +When true, suppresses automatically-triggered syncs: the scheduled sync-and-analyze and update-field-values jobs do not run (and new triggers are not registered), and adding a new database does not kick off an initial sync. Syncs originating from an explicit request — the Sync-now REST endpoints, or a transform finalizing its output table — are unaffected. For deployments that load database metadata from disk at startup and should not have Metabase re-discover it. + ### `MB_DISABLE_CORS_ON_LOCALHOST` - Type: boolean @@ -572,6 +627,15 @@ SMTP username. Custom SMTP server username. +### `MB_EMBEDDED_METABOT_ENABLED` + +- Type: boolean +- Default: `true` +- [Exported as](../installation-and-operation/serialization): `embedded-metabot-enabled`. +- [Configuration file name](./config-file): `embedded-metabot-enabled` + +Whether Metabot is enabled for embedding. + ### `MB_EMBEDDING_APP_ORIGIN [DEPRECATED]` > Only available on Metabase [Pro](/product/pro) and [Enterprise](/product/enterprise) plans. @@ -1159,6 +1223,22 @@ When set to `true`, users who log in via LDAP will automatically get a Metabase The array of last two ISO8601 dates when an admin dismissed the license token missing banner. +### `MB_LLM_ANTHROPIC_API_KEY` + +- Type: string +- Default: `null` +- [Configuration file name](./config-file): `llm-anthropic-api-key` + +The Anthropic API Key. + +### `MB_LLM_METABOT_PROVIDER` + +- Type: string +- Default: `anthropic/claude-sonnet-4-6` +- [Configuration file name](./config-file): `llm-metabot-provider` + +The AI provider and model for Metabot. Format: provider/model-name, e.g. `anthropic/claude-haiku-4-5`, `openai/gpt-4.1-mini`, `openrouter/anthropic/claude-haiku-4-5`. + ### `MB_LOAD_ANALYTICS_CONTENT` - Type: boolean @@ -1226,6 +1306,15 @@ Custom CORS origins for self-hosted MCP clients, space-separated. Popular MCP clients enabled for CORS, stored as CSV client keys (e.g. claude, vscode). +### `MB_METABOT_ENABLED` + +- Type: boolean +- Default: `true` +- [Exported as](../installation-and-operation/serialization): `metabot-enabled`. +- [Configuration file name](./config-file): `metabot-enabled` + +Whether Metabot is enabled for regular usage. + ### `MB_METABOT_SLACK_SIGNING_SECRET` - Type: string @@ -1445,6 +1534,14 @@ Whether to automatically import from the remote git repository. Only applies if If remote-sync-type is :read-only and remote-sync-auto-import is true, the rate (in minutes) at which to check for updates to import. Defaults to 5. +### `MB_REMOTE_SYNC_BRANCH` + +- Type: string +- Default: `null` +- [Configuration file name](./config-file): `remote-sync-branch` + +The remote branch to sync with, e.g. `main`. + ### `MB_REMOTE_SYNC_CHECK_CHANGES_CACHE_TTL_SECONDS` - Type: integer @@ -1461,6 +1558,14 @@ Time-to-live in seconds for the remote changes check cache. Default is 60 second The maximum amount of time a remote sync task will be given to complete. +### `MB_REMOTE_SYNC_TOKEN` + +- Type: string +- Default: `null` +- [Configuration file name](./config-file): `remote-sync-token` + +An Authorization Bearer token allowing access to the git repo over HTTP. + ### `MB_REMOTE_SYNC_TRANSFORMS` - Type: boolean @@ -1469,6 +1574,22 @@ The maximum amount of time a remote sync task will be given to complete. Whether to sync transforms via remote-sync. When enabled, all transforms, transform tags, and transform jobs are synced as a single unit (all-or-nothing). +### `MB_REMOTE_SYNC_TYPE` + +- Type: keyword +- Default: `read-only` +- [Configuration file name](./config-file): `remote-sync-type` + +Git synchronization type - :read-write or :read-only. + +### `MB_REMOTE_SYNC_URL` + +- Type: string +- Default: `null` +- [Configuration file name](./config-file): `remote-sync-url` + +The location of your git repository, e.g. https://github.com/acme-inco/metabase.git. + ### `MB_REPORT_TIMEZONE` - Type: string @@ -2077,6 +2198,18 @@ By default, this is 0 and the thread interrupt escalation does not run. Timeout in milliseconds to wait after query cancellation before escalating to thread interruption. This is used to free up threads that are stuck waiting for a DB response after a query has been cancelled. +### `MB_TRANSFORM_RUN_JOB_SQL_CONCURRENCY` + +> Only available on Metabase [Pro](/product/pro) and [Enterprise](/product/enterprise) plans. + +- Type: integer +- Default: `3` + +Maximum number of SQL-backed transforms a single transform-job run may execute in parallel. + +This setting is only configurable on instances with the transforms add-on; OSS + deployments without the add-on always use the default. + ### `MB_TRANSFORM_TIMEOUT` > Only available on Metabase [Pro](/product/pro) and [Enterprise](/product/enterprise) plans. @@ -2086,8 +2219,11 @@ Timeout in milliseconds to wait after query cancellation before escalating to th The timeout for a transform job, in minutes. -Each query executed by a transform is also subject to the MB_DB_QUERY_TIMEOUT_MINUTES timeout, - so make sure that value isn't lower, or it will timeout your transform. +Controls the timeout for transform runs, including the queries they execute. This takes precedence + over MB_DB_QUERY_TIMEOUT_MINUTES for queries executed inside a transform, so transforms can run longer than regular + Metabase queries. Enforced per-statement via `Statement.setQueryTimeout`; transforms also use a separate JDBC + connection pool whose c3p0 leak-detector tolerates this longer runtime, so non-transform connections continue to + use the shorter `MB_DB_QUERY_TIMEOUT_MINUTES` leak-detector. ### `MB_TRANSFORMS_ENABLED` @@ -2179,6 +2315,26 @@ Use [MB_SESSION_COOKIES](#mb_session_cookies) to also expire sessions, when brow Also see the [Changing session expiration](../people-and-groups/changing-session-expiration) documentation page. +### `MB_APPLICATION_DB_IDLE_CONNECTION_TEST_PERIOD_SECONDS` + +Type: integer
+Default: `60`
+Since: v62.0 + +How often, in seconds, to test idle connections in the application database pool. Set to `0` to disable idle connection testing. + +### `MB_APPLICATION_DB_MAX_CONNECTION_AGE_SECONDS` + +Type: integer
+Default: `3600`
+Since: v62.0 + +Maximum lifetime, in seconds, of a connection in the application database pool. After this duration the connection is closed and a new one is opened. Set to `0` to keep connections until the database closes them. + +The default of one hour is set primarily to limit memory growth (especially on PostgreSQL). + +If you are connecting with a short-lived credential (e.g. an AWS RDS IAM auth token) baked into the URL or password at startup, setting this to `0` is a partial workaround — eventual reconnects from the database or the network will still fail. Prefer [MB_DB_AWS_IAM](#mb_db_aws_iam) (AWS RDS / Aurora) or [MB_DB_AZURE_MANAGED_IDENTITY_CLIENT_ID](#mb_db_azure_managed_identity_client_id) (Azure). + ### `MB_APPLICATION_DB_MAX_CONNECTION_POOL_SIZE` Type: integer
@@ -2193,6 +2349,30 @@ To see how many connections are being used, check the Metabase logs and look for See [MB_JDBC_DATA_WAREHOUSE_MAX_CONNECTION_POOL_SIZE](#mb_jdbc_data_warehouse_max_connection_pool_size) for setting maximum connections to the databases connected to Metabase. +### `MB_APPLICATION_DB_MAX_IDLE_TIME_EXCESS_CONNECTIONS_SECONDS` + +Type: integer
+Default: `600`
+Since: v62.0 + +How long, in seconds, an idle connection beyond the minimum pool size may stay open before being culled. Set to `0` to never cull excess idle connections. + +### `MB_APPLICATION_DB_TEST_CONNECTION_ON_CHECKOUT` + +Type: boolean
+Default: `false`
+Since: v62.0 + +When `true`, each connection is validated when checked out of the pool. Adds latency to every checkout. Useful when credentials may invalidate connections behind the pool's back. + +### `MB_APPLICATION_DB_UNRETURNED_CONNECTION_TIMEOUT_SECONDS` + +Type: integer
+Default: `3600`
+Since: v62.0 + +How long, in seconds, before a checked-out but unreturned connection is forcibly reclaimed. The legacy name `MB_APPLICATION_DB_UNRETURNED_CONNECTION_TIMEOUT` continues to work; the suffixed form is preferred. + ### `MB_ASYNC_QUERY_THREAD_POOL_SIZE` Type: integer
@@ -2222,6 +2402,28 @@ Default: `true` When set to `false`, Metabase will print migrations needed to be done in the application database and exit. Those migrations need to be applied manually. When `true`, Metabase will automatically make changes to the application database. This is not related to migrating away from H2. +### `MB_DB_AWS_IAM` + +Type: boolean
+Default: `false`
+Since: v0.58.0 + +When `true`, authenticate to the application database (PostgreSQL or MySQL/MariaDB on AWS RDS or Aurora) using AWS IAM instead of a password. Omit [MB_DB_PASS](#mb_db_pass). Auth tokens are refreshed automatically. + +Requires that AWS credentials are available via the standard credential chain (e.g. EKS IRSA, EC2 instance profile, ECS task role, or `AWS_ACCESS_KEY_ID` / `AWS_SECRET_ACCESS_KEY`), that the credentials hold the `rds-db:connect` permission for your database user, and that the DB user is set up for IAM authentication. + +For MySQL/MariaDB, also set [MB_DB_SSL_CERT](#mb_db_ssl_cert), or pass the SSL parameters in [MB_DB_CONNECTION_URI](#mb_db_connection_uri). + +### `MB_DB_AZURE_MANAGED_IDENTITY_CLIENT_ID` + +Type: string
+Default: `null`
+Since: v0.51.0 + +Authenticate to a PostgreSQL or MySQL application database using an Azure Managed Identity instead of a password. Set this to the client ID of a user-assigned Managed Identity attached to your compute resource. Omit [MB_DB_PASS](#mb_db_pass). Access tokens are refreshed automatically. + +Requires the Database authentication providers Pro/Enterprise feature. + ### `MB_DB_CONNECTION_URI` Type: string
@@ -2285,6 +2487,17 @@ Default: `null` The port for [MB_DB_HOST](#mb_db_host). +### `MB_DB_SSL_CERT` + +Type: string
+Default: `null`
+Since: v0.58.0 + +SSL configuration for the application database. Used with [MB_DB_AWS_IAM](#mb_db_aws_iam) on MySQL/MariaDB, where SSL is required. + +- `"trust"` — trust the server certificate without validation. +- A filesystem path to a PEM file — validate against the supplied CA certificate. + ### `MB_DB_TYPE` Type: string (`"h2"`, `"postgres"`, `"mysql"`)
@@ -2564,6 +2777,15 @@ Path of the "plugins" directory, which is used to store the Metabase database dr The location is where custom third-party drivers should be added. Then Metabase will load the driver on startup, which can be verified in the log. +### `MB_PROMETHEUS_SERVER_PORT` + +Type: integer
+Default: `null` + +Port to serve Prometheus metrics from. If set, Prometheus collectors are registered and served from `localhost:/metrics`. + +See [Observability with Prometheus](../installation-and-operation/observability-with-prometheus). + ### `MB_QP_CACHE_BACKEND` Type: string
diff --git a/_docs/master/configuring-metabase/settings.md b/_docs/master/configuring-metabase/settings.md index eac94a4e6b..61ef4a62ab 100644 --- a/_docs/master/configuring-metabase/settings.md +++ b/_docs/master/configuring-metabase/settings.md @@ -18,7 +18,6 @@ _Admin > Settings > General_ This section contains settings for your whole instance, like its URL, the reporting timezone, and toggles for disabling or enabling some of Metabase's optional features. You can configure these settings by clicking the **grid icon** in the upper right, then going to **Admin** > **Settings** > **General**. - ## Site name How you’d like to refer to this instance of Metabase. @@ -47,10 +46,20 @@ To revert to the default Metabase homepage, simply toggle off Custom homepage. This email address will be displayed in various messages throughout Metabase when users encounter a scenario where they need assistance from an admin, such as a password reset request. -## Anonymous tracking +## Usage tracking + +### Send anonymous tracking data to Metabase On self-hosted Metabases, this option determines whether or not you allow [anonymous data about your usage of Metabase](../installation-and-operation/information-collection) to be sent back to us to help us improve the product. [Your database’s data is never tracked or sent](/security). +### Collect user data to display in usage analytics + +{% include plans-blockquote.html feature="Collecting user data" %} + +You can switch on logging of IP addresses, user agents, embed path, query parameters, and Metabot conversation metadata for people using your Metabase, both for people directly by logging into Metabase, or for people who view an embedded Metabase component in your app. If enabled, you can find this information in your [usage analytics](../usage-and-performance-tools/usage-analytics). + +By default, collection of user data is turned **off**. + ## Friendly table and field names By default, Metabase attempts to make field and table names more readable by changing things like `somehorriblename` to `Some Horrible Name`. This does not work well for languages other than English, or for fields that have lots of abbreviations or codes in them. If you'd like to turn this setting off, you can do so from the Admin Panel under **Admin** **> Settings** > **General**. diff --git a/_docs/master/configuring-metabase/slack.md b/_docs/master/configuring-metabase/slack.md index c8786aff31..1749c45e4a 100644 --- a/_docs/master/configuring-metabase/slack.md +++ b/_docs/master/configuring-metabase/slack.md @@ -118,7 +118,7 @@ To check or edit your OAuth settings: > Natural language questions in Slack require [Metabot](../ai/metabot). -![Natural language questions in Slack](../ai/metabot-slack.png) +![Natural language questions in Slack](../ai/images/metabot-slack.png) Once you've connected Slack, you can let people chat with [Metabot](../ai/metabot) directly in Slack channels. For more on what Metabot can do in Slack, see [Metabot in Slack](../ai/metabot-slack). diff --git a/_docs/master/data-modeling/metrics.md b/_docs/master/data-modeling/metrics.md index 99abfdd1e8..4e2329d193 100644 --- a/_docs/master/data-modeling/metrics.md +++ b/_docs/master/data-modeling/metrics.md @@ -94,9 +94,9 @@ To edit a metric: 3. Save your changes. -## Explore and compare metrics +## Explore, compare, and do math with metrics -You can explore metrics, break them out by different dimensions, and compare metrics and [measures](../data-studio/measures) to each other in the [Metrics Explorer](../questions/metrics-explorer). +To break metrics out by different dimensions, compare metrics and [measures](../data-studio/measures), and do math with metrics (like add or divide metrics by each other), check out the [Metrics Explorer](../questions/metrics-explorer). ![Metrics explorer](./images/metric-explorer.png) @@ -120,7 +120,7 @@ You can use [custom expressions](../questions/query-builder/expressions) to defi (CountIf([Score] >= 9) - CountIf([Score] <= 6) ) / Count() * 100 ``` -Metric formula must be an _aggregation_ of a column, meaning you can have a formula like `Sum([Price])` which will add up all the values in the `Price` column across all records, but you can't have a formula like `[Price] + [Tax]` which adds two values on a per-record basis. If you need to create a "calculated" column, consider using [transforms](../data-studio/transforms/transforms-overview) or [models](../data-modeling/models) instead. +A metric formula must be an _aggregation_ of a column, meaning you can have a formula like `Sum([Price])` which will add up all the values in the `Price` column across all records, but you can't have a formula like `[Price] + [Tax]` which adds two values on a per-record basis. If you want to create a "calculated" column, consider creating a [transform](../data-studio/transforms/transforms-overview) or [model](../data-modeling/models) instead. We don't recommend adding filters into the metric definition to avoid filter conflicts when using metrics in the query builder. You can use conditional custom expressions like [`CountIf`, `SumIf`, and `DistinctIf`](../questions/query-builder/expressions-list#aggregations) to create conditional aggregations. diff --git a/_docs/master/data-modeling/model-persistence.md b/_docs/master/data-modeling/model-persistence.md index 755f7aa0c4..99906dec50 100644 --- a/_docs/master/data-modeling/model-persistence.md +++ b/_docs/master/data-modeling/model-persistence.md @@ -11,7 +11,7 @@ layout: new-docs # Model persistence -> Prefer [Transforms](../data-studio/transforms/transforms-overview) instead of model persistence. Model persistence remains supported for now, but it will be deprecated in future versions of Metabase. You can [convert models to transforms in bulk](../data-studio/transforms/transforms-overview#convert-models-to-transforms). +> Prefer [Transforms](../data-studio/transforms/transforms-overview) instead of model persistence. Model persistence remains supported for now, but it will be deprecated in future versions of Metabase. You can [convert models to transforms in bulk](../data-studio/transforms/query-transforms#convert-models-to-transforms). Metabase can persist the results of your models so that your models (and the questions based on those models) load faster. diff --git a/_docs/master/data-modeling/models.md b/_docs/master/data-modeling/models.md index f66020107c..f6e019f54b 100644 --- a/_docs/master/data-modeling/models.md +++ b/_docs/master/data-modeling/models.md @@ -13,7 +13,7 @@ redirect_from: # Models -> Consider using [Transforms](../data-studio/transforms/transforms-overview) instead of models. You can [convert models to transforms in bulk](../data-studio/transforms/transforms-overview#convert-models-to-transforms). +> Consider using [Transforms](../data-studio/transforms/transforms-overview) instead of models. You can [convert models to transforms in bulk](../data-studio/transforms/query-transforms#convert-models-to-transforms). Models curate data from another table or tables from the same database to anticipate the kinds of questions people will ask of the data. You can think of them as derived tables, or a special kind of saved question meant to be used as the starting point for new questions. You can base a model on a SQL or query builder question, which means you can include custom, calculated columns in your model. @@ -231,7 +231,7 @@ See [Model persistence](./model-persistence) If you're an admin, you can convert existing models to transforms one at a time. Conversion creates a transform from the model's query, runs it to produce the output table, and then updates all questions and dashboards that used the model to use the transform's table instead. The model itself becomes a saved question. -See [Convert existing models to transforms](../data-studio/transforms/transforms-overview#convert-models-to-transforms). +See [Convert existing models to transforms](../data-studio/transforms/query-transforms#convert-models-to-transforms). ## Further reading diff --git a/_docs/master/data-studio/images/disable-all-jobs.png b/_docs/master/data-studio/images/disable-all-jobs.png new file mode 100644 index 0000000000..61bc13e838 Binary files /dev/null and b/_docs/master/data-studio/images/disable-all-jobs.png differ diff --git a/_docs/master/data-studio/images/jobs-schedule.png b/_docs/master/data-studio/images/jobs-schedule.png new file mode 100644 index 0000000000..57329bd6ca Binary files /dev/null and b/_docs/master/data-studio/images/jobs-schedule.png differ diff --git a/_docs/master/data-studio/transforms/addons.md b/_docs/master/data-studio/transforms/addons.md new file mode 100644 index 0000000000..c799f1da6a --- /dev/null +++ b/_docs/master/data-studio/transforms/addons.md @@ -0,0 +1,111 @@ +--- +version: master +has_magic_breadcrumbs: true +show_category_breadcrumb: true +show_title_breadcrumb: true +category: 'Data Studio' +title: 'Transform add-ons' +source_url: 'https://github.com/metabase/metabase/blob/master/docs/data-studio/transforms/addons.md' +layout: new-docs +summary: 'Metabase transforms come in two flavors - basic transforms for basic query-based functionality, and advanced transforms for Python workflows, transform inspector, and other functionality.' +--- + +# Transform add-ons + +At a glance: + +[**Basic transforms**](#basic-transforms): + +- Run [query-based transforms](query-transforms) +- Schedule transform [jobs](jobs-and-runs). +- (Pro/Enterprise only) Configure [permissions for transforms](transforms-overview#permissions-for-transforms). + +[**Advanced transforms**](#advanced-transforms): + +- Run [query-based](query-transforms) and [Python transforms](python-transforms); +- Schedule transform [jobs](jobs-and-runs). +- (Pro/Enterprise only) Configure [permissions for transforms](transforms-overview#permissions-for-transforms). +- [Writable connection](../../databases/writable-connection): separate database connection used for write operations. +- [Transform inspector](transform-inspector). + +Availability and pricing depends on your plan and hosting method. + +## Basic transforms + +With basic transforms, you can: + +- Write and run [query-based transforms](query-transforms) (but not Python transforms). +- [Schedule and run jobs](jobs-and-runs). +- (Pro/Enterprise only) Configure [permissions for transforms](transforms-overview#permissions-for-transforms). + +### Enable basic transforms + +- **Self-hosted Metabases**: Basic transform functionality is included on self-hosted Metabases by default. Just log into your Metabase, [enable transforms](../transforms/transforms-overview#enable-transforms), and you're good to go. + +- **Metabase Cloud**: Basic transform functionality on Metabase Cloud - Starter, Pro, or Enterprise - comes with an additional small fee per successful transform run, see [Pricing](/pricing). + + Only people logged in with an email of a [Metabase Store admins](../../cloud/accounts-and-billing#add-people-to-manage-your-metabase-store-account) (not just Metabase _instance_ admins) can enable basic transforms. To enable Basic transforms on Metabase Cloud, see [Enable transforms](./transforms-overview#enable-transforms). + +### Cancel basic transforms + +Once basic transforms are enabled on your Metabase Cloud instance, they can't be disabled. + +## Advanced transforms + +Advanced transforms include: + +- Everything in [basic transforms](#basic-transforms). +- [Python transforms](python-transforms) for more flexible data processing. +- [Writable connection](../../databases/writable-connection): separate database connection used for write operations. +- [Transform inspector](transform-inspector). + +You can buy the Advanced transforms add-on for: + +- Any Metabase Cloud instance (Starter, Pro, Enterprise) +- Self-hosted Pro or Enterprise instances. + + Currently, you can't use Advanced transforms functionality on Open Source self-hosted plans. + +The Advanced transforms add-on comes with an additional charge per successful transform run (compare to [Basic transforms](#basic-transforms)). See [Pricing](/pricing). + +### Enable Advanced transforms + +To enable Advanced transforms functionality, you need to have [Basic transforms](#basic-transforms) already, see [Enable basic transforms](#enable-basic-transforms). + +There are two ways to enable Advanced transforms: + +- **From your Metabase instance**: you can navigate to a feature requiring advanced transforms (like Python transforms or transform inspector), and follow the prompts to upgrade. + + To enable Advanced transforms from your Metabase instance, you need to be logged into the instance with the same email as a [Metabase Store admin](../../cloud/accounts-and-billing#add-people-to-manage-your-metabase-store-account), because Advanced transform incur an additional charge. + +- **From [Metabase Store](https://store.metabase.com)**: + + 1. Log into [Metabase Store](https://store.metabase.com) (your Metabase Store account might be different from your Metabase instance account). + 2. Click on **Manage plan** next to the instance where you'd like to add Advanced transforms. + 3. Under **Manage Add-ons**, find **Advanced transforms** and click **Upgrade**. + +Once you upgrade to Advanced transforms: + +- You get access to Advanced transforms features/ +- All your existing query-based transforms will be charged at Advanced transforms rate. + +### Cancel Advanced transforms + +You can downgrade from Advanced transforms to [Basic transforms](#basic-transforms). + +1. Log into [Metabase Store](https://store.metabase.com) (your Metabase Store account might be different from your Metabase instance account). +2. Click on **Manage plan** next to the instance with Advanced transforms. +3. Under **Manage Add-ons**, find **Advanced transforms**, click **three dos** and select **Downgrade to basic**. + +Once you downgrade from advanced transforms: + +- Your Python transforms will no longer run and will be removed. +- Transforms and other write features will stop using the writable connection (if you had one configured.) + +## How billing works for transforms + +Unless you're on an Enterprise plan, transforms - either basic (on Metabase Cloud) or advanced - are billed based on the number of successful runs. See [Jobs and runs](jobs-and-runs) for more on transform runs, and [Pricing](/pricing) for up-to-date information on pricing. + +When you upgrade from basic to advanced transforms, _all_ your transforms will be billed at advanced transforms rate. + +If you're on an Enterprise plan and have questions about billing, [contact us](/help-premium). diff --git a/_docs/master/data-studio/transforms/jobs-and-runs.md b/_docs/master/data-studio/transforms/jobs-and-runs.md index 93346aaeaf..42e32a5961 100644 --- a/_docs/master/data-studio/transforms/jobs-and-runs.md +++ b/_docs/master/data-studio/transforms/jobs-and-runs.md @@ -40,16 +40,76 @@ _Data Studio > Jobs_ Jobs run one or more transforms on schedule based on transform tags. -To see all jobs, go to **Data Studio** and click on the **Jobs** at the bottom of the left sidebar. - -To create a new job, go to **Data Studio > Jobs**, and click on the **+ New** button in the top right. - Jobs have two components: schedule and tags. - **Schedule** determines when the job will be executed: daily, hourly, etc. You can specify a custom cron schedule (e.g. "Every weekday at 9:05 AM"). The times are given in your Metabase's system timezone. - **Tags** determine _which_ transforms a job runs, not when the job runs. For example, you can create a `Weekdays` tag, add that tag to a few transforms, then create a job that runs all the transforms with the `Weekdays` tag every weekday at 9:05AM. -Job can use multiple tags, and will run all transforms that have _any_ of those tags. For example, you can have a job "Weekend job" that is scheduled run at noon on Saturdays and Sundays that picks up all transforms tagged either "Saturday", "Sunday", or "Weekend". +Jobs will run all transforms tagged with any of the tags, plus any transforms that the tagged transforms depend on, see [Jobs will run all dependent transforms](#jobs-will-run-all-dependent-transforms). + +You can see which transforms a job will run and in which order on the job's page. + +### See all jobs + +To see all jobs, go to **Data Studio** and click the **Jobs** at the bottom of the left sidebar. + +### Create a job + +To create a new job: + +1. Go to **Data Studio > Jobs** +2. Click the **+ New** button in the top right. +3. Specify the schedule: select one of the built-in schedules or use cron syntax to specify a custom schedule, + + ![Jobs schedule](../images/jobs-schedule.png) + + Job can use multiple tags, and will run all transforms that have _any_ of those tags. For example, you can have a job "Weekend job" that is scheduled run at noon on Saturdays and Sundays that picks up all transforms tagged either "Saturday", "Sunday", or "Weekend". + +### Disable jobs + +You can disable jobs without deleting them. Unlike deletion (which is permanent), disabling a job just means it won't run until you re-enable it. This is useful when you want to temporarily stop transforms from running - for example, for debugging purposes. This way you don't your lose configuration settings like tags and schedules. + +To disable a specific job: + +1. Go to **Data studio > Jobs**. +2. Find the job you want to disable and click the **three dots** icon to the right of the job's name. +3. Select **Disable** + +To disable all jobs: + +1. Go to **Data studio > Jobs**. +2. Click the **three dots** icon above the table with all the jobs, and select **Disable all**. + + ![Disable all jobs](../images/disable-all-jobs.png) + +Even if you disable all jobs, new jobs will still be created enabled by default. + +### Re-enable jobs + +If you [disabled any jobs](#disable-jobs), you can later re-enable them: + +To re-enable a specific job: + +1. Go to **Data studio > Jobs**. +2. Find the job you want to re-enable and click the **three dots** icon to the right of the job's name. +3. Select **Re-enable** + +To re-enable all jobs: + +1. Go to **Data studio > Jobs**. +2. Click the **three dots** icon above the table with all the jobs, and select **Re-enable all**. + +### Delete a job + +Deleting a job will not delete any transforms. + +Deleted jobs can't be restored. If you want to temporarily stop a job from running, consider disabling the job instead. + +To delete a job: + +1. Go to **Data Studio > Jobs**. +2. Find the job you want to delete and click the **three dots** icon to the right of the job's name. +3. Select **Delete**. ## Jobs will run all dependent transforms diff --git a/_docs/master/data-studio/transforms/python-runner.md b/_docs/master/data-studio/transforms/python-runner.md index f164f55a77..e4d9307989 100644 --- a/_docs/master/data-studio/transforms/python-runner.md +++ b/_docs/master/data-studio/transforms/python-runner.md @@ -12,7 +12,7 @@ summary: 'Configure self-hosted Python execution environment to run Python trans # Python runner -> Self-hosted Python transforms require self-hosted Pro or Enterprise plan with the **Advanced transforms** add-on. +> Self-hosted Python transforms require self-hosted Pro or Enterprise plan with the [Advanced transforms add-on](addons). To run Python transforms from a self-hosted Metabase, you'll need to configure a separate self-hosted execution environment. If you're using Metabase Cloud, you'll need to buy the Transforms add-on. @@ -102,7 +102,7 @@ docker run -d \ ### Metabase environment variables -These settings can also be configured in the Metabase UI at **Admin** > **Settings** > **Python Runner** (`/admin/settings/python-runner`). Note that environment variables take precedence over UI settings. +These settings can also be configured in the Metabase UI at **Admin** > **Settings** > **Python Runner**. Note that environment variables take precedence over UI settings. | Variable | Description | | ----------------------------------------- | ---------------------------------------------------------------------------------- | @@ -115,8 +115,6 @@ These settings can also be configured in the Metabase UI at **Admin** > **Settin | `MB_PYTHON_STORAGE_S_3_SECRET_KEY` | S3 secret key | | `MB_PYTHON_STORAGE_S_3_PATH_STYLE_ACCESS` | (Optional) Set to `true` for S3-compatible services like MinIO or LocalStack | ---- - ## Using Docker Compose Docker Compose simplifies managing multiple containers. Below are example configurations for different scenarios. diff --git a/_docs/master/data-studio/transforms/python-transforms.md b/_docs/master/data-studio/transforms/python-transforms.md index 45272573fa..5e65db87bc 100644 --- a/_docs/master/data-studio/transforms/python-transforms.md +++ b/_docs/master/data-studio/transforms/python-transforms.md @@ -12,7 +12,7 @@ summary: 'Use Python to wrangle your data in Metabase and write the results back # Python transforms -> Python transforms require the **Transforms add-on**. +> Python transforms require the [Advanced transforms add-on](addons) Use Python to write [transforms](transforms-overview). diff --git a/_docs/master/data-studio/transforms/query-transforms.md b/_docs/master/data-studio/transforms/query-transforms.md index 9a35179b59..ebbb41be16 100644 --- a/_docs/master/data-studio/transforms/query-transforms.md +++ b/_docs/master/data-studio/transforms/query-transforms.md @@ -12,7 +12,7 @@ summary: 'Create Metabase questions and SQL queries to transform your data and w # Query-based transforms -> On Metabase Cloud, you need the **Transforms** add-on to run query-based transforms. +> On Metabase Cloud, you need the [**Basic transforms** add-on](addons) to run query-based transforms. With query-based transforms, you can write a query in SQL or Metabase's query builder, and then write the results of the query back into the database on schedule. @@ -30,23 +30,24 @@ For general information about Metabase transforms, see [Transforms](transforms-o ## Create a query-based transform -On Metabase Cloud, you need the **Transforms** add-on to create query-based transforms. +On Metabase Cloud, you need the [**Basic transforms** add-on](addons) to create query-based transforms. -1. Go to **Data studio > Transforms**. +1. [Enable transforms](transforms-overview#enable-transforms). +2. Go to **Data studio > Transforms**. -2. Click **+ New** and pick "Query builder", "SQL", or "Copy of existing question". +3. Click **+ New** and pick "Query builder", "SQL", or "Copy of existing question". Currently, you can't convert between different transform types (like converting a query builder transform to a SQL-based transform, or a SQL transform into a Python transform). If you want to change your transform built with the query builder into a SQL transform, you'll need to create a new transform with the same target and tags, and delete the old transform. -3. Write your transform query as you would normally write a query in Metabase. See [Query builder](../../questions/query-builder/editor) and [SQL editor](../../questions/native-editor/writing-sql) documentation for more information. +4. Write your transform query as you would normally write a query in Metabase. See [Query builder](../../questions/query-builder/editor) and [SQL editor](../../questions/native-editor/writing-sql) documentation for more information. Not all databases support transforms, see [Databases that support transforms](transforms-overview#databases-that-support-transforms). -4. To test your transform, press the **Run** button at the bottom of the editor. +5. To test your transform, press the **Run** button at the bottom of the editor. Previewing a query transform in the editor will _not_ write the result of the transform back to the database. -5. Click **Save** in the top right corner and fill out the transform information: +6. Click **Save** in the top right corner and fill out the transform information: - **Name** (required): The name of the transform. - **Schema** (required): Target schema for your transform. This schema can be different from the schema of the source table(s). You create a new schema by typing its name in this field. You can only transform data _within_ a database; you can't write from one database to another. @@ -54,7 +55,7 @@ On Metabase Cloud, you need the **Transforms** add-on to create query-based tran - **Folder** (optional): The folder where the transform should live. Click on the field to pick a different folder or create a new one. - **Incremental transformation** (optional): see [Incremental query transforms](#incremental-query-transforms) -6. Optionally, assign tags to your transforms. Tags are used by [jobs](jobs-and-runs) to run transforms on schedule. +7. Optionally, assign tags to your transforms. Tags are used by [jobs](jobs-and-runs) to run transforms on schedule. ## Variables in SQL transforms @@ -92,8 +93,6 @@ Parameters in transforms must either: The reason transform variables must have a default value (or be optional) is that transforms run on a schedule, so there's no way to pass a value to the variable when the job runs the transform. -The incremental `{%raw%}[[WHERE id > {{checkpoint}}]]{% endraw %}` pattern shown in [Incremental query transforms](#incremental-query-transforms) is an example of this an optional variable in practice. See also [optional variables](../../questions/native-editor/optional-variables). - ## Run a query transform See [Run a transform](transforms-overview#run-a-transform). You'll see logs for a transform run on the transform's page. @@ -134,8 +133,8 @@ To make this transform incrementally load the data based on new values of `order 1. Add a table variable, for example `{{orders_var}}` replacing `orders` in the `FROM` statement; 2. In the table variable settings, connect the table variable to the `orders` table; 3. Replace other references to the table in your query with either: - - The name of the table variable (if you have "Emit table alias" toggled on in variable's setting). - - Your own handcrafted alias for the variable. + - The name of the table variable (if you have "Emit table alias" toggled on in variable's setting). + - Your own handcrafted alias for the variable. So your query will look like this: @@ -159,3 +158,36 @@ To make a query transform incremental: 1. Go to the transform's page in **Data studio > Transforms**. 2. Switch to **Settings** tab. 3. In **Column to check for new values**, select the column in one of the source tables that Metabase should check to determine which values are new. Only some columns are eligible. See [prerequisites for incremental transforms](./transforms-overview#prerequisites-for-incremental-transforms). + +## Convert models to transforms + +{% include plans-blockquote.html feature="Converting models to transforms"%} + +If you have models you'd like to migrate to transforms, Metabase can convert them for you. When you convert a model, Metabase: + +1. Creates a new transform based on the model's query. +2. Runs the transform to create the output table in your database. +3. Replaces every question, dashboard, and other item that used the model with the transform's output table. +4. Converts the original model to a question. + +You must be an admin to convert models, and the model's database must [support transforms](transforms-overview#databases-that-support-transforms). + +To convert a model into a transform: + +1. Review [Replacing data sources](../dependencies/replace-data-sources) docs for overview and limitations of the process. +2. Open **Data Studio** and select **Transforms** in the sidebar. +3. Click **Tools > Migrate models**. +4. Find the model you want to convert and click it to open its details panel. The panel shows the model's name, database, and collection, and a list of items that depend on it. +5. Click **Convert to a transform**. +6. Fill out the transform settings. See [Create a transform](#create-a-query-based-transform) for the overview of settings. +7. Click **Convert to a transform**. + +Metabase runs the conversion in the background. A status indicator at the bottom of the screen shows progress. + +If the transform run fails, Metabase stops and leaves the model unchanged—nothing is replaced. + +If the transform runs successfully, but the source swap fails afterward, the transform and its output table are kept. The model is left unchanged. You can complete the migration manually using [Replace data sources](../dependencies/replace-data-sources) to point the remaining content from the model to the transform's output table. + +Once conversion completes, all content that previously queried the model now queries the transform's output table. The original model just becomes a question. + +Newly created tables will be created with default permissions and will _not_ inherit the model's permissions. As an alternative, consider manually creating and running the transform first, setting up the permissions, then using [Replace data sources](../dependencies/replace-data-sources) to swap the model for the transform's output table once you configured permissions. diff --git a/_docs/master/data-studio/transforms/transform-inspector.md b/_docs/master/data-studio/transforms/transform-inspector.md index 48c2f4c28d..d456155ff6 100644 --- a/_docs/master/data-studio/transforms/transform-inspector.md +++ b/_docs/master/data-studio/transforms/transform-inspector.md @@ -12,7 +12,7 @@ summary: 'Analyze how your transforms process data by inspecting input and outpu # Transform inspector -> Transform inspector requires the **Advanced transforms** add-on. +> Transform inspector requires the [Advanced transforms add-on](addons). _Data Studio > Transforms > [transform name] > Inspect_ diff --git a/_docs/master/data-studio/transforms/transforms-overview.md b/_docs/master/data-studio/transforms/transforms-overview.md index 50488c3497..e417ba30ce 100644 --- a/_docs/master/data-studio/transforms/transforms-overview.md +++ b/_docs/master/data-studio/transforms/transforms-overview.md @@ -43,7 +43,7 @@ Currently, Metabase can create transforms on the following databases: You can't create transforms on databases that have [Database routing](../../permissions/database-routing) enabled, or on Metabase's Sample Database. -Transforms will create tables in your database, so the database user you use for your connection must have appropriate privileges. See [Database users, roles, and privileges](../../databases/users-roles-privileges). We suggest using a [Writable connection](../../databases/writable-connection) option for your database. +Transforms will create tables in your database, so the database user you use for your connection must have appropriate privileges. See [Database users, roles, and privileges](../../databases/users-roles-privileges). We suggest using a [Writable connection](../../databases/writable-connection) for your database. ## Types of transforms @@ -54,22 +54,39 @@ Metabase supports two types of transforms: query-based transforms and Python tra ## Permissions for transforms -If you are running Metabase Open Source/Starter, Admins (and only Admins) can see and run transforms. +Permission configuration for transform depends on your plan. -Metabase Pro/Enterprise comes with additional permission controls for transforms: +- **Metabase Open Source/Starter**: Admins (and only Admins) can see and run transforms. -- To **see** the list of transforms on your instance, people need to be able to access Data Studio, so they need to be either an Admin or a member of the special [Data Analyst group](../../people-and-groups/managing). -- To **execute** transforms on a database, people additionally need to have the [Transform permissions](../../permissions/data) for that database. +- **Metabase Pro/Enterprise** comes with additional permission controls for transforms: a special [Data Analysts](../../people-and-groups/managing) group for non-Admins with potential transform access, and granular transform permissions for each database: + + - To **see** the list of transforms on your instance, people need to be able to access Data Studio, so they need to be either an Admin or a member of the special [Data Analyst group](../../people-and-groups/managing). + - To **execute** transforms on a database, people need to be either Admins on belong to the special [Data Analyst group](../../people-and-groups/managing). Additionally people need to have the [Transform permissions](../../permissions/data) for that database. + +## Enable transforms + +Before you can start writing transforms, you'll need to enable transforms in your Metabase instance. + +If you are on a Metabase Cloud plan, only people logged in with an email of a [Metabase Store admins](../../cloud/accounts-and-billing#add-people-to-manage-your-metabase-store-account) (not just Metabase _instance_ admins) can enable basic transforms, because transforms incur a cost per run on Metabase Cloud. + +To enable transforms: + +1. Navigate to [**Data Studio**](../overview) by click the **grid icon** in top right corner of your Metabase and selecing **Data Studio**. +2. In Data Studio, click **Transforms** in the right sidebar. +3. If the transforms have not been enabled on your instance yet, you'll see a prompt to enable them. You can do just that. + +Once you've enabled transforms, you can [configure permissions](#permissions-for-transforms) and start [creating transforms](#create-a-transform). ## See all transforms _Data Studio > Transforms_ +See [permissions needed to see transforms](#permissions-for-transforms). + You can see all your Metabase's transforms: -1. Make sure you have [appropriate permissions to see transforms](#permissions-for-transforms). -2. Click the **grid** icon on top right and go to **Data Studio**. -3. In the left sidebar, select **Transforms**. +1. Click the **grid** icon on top right and go to **Data Studio**. +2. In the left sidebar, select **Transforms**. ![Transforms](../images/transforms.png) @@ -77,11 +94,13 @@ You can see all your Metabase's transforms: _Data Studio > Transforms_ -If you're using remote sync, you won't be able to create transforms if your instance is in ["read-only" sync mode](../../installation-and-operation/remote-sync). +> If you're using remote sync, you won't be able to create transforms if your instance is in ["read-only" sync mode](../../installation-and-operation/remote-sync). + +See [permissions needed to create transforms](#permissions-for-transforms). To create a transform: -1. Make sure you have [appropriate permissions for creating transforms](#permissions-for-transforms). +1. [Enable transforms](#enable-transforms). 2. Click the **grid** icon on top right and go to **Data Studio**. 3. In the left sidebar, select **Transforms**. 4. Click **+ New** and select a source for your transform. @@ -102,7 +121,7 @@ To create a transform: If you're writing a SQL transform, variables _must_ be wrapped in optional blocks (`[[ ]]`), or given a default value. See [variables in SQL transforms](query-transforms#variables-in-sql-transforms) for more details. - If you have the Metabot AI add-on, you can [use Metabot](#use-metabot-to-generate-code-for-transforms) to generate code for your transform. + If [Metabot is enabled](../../ai/settings#enable-ai-features), you can [use Metabot](#use-metabot-to-generate-code-for-transforms) to generate code for your transform. 6. Click **Save** in the top right corner and fill out the transform information: @@ -118,7 +137,7 @@ To create a transform: ## Use Metabot to generate code for transforms -> Code generation for transforms requires the **Metabot AI** and **Transforms** add-ons. +> Code generation for transforms requires [AI features](../../ai/settings#enable-ai-features). You can ask Metabot to generate a new SQL or Python-based transform, or edit an existing transform. @@ -152,12 +171,13 @@ If you're using remote sync, you won't be able to edit transforms if your instan _Data Studio > Transforms > Definition_ +See [permissions to edit transforms](#permissions-for-transforms). + To edit the transform's query or script: -1. Make sure you have [permissions to edit transforms](../../permissions/data). -2. Go to **Data Studio > Transforms**. -3. Find the transform you'd like to edit and click on **Edit definition** above the transform definition. -4. Edit the query or script. +1. Go to **Data Studio > Transforms**. +2. Find the transform you'd like to edit and click on **Edit definition** above the transform definition. +3. Edit the query or script. See [query-based transforms](query-transforms) and [Python transforms](python-transforms) for more information. You can [use Metabot](#use-metabot-to-generate-code-for-transforms) to help edit your transform. @@ -175,11 +195,11 @@ To edit transform's target table, i.e., the table where the query results are wr You can run a transform manually or schedule the transform using tags and jobs. -Running a transform for the first time will create and sync the table created by the transform, and you'll be able to edit the table's [metadata](../../data-modeling/metadata-editing) and [permissions](../../permissions/data). Subsequent runs will drop and recreate the table, unless you use [Incremental transforms](#incremental-transforms). +- To run a transform manually, visit the transform in **Data Studio > Transforms > Runs** and click **Run**. -To run a transform manually, visit the transform in **Data Studio > Transforms > Runs** and click **Run**. +- To schedule a transform, you'll need to assign one or more tags to it, then create a [scheduled job](./jobs-and-runs) that picks up those tags. -To schedule a transform, you'll need to assign one or more tags to it, then create a [scheduled job](./jobs-and-runs) that picks up those tags. +Running a transform for the first time will create and sync the table created by the transform, and you'll be able to edit the table's [metadata](../../data-modeling/metadata-editing) and [permissions](../../permissions/data). Subsequent runs will drop and recreate the table, unless you use [Incremental transforms](#incremental-transforms). You can see the time and status of the latest transform run on the transform's page, or in the [Runs view](./jobs-and-runs). The time of the run is given in the system's timezone. @@ -189,6 +209,8 @@ For Python transforms, you'll also see the transform's execution logs. _Data Studio > Transforms > [transform name] > Inspect_ +> Transform inspector requires the [Advanced transforms add-on](addons) + The [transform inspector](./transform-inspector) lets you poke at the input and outputs of your transform. ## Transform dependencies @@ -207,7 +229,7 @@ On Metabase Pro or Enterprise plans, you can see the transform dependencies grap If a job includes a transform that depends on a table created by another transform, then the job will run all the tagged transforms and their dependencies, even if they lack tags, see [Jobs and runs](jobs-and-runs) for more information. -### Incremental transforms +## Incremental transforms _Data Studio > Transforms > Settings_ @@ -227,6 +249,8 @@ Incremental transforms work differently for query-based transforms and Python tr _Admin > General > Remote sync_ +{% include plans-blockquote.html feature="Versioning transforms" %} + You can check your transforms into git with [Remote Sync](../../installation-and-operation/remote-sync). If you enable transform sync, Metabase will serialize transforms as YAML files and push them to your specified GitHub repo branch. To enable git sync of transforms: @@ -248,34 +272,4 @@ Transforms are similar to models with model persistence turned on, but there are Use models to enable non-admins to create their own datasets within Metabase, and to add context like field descriptions and semantic types. Use transforms to create persisted datasets in your database and reuse them across Metabase. In future versions of Metabase, model persistence will be deprecated in favor of transforms. -## Convert models to transforms - -If you have models you'd like to migrate to transforms, Metabase can convert them for you. When you convert a model, Metabase: - -1. Creates a new transform based on the model's query. -2. Runs the transform to create the output table in your database. -3. Replaces every question, dashboard, and other item that used the model with the transform's output table. -4. Converts the original model to a question. - -You must be an admin to convert models, and the model's database must [support transforms](#databases-that-support-transforms). - -Before converting models into transforms, review [Replacing data sources](../dependencies/replace-data-sources) docs for overview and limitations of the process. - -To convert a model into a transform: - -1. Open **Data Studio** and select **Transforms** in the sidebar. -2. Click **Tools > Migrate models**. -3. Find the model you want to convert and click it to open its details panel. The panel shows the model's name, database, and collection, and a list of items that depend on it. -4. Click **Convert to a transform**. -5. Fill out the transform settings. See [Create a transform](#create-a-transform) for the overview of settings. -6. Click **Convert to a transform**. - -Metabase runs the conversion in the background. A status indicator at the bottom of the screen shows progress. - -If the transform run fails, Metabase stops and leaves the model unchanged—nothing is replaced. - -If the transform runs successfully but the source swap fails afterward, the transform and its output table are kept. The model is left unchanged. You can complete the migration manually using [Replace data sources](../dependencies/replace-data-sources) to point remaining content from the model to the transform's output table. - -Once conversion completes, all content that previously queried the model now queries the transform's output table, and the model becomes a saved question. - -Newly created tables will be created with default permissions and will _not_ inherit the model's permissions. As an alternative, consider manually creating and running the transform first, setting up the permissions, then using [Replace data sources](../dependencies/replace-data-sources) to swap the model for the transform's output table once you configured permissions. +On Metabase Pro/Enterprise plans, you can convert Metabase models to transforms in bulk, see [Convert models to transforms](query-transforms#convert-models-to-transforms) diff --git a/_docs/master/databases/writable-connection.md b/_docs/master/databases/writable-connection.md index 6c49301764..b78c7c35c6 100644 --- a/_docs/master/databases/writable-connection.md +++ b/_docs/master/databases/writable-connection.md @@ -12,9 +12,9 @@ redirect_from: - /docs/master/databases/writeable-connection --- -## Writable connection +# Writable connection -> Writable connection requires the **Advanced transforms (SQL + Python)** add-on +> Writable connection requires the [Advanced transforms add-on](../data-studio/transforms/addons) _Admin > Databases > Writable connection_ diff --git a/_docs/master/developers-guide/driver-changelog.md b/_docs/master/developers-guide/driver-changelog.md index 4d2f614a24..d5ddc572bc 100644 --- a/_docs/master/developers-guide/driver-changelog.md +++ b/_docs/master/developers-guide/driver-changelog.md @@ -11,10 +11,85 @@ layout: new-docs # Driver Interface Changelog +## Metabase 0.62.0 + +- `sql.params.substitution/field->clause`, `to-clause`, `desugar-filter-clause`, `wrap-value-literals-in-mbql`, and + `date-string->filter`, introduced in 0.61.0, have been removed; they are no longer necessary. They have been + replaced by a single method, `sql.params.substitution/->honeysql`, which compiles an MBQL 5 clause to HoneySQL with + the given options. + +- The `metabase.driver.commmon.parameters` and `metabase.driver.commmon.parameters.parse` namespaces, deprecated in + 0.57.0, have been removed. Please use the Lib implementations instead. Relevant functions are aliased in + `metabase.lib.core`, for example `metabase.lib.core/parse-parameters`, `metabase.lib.core/parsed-parameter`, and + `metabase.lib.core/parsed-parameter?`. + +- The `metabase.driver.common.parameters.dates` and `metabase.driver.common.parameters.operators` namespaces, + deprecated in 0.57.0, have been removed. Use the equivalent QP namespaces instead: + `metabase.query-processor.parameters.dates` and `metabase.query-processor.parameters.operators`, respectively. These + namespaces return MBQL 5 clauses rather than MBQL 4; use `metabase.lib.core/->legacy-MBQL` if needed until your + driver has been fully updated to MBQL 5. + +- `metabase.driver.sql.parameters.substitution/align-temporal-unit-with-param-type`, deprecated in 0.49.0, has been + removed. + +- `metabase.driver-api.core/desugar-filter-clause`, `metabase.driver-api.core/negate-filter-clause`, and + `metabase.driver-api.core/simplify-compound-filter`, deprecated in 0.57.0, have been removed; use the + `metabase.lib.core` versions instead. The new versions operate on MBQL 5 instead of MBQL 4. + +- Added `metabase.driver.sql/table-qualification-style` multimethod. Returns one of + `:table-qualification-style/{table,schema-table,db-table,db-schema-table}` describing the per-driver + SQL identifier shape. Used by workspace table remapping + (`metabase-enterprise.workspaces.core/engine-namespace-positions`) to decide tuple shape when + storing `:model/TableRemapping` rows and matching AST positions during query rewriting. Defaults + to `:table-qualification-style/schema-table` -- the common case, so Postgres/Redshift/H2/ClickHouse + need no override. Drivers that emit `db.table` (MySQL) override to + `:table-qualification-style/db-table`; drivers that emit `db.schema.table` (SQL Server, BigQuery) + override to `:table-qualification-style/db-schema-table`. Drivers that emit a bare `table` use + `:table-qualification-style/table`. + +- Added `metabase.driver.sql/db-slot-value` multimethod. Returns the `:db` AST slot string (catalog, + project id, etc.) for a `Database` row. Required for `:table-qualification-style/db-table` and + `:table-qualification-style/db-schema-table` drivers; the default returns `nil`. Overridden by + MySQL and SQL Server (`(:db (:details db))`) and BigQuery (`(:project-id (:details db))`). + +- Added `metabase.driver/qualified-name-components` multimethod. Returns the ordered subset of + `#{:db :schema}` identifier positions a driver populates when referencing a table in compiled + SQL. Defaults to `[:schema]`. Drivers that emit bare table names (Mongo) override to `[]`; + MySQL overrides to `[:db]` (its "database" rides on the connection but participates as the + `:db` AST slot for cross-DB consumers); drivers that emit a 3-part `catalog.schema.table` + identifier (SQL Server, BigQuery) override to `[:db :schema]`. + ## Metabase 0.61.0 +- Added the following driver multimethods to support MBQL5 compilation migration: + - `sql.qp/compile-mbql` - Compiles an MBQL inner query to HoneySQL. + - `sql.qp/mbql-clause-with-opts` - Returns an MBQL clause in the desired MBQL format of the driver. + - `sql.qp/expression-by-name` - Gets an expression from a query or stage (`*inner-query`) by name. + - `sql.qp/aggregation-name` - Returns the name of an aggregation clause. + - `sql.qp/over-order-by->honeysql` - Returns the HoneySQL for an order by clause in the over clause of a window function. + - `sql.qp/clause-value-idx` - Returns the index of the value in a value clause. + - `sql.qp/breakout-options-index` - Returns the index of options in a breakout clause. + - `sql.params.substitution/field->clause` - Returns an MBQL field clause with the given options. + - `sql.params.substitution/to-clause` - Helper to dispatch to `params.ops/to-clause` or `qp.params.ops/to-clause`. + - `sql.params.substitution/desugar-filter-clause` - Helper to dispatch to `driver-api/desugar-filter-clause` or `lib/desugar-filter-clause`. + - `sql.params.substitution/wrap-value-literals-in-mbql` - Helper to dispatch to `driver-api/wrap-value-literals-in-mbql` or `driver-api/wrap-value-literals-in-mbql5`. + - `sql.params.substitution/date-string->filter` - Helper to dispatch to `params.dates/date-string->filter` or `qp.params.dates/date-string->filter`. + + These methods have implementations for the `:sql` and `:sql-mbql5` drivers. Concrete drivers should *not* need to + implement these methods. Drivers can opt-in to MBQL5 compilation by adding the `:sql-mbql5` driver as a parent, and updating the `sql.qp/->honeysql` + methods to handle the clause options argument as the second parameter. See the `:h2` driver in https://github.com/metabase/metabase/pull/71439 for + an example. Drivers will need to be migrated to work with MBQL5 compilation over the next three releases by v64. After v64 these methods will be deprecated + in favour of the `:sql-mbql5` implementations once all drivers have been migrated. + +- Added a `driver` parameter to `sql.qp/maybe-cast-uuid-for-text-compare`. Any drivers that call this function should + update it to pass in the `driver` parameter now. An example is in the Snowflake driver's `string-filter` function. + - `driver/field-reference-mlv2`, deprecated in 0.57.0, has now been removed. +- `metabase.driver.sql/set-role-statement` has been deprecated in favor of + `metabase.driver.sql-jdbc/set-role-statement`, which takes an additional `java.sql.Connection` parameter, so you use + the connection to call `quote_ident()` or similar for identifier quoting/escaping purposes. + ## Metabase 0.60.0 - Added `validate-impersonated-query` multimethod. This is used for drivers to perform validation on impersonated native queries. @@ -69,6 +144,9 @@ layout: new-docs ## Metabase 0.57.0 +- Added `metabase.driver/validate-db-details!` multimethod for rejecting connection details that are unsafe to + persist (independent of whether the database is currently reachable). The default implementation is a no-op. + - `driver/field-reference-mlv2` is now deprecated, and is no longer used. Please remove your implementations. - The key `metabase.driver-api.core/qp.add.nfc-path` is now more consistently populated; other `qp.add.*` keys no diff --git a/_docs/master/developers-guide/drivers/driver-tests.md b/_docs/master/developers-guide/drivers/driver-tests.md index 351687739d..b88ff7331a 100644 --- a/_docs/master/developers-guide/drivers/driver-tests.md +++ b/_docs/master/developers-guide/drivers/driver-tests.md @@ -235,7 +235,7 @@ be-tests-postgres-latest-ee: POSTGRES_DB: circle_test POSTGRES_HOST_AUTH_METHOD: trust steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Test Postgres driver (latest) uses: ./.github/actions/test-driver with: diff --git a/_docs/master/embedding/appearance.md b/_docs/master/embedding/appearance.md index d3b94fe769..1890d6f6e0 100644 --- a/_docs/master/embedding/appearance.md +++ b/_docs/master/embedding/appearance.md @@ -18,8 +18,12 @@ You can style your embedded [Metabase components](./components) with a **theme** ![Embed share button](./images/embed-share-button.png) -Guest embeds on OSS and Starter plans come with two theme presets - light and dark. On Metabase Pro and Enterprise plans, you can also customize individual colors, backgrounds, fonts and more. See [Advanced theming](#advanced-theming). +On OSS and Starter plans, embeds come with two theme presets: [light and dark](#dark-mode-and-light-mode). +On Pro and Enterprise plans, you can: + +- [Save reusable themes](#embedding-themes), then pick one in the embed wizard. +- Customize individual colors, backgrounds, fonts, and more in your embedding code. See [Advanced theming](#advanced-theming). ## Dark mode and light mode @@ -35,16 +39,84 @@ defineMetabaseConfig({ }); ``` +## Embedding themes + +![Embedding themes](./images/themes.png) + +{% include plans-blockquote.html feature="Saved embedding themes" is_plural=true %} + +A theme is a named set of colors and fonts that the embed wizard can copy into each new embed's config. The embed doesn't reference the theme, the embed carries its own inlined copy of the values. Changing or deleting the theme won't affect existing embeds. + +### Manage themes + +Go to **Admin settings > Embedding > Themes**. + +Metabase ships with light and dark themes that pick up any appearance settings you've set on your Metabase (though you can tinker with these default themes as well, including removing theme like you can any other custom theme). + +From the Themes tab, you can: + +- **Create a theme.** Click **+ New theme**, then set a name, colors, and font. +- **Edit a theme.** Click a theme card to open the editor. Changes show up in the live preview. +- **Choose what the preview renders.** Pick the dashboard or question used to preview the theme. +- **Duplicate a theme.** Handy if you want to vary an existing theme. +- **Delete a theme.** This deletion is eternal. + +![Theme editor](./images/theme-editor.png) + +### Apply a saved theme to a new embed + +When you create a new embed using the [embed wizard](./modular-embedding#3-customize-your-embed), the last customization step lets you pick: + +- **A saved theme** from your list of themes. +- **Instance theme** to use Metabase's instance defaults. +- **Custom** to set colors directly on this embed without saving them as a theme. + +![Embed wizard appearance](./images/embed-wizard-appearance.png) + +The theme you pick is inlined into the generated `defineMetabaseConfig({ theme: ... })` snippet. Because each embed carries its _own_ copy of the values, editing or deleting the theme in Metabase won't change the themes in embeds that have already been generated. Those embeds keep the colors and fonts they were created with. To pick up theme changes in an existing embed, regenerate the snippet from the wizard, or edit the `theme` block in your code by hand. + +### Reuse a saved theme in the SDK + +If you're using the [SDK](./sdk/introduction), pass a theme to `MetabaseProvider` with `defineMetabaseTheme`, which accepts the same theme shape that you configure in the Themes admin UI. You can copy a saved theme's values into your code: + +```tsx +import { + MetabaseProvider, + defineMetabaseTheme, +} from "@metabase/embedding-sdk-react"; + +const theme = defineMetabaseTheme({ + fontFamily: "Lato", + colors: { + brand: "#50e397", + background: "#11123d", + "text-primary": "#f9f9fc", + }, +}); + +export function App() { + return ( + + {/* your app */} + + ); +} +``` + +For the full set of available colors and component overrides, see [Theme options](#theme-options). + ## Advanced theming {% include plans-blockquote.html feature="Advanced theming modular embeds" is_plural=true %} -On Pro/Enterprise plan, you can configure granular appearance options, like background colors, font sizes etc. See the [list of all theming options](). +On Pro/Enterprise plan, you can configure granular appearance options, like background colors, font sizes etc. See the [list of all theming options](#theme-options). ### Add an advanced theme to your embed ![Behavior and appearance](./images/behavior-and-appearance.png) +If you have a [saved theme](#embedding-themes), you can pick it directly in the embed wizard. The rest of this section covers further customization on top of (or instead of) a saved theme. + Some appearance options like brand, text, and background color are configurable in the [embed wizard](./modular-embedding#create-a-new-embed). For other appearance settings, use the `theme` parameter with `preset` in the `defineMetabaseConfig()` function in your [embedding code snippet](./modular-embedding#add-the-embedding-script-to-your-app). For example: diff --git a/_docs/master/embedding/components.md b/_docs/master/embedding/components.md index e0c75ff3e9..4fce7edb90 100644 --- a/_docs/master/embedding/components.md +++ b/_docs/master/embedding/components.md @@ -53,10 +53,6 @@ If you surround your attribute value with double quotes, make sure to use single > ``` -## Resizing dashboards to fit their content - -The `` web component automatically resizes to fit its content. No additional configuration is needed. - ## Question To render a question (chart): @@ -113,6 +109,8 @@ To render the AI chat interface: ``` +If you're using the SDK, you can use either the [`MetabotQuestion`](./sdk/ai-chat#example) component or the [`useMetabot`](./sdk/ai-chat#building-custom-ai-chat-uis-with-usemetabot) hook for a custom UI. + ### Attributes {% include_file "{{ dirname }}/eajs/snippets/MetabaseMetabotAttributes.md" snippet="properties" %} diff --git a/_docs/master/embedding/eajs/snippets/MetabaseDashboardAttributes.md b/_docs/master/embedding/eajs/snippets/MetabaseDashboardAttributes.md index 4620b84fa7..aa8cfc2b75 100644 --- a/_docs/master/embedding/eajs/snippets/MetabaseDashboardAttributes.md +++ b/_docs/master/embedding/eajs/snippets/MetabaseDashboardAttributes.md @@ -18,18 +18,19 @@ or `token` (for guest embeds), plus optional display configuration. -| Property | Type | Description | -| :--------------------------------------------------------------- | :------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `auto-refresh-interval` | `number` | Auto-refresh interval in seconds. For example, `60` refreshes the dashboard every 60 seconds.
---
Optional
Available in Pro/Enterprise and Guest embed. | -| `custom-context` | `string` | Optional custom context string passed through to the guest token endpoint.
---
Optional
Available in Guest embed. | -| `dashboard-id` | `string` \| `number` | The ID of the dashboard to embed. Can be a regular ID or an [entity ID](/docs/latest/installation-and-operation/serialization#entity-ids-work-with-embedding). Only for SSO embeds — guest embeds set the ID with `token`. | -| `drills` | `boolean` | Whether to enable drill-through on the dashboard.
---
Optional
Default: `true`
Available in Pro/Enterprise. | -| `enable-entity-navigation` | `boolean` | Whether to enable internal entity navigation (links to dashboards/questions). Requires `drills` to be `true`
---
Optional
Default: `false`
Available in Pro/Enterprise. | -| `hidden-parameters` | `string`[] | List of filter names to hide from the dashboard, e.g. `['productId']`.
---
Optional
Available in Pro/Enterprise. | -| `initial-parameters` | `object` | Default values for dashboard filters, e.g. `{ 'productId': '42' }`.
---
Optional
Available in Pro/Enterprise and Guest embed. | -| `token` | `string` | The token for guest embeds. Set automatically by the guest embed flow.
---
Optional
Available in Guest embed. | -| `with-downloads` | `boolean` | Whether to show the button to download the dashboard as PDF and download question results.
---
Optional
Default: `true` on OSS/Starter, `false` on Pro/Enterprise
Available in Guest embed. | -| `with-subscriptions` | `boolean` | Whether to let people set up [dashboard subscriptions](/docs/latest/dashboards/subscriptions). Subscriptions sent from embedded dashboards exclude links to Metabase items.
---
Optional
Available in Pro/Enterprise. | -| `with-title` | `boolean` | Whether to show the dashboard title in the embed.
---
Optional
Default: `true`
Available in Guest embed. | +| Property | Type | Description | +| :--------------------------------------------------------------- | :------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `auto-refresh-interval` | `number` | Auto-refresh interval in seconds. For example, `60` refreshes the dashboard every 60 seconds.
---
Optional
Available in Pro/Enterprise and Guest embed. | +| `custom-context` | `string` | Optional custom context string passed through to the guest token endpoint.
---
Optional
Available in Guest embed. | +| `dashboard-id` | `string` \| `number` | The ID of the dashboard to embed. Can be a regular ID or an [entity ID](/docs/latest/installation-and-operation/serialization#entity-ids-work-with-embedding). Only for SSO embeds — guest embeds set the ID with `token`. | +| `drills` | `boolean` | Whether to enable drill-through on the dashboard.
---
Optional
Default: `true`
Available in Pro/Enterprise. | +| `enable-entity-navigation` | `boolean` | Whether to enable internal entity navigation (links to dashboards/questions). Requires `drills` to be `true`
---
Optional
Default: `false`
Available in Pro/Enterprise. | +| `hidden-parameters` | `string`[] | List of filter names to hide from the dashboard, e.g. `['productId']`.
---
Optional
Available in Pro/Enterprise. | +| `initial-parameters` | `object` | Default values for dashboard filters, e.g. `{ 'productId': '42' }`.
---
Optional
Available in Pro/Enterprise and Guest embed. | +| `parameters` | `object` | Controlled dashboard filters values, e.g. `{ 'productId': '42' }`. Setting this attribute supersedes `initial-parameters` as the seed and stays in sync with subsequent mutations. Pair with the `parameters-change` DOM event to track edits.
---
Optional
Available in Pro/Enterprise and Guest embed. | +| `token` | `string` | The token for guest embeds. Set automatically by the guest embed flow.
---
Optional
Available in Guest embed. | +| `with-downloads` | `boolean` | Whether to show the button to download the dashboard as PDF and download question results.
---
Optional
Default: `true` on OSS/Starter, `false` on Pro/Enterprise
Available in Guest embed. | +| `with-subscriptions` | `boolean` | Whether to let people set up [dashboard subscriptions](/docs/latest/dashboards/subscriptions). Subscriptions sent from embedded dashboards exclude links to Metabase items.
---
Optional
Available in Pro/Enterprise. | +| `with-title` | `boolean` | Whether to show the dashboard title in the embed.
---
Optional
Default: `true`
Available in Guest embed. | diff --git a/_docs/master/embedding/eajs/snippets/MetabaseQuestionAttributes.md b/_docs/master/embedding/eajs/snippets/MetabaseQuestionAttributes.md index be2a3b0c9c..f20760027e 100644 --- a/_docs/master/embedding/eajs/snippets/MetabaseQuestionAttributes.md +++ b/_docs/master/embedding/eajs/snippets/MetabaseQuestionAttributes.md @@ -29,6 +29,7 @@ Use `question-id="new-native"` to embed the SQL editor interface. | `initial-sql-parameters` | `object` | Default values for SQL parameters, only applicable to native SQL questions, e.g. `{ "productId": "42" }`.
---
Optional
Available in Pro/Enterprise and Guest embed. | | `is-save-enabled` | `boolean` | Whether the save button is enabled.
---
Optional
Default: `false`
Available in Pro/Enterprise. | | `question-id` | `string` \| `number` | The ID of the question to embed. Can be a regular ID or an [entity ID](/docs/latest/installation-and-operation/serialization#entity-ids-work-with-embedding). Use `"new"` to embed the query builder, or `"new-native"` to embed the SQL editor. Only for SSO embeds — guest embeds use `token`. | +| `sql-parameters` | `object` | Controlled SQL parameter values, e.g. `{ "productId": "42" }`. Setting this attribute supersedes `initial-sql-parameters` as the seed and stays in sync with subsequent mutations. Pair with the `sql-parameters-change` DOM event to track edits.
---
Optional
Available in Pro/Enterprise and Guest embed. | | `target-collection` | `string` \| `number` | The collection to save a question to. Values: regular ID, entity ID, `"personal"`, `"root"`.
---
Optional
Available in Pro/Enterprise. | | `token` | `string` | The token for guest embeds. Set automatically by the guest embed flow.
---
Optional
Available in Guest embed. | | `with-alerts` | `boolean` | Whether to show the alerts button.
---
Optional
Default: `false`
Available in Pro/Enterprise. | diff --git a/_docs/master/embedding/full-app-embedding-quick-start-guide.md b/_docs/master/embedding/full-app-embedding-quick-start-guide.md index 52b7ad076e..4503e51e93 100644 --- a/_docs/master/embedding/full-app-embedding-quick-start-guide.md +++ b/_docs/master/embedding/full-app-embedding-quick-start-guide.md @@ -19,8 +19,6 @@ redirect_from: You'll embed the full Metabase application in your app. Once logged in, people can view a Metabase dashboard in your web app, and be able to use the full Metabase application to explore their data, and only their data. -{% include shared/in-page-promo-embedding-workshop.html %} - ## Prerequisites {% include plans-blockquote.html feature="Full app embedding" convert_pro_link_to_embedding=true%} diff --git a/_docs/master/embedding/full-app-embedding.md b/_docs/master/embedding/full-app-embedding.md index 4e4e692950..09a5b338fa 100644 --- a/_docs/master/embedding/full-app-embedding.md +++ b/_docs/master/embedding/full-app-embedding.md @@ -17,8 +17,6 @@ redirect_from: {% include plans-blockquote.html feature="Full app embedding" convert_pro_link_to_embedding=true %} -{% include shared/in-page-promo-embedding-workshop.html %} - **Full app embedding** lets you embed the entire Metabase app in an iframe. Full app embedding integrates your [permissions](../permissions/introduction) and [SSO](../people-and-groups/start#authentication) to give people the right level of access to [query](../questions/query-builder/editor) and [drill-down](/learn/metabase-basics/querying-and-dashboards/questions/drill-through) into your data. > If you are just starting out with Metabase embedding, consider using [Modular embedding](./modular-embedding) instead of full app embedding - it's an improved, more customizable option for embedding individual Metabase components. @@ -174,8 +172,6 @@ To manually log someone out of Metabase, load the following URL (for example, in https://metabase.yourcompany.com/auth/logout ``` -If you're using [JWT](../people-and-groups/authenticating-with-jwt) for SSO, we recommend setting the `exp` (expiration time) property to a short duration (e.g., 1 minute). - ## Supported postMessage messages _from_ embedded Metabase To keep up with changes to an embedded Metabase URL (for example, when a filter is applied), set up your app to listen for "location" messages from the embedded Metabase. If you want to use this message for deep-linking, note that "location" mirrors "window.location". diff --git a/_docs/master/embedding/guest-embedding.md b/_docs/master/embedding/guest-embedding.md index ff78c72c45..d4f3e66a34 100644 --- a/_docs/master/embedding/guest-embedding.md +++ b/_docs/master/embedding/guest-embedding.md @@ -12,8 +12,6 @@ summary: 'Embed questions, dashboards, and documents without requiring SSO.' # Guest embeds -{% include shared/in-page-promo-embedding-workshop.html %} - Guest embeds are a way to embed basic Metabase components in your app without requiring you to create a Metabase account for each person viewing the charts and dashboards. But not logging people in to your Metabase has some major tradeoffs: see [limitations](#guest-embed-limitations). "Guest" refers to the authentication approach: Metabase doesn't create a session for each person. Authentication has nothing to do with data freshness. Dashboards and charts in guest embeds always show live data from your database. @@ -62,6 +60,9 @@ Add the embed script and configuration to your HTML: window.metabaseConfig = { isGuest: true, instanceUrl: "YOUR_METABASE_URL", + // Optional. Set this if you want the embed to fetch a fresh JWT + // when the current one expires. See "Refreshing the JWT" below. + // guestEmbedProviderUri: "/your/apps/endpoint", }; ``` @@ -107,12 +108,15 @@ Replace `YOUR_METABASE_SECRET_KEY` with your [embedding secret key](#regeneratin You can set different attributes to enable/disable UI. Here are some example attributes: -| Attribute | Description | -| -------------------- | --------------------------------------------------------------------- | -| `token` | Required. The signed JWT token from your server. | -| `with-title` | Show or hide the title. Values: `"true"` or `"false"`. | -| `with-downloads`\* | Enable or disable downloads. Values: `"true"` or `"false"`. | -| `initial-parameters` | JSON string of parameter values. Example: `'{"category":["Gizmo"]}'`. | +| Attribute | Description | +| ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `token` | Required. The signed JWT token from your server. | +| `with-title` | Show or hide the title. Values: `"true"` or `"false"`. | +| `with-downloads`\* | Enable or disable downloads. Values: `"true"` or `"false"`. | +| `initial-parameters` | JSON string of initial parameter values (uncontrolled). Example: `'{"category":["Gizmo"]}'`. See [Modular embedding parameters](./parameters#pass-parameter-values-to-embedded-components). | +| `parameters` | JSON string of parameter values (controlled). Example: `'{"category":["Gizmo"]}'`. See [Modular embedding parameters](./parameters#pass-parameter-values-to-embedded-components). | +| `auto-refresh-interval` | Dashboards only. Auto-refresh interval in seconds. | +| `custom-context` | Forwarded to your [`guestEmbedProviderUri`](#refreshing-or-initializing-the-jwt-from-your-server) endpoint as `customContext`. Either a string (e.g., `"gadgets-tab"`), or a JSON-stringified object like `initial-parameters` (e.g., `'{"tab":"gadgets","region":"us-east"}'`). | \* Disabling downloads is only available on [Pro](/product/pro) and [Enterprise](/product/enterprise) plans. @@ -194,6 +198,8 @@ Fetch the JWT token from your backend and programmatically pass it to the 'metab
``` +See [Modular embedding parameters](./parameters#pass-parameter-values-to-embedded-components) for controlled parameters documentation. + ### Locked parameters Locked parameters let you filter data without exposing the filter to the end-user. Locking parameters is useful for restricting data based on who's viewing the embed (for example, showing each customer only their own data). @@ -259,7 +265,7 @@ Things to keep in mind if you need to make changes to your locked parameters. ### Include all locked parameters in your JWT -Once you publish a question or dashboard with a locked parameter, you _must_ include the name of the locked parameter in the `params` object when you sign the JWT. If you leave the parameter out, Metabase will refuse the request and log: `You must specify a value for :parameter in the JWT`. +Once you publish a question or dashboard with a locked parameter, you _must_ include the name of the locked parameter in the `params` object when you sign the JWT. If you leave the parameter out, Metabase will refuse the request and log: `You must specify a value for : in the JWT`. For example, if your locked parameter is `category`, the error will read `You must specify a value for :category in the JWT`. ### Pass an empty array to turn off a locked parameter @@ -309,6 +315,146 @@ Because Metabase doesn't render locked parameters as filter widgets, you can use When the end-user changes a value in your custom widget, re-sign a new JWT on your server with the updated `params` and swap it onto the web component's `token` attribute. The embed will re-request the data with the new locked value. +## Refreshing or initializing the JWT from your server + +JWTs that you sign for guest embeds have an expiration (`exp`). Once a token expires, the embed can't load fresh data, and any filter selections the viewer made will reset on the next request. To keep the embed alive without reloading the page, you can configure a guest token endpoint on your server to hand out fresh JWTs on demand. + +The endpoint can serve two flows: + +- **Refreshing tokens**: when the embed's current JWT is about to expire, the embed POSTs to your endpoint to get the new JWT, and swaps it in. +- **Initializing with a token** (optional): if you don't want to pre-render a JWT in the HTML at all, the embed can call the same endpoint on load to fetch that first JWT. + +### Setting the endpoint URL in the guest embed + +Add `guestEmbedProviderUri` to your `metabaseConfig`. The value is a path (or full URL) to an endpoint in your app: + +```html + +``` + +When the embed needs a token, it sends a `POST` request to `guestEmbedProviderUri` with a JSON body, which includes cookies, so you can authenticate the request with your app's existing session. + +Request: + +```json +{ + "entityType": "dashboard", + "entityId": 10, + "customContext": "..." +} +``` + +| Field | Description | +| --------------- | ------------------------------------------------------------------------- | +| `entityType` | `"dashboard"` or `"question"`. | +| `entityId` | The ID of the dashboard or question being embedded. | +| `customContext` | Optional. The string or object you set on the `custom-context` attribute. | + +Response: a JSON object with a single `jwt` field: + +```json +{ "jwt": "YOUR_NEWLY_SIGNED_JWT" } +``` + +### Refresh flow + +Pre-render an initial JWT on the component (just like a regular guest embed) and configure `guestEmbedProviderUri`. When the JWT expires, the embed will call your endpoint to get a fresh one and swap it in. + +```html + + + +``` + +### Initialize the embed without a JWT in the HTML + +If you don't want to render the JWT in the HTML at all, omit the `token` attribute and use `dashboard-id` (or `question-id`) instead. If you've set the `guestEmbedProviderUri`, then the embed will call that endpoint on load to fetch the first JWT. + +```html + +``` + +This way you can keep all your token-issuing logic in one place on your server. + +### Example endpoint (Node.js / Express) + +```javascript +const jwt = require("jsonwebtoken"); +const METABASE_SECRET_KEY = "YOUR_METABASE_SECRET_KEY"; + +app.post("/api/metabase-guest-token", (req, res) => { + // Authenticate using your app's existing session. + const user = req.session?.user; + if (!user) { + return res.status(403).json({ error: "Not signed in" }); + } + + const { entityType, entityId, customContext } = req.body; + + const payload = { + resource: { [entityType]: entityId }, + params: paramsFor(user, customContext), + exp: Math.round(Date.now() / 1000) + 10 * 60, // 10 minute expiration + }; + + res.json({ jwt: jwt.sign(payload, METABASE_SECRET_KEY) }); +}); +``` + +Because the embed's request includes your app's session cookie, your endpoint can: + +- Refuse to issue a JWT (with a `403`) for visitors who aren't signed in to your app. +- Compute different `params` (i.e., locked filter values) per visitor. + +### Sending custom context + +When you embed the same dashboard or question more than once on a page, you can use the `custom-context` attribute to tell your endpoint which copy is requesting a token. The value you pass is forwarded to your endpoint as `customContext`. + +For example, two copies of the same dashboard scoped to different categories: + +```html + +``` + +You can also pass a JSON-stringified object (the embed parses it before forwarding it on, so your endpoint receives a real object): + +```html + +``` + +Your endpoint can switch on `customContext` to set different locked parameters, like so: + +```javascript +function paramsFor(user, customContext) { + switch (customContext) { + case "gadgets-tab": + return { category: ["Gadget"] }; + case "doohickeys-tab": + return { category: ["Doohickey"] }; + default: + return {}; + } +} +``` + ## Disabling embedding for a question or dashboard 1. Visit the embeddable question or dashboard. @@ -366,6 +512,7 @@ When a visitor views your page: 2. The web component sends the token to Metabase. 3. Metabase verifies the JWT signature using your secret key. 4. If valid, Metabase returns the embedded content. +5. If you've configured [JWT refresh](#refreshing-or-initializing-the-jwt-from-your-server), the embed will fetch a fresh JWT from your endpoint when it next needs to make a data request after the current token has expired — not on a background timer. An idle embed makes no refresh requests. (Optionally, the embed can also fetch the very first JWT from your endpoint on load.) The embed keeps working without a page reload. For interactive filters, you can pass initial parameter values via the `initial-parameters` attribute. When a visitor changes a filter, the web component handles the update automatically. diff --git a/_docs/master/embedding/images/ai-chat-dedicated-chart.png b/_docs/master/embedding/images/ai-chat-dedicated-chart.png new file mode 100644 index 0000000000..546056b196 Binary files /dev/null and b/_docs/master/embedding/images/ai-chat-dedicated-chart.png differ diff --git a/_docs/master/embedding/images/ai-chat-inline-chart.png b/_docs/master/embedding/images/ai-chat-inline-chart.png new file mode 100644 index 0000000000..c08e289540 Binary files /dev/null and b/_docs/master/embedding/images/ai-chat-inline-chart.png differ diff --git a/_docs/master/embedding/images/embed-wizard-appearance.png b/_docs/master/embedding/images/embed-wizard-appearance.png new file mode 100644 index 0000000000..412779cce5 Binary files /dev/null and b/_docs/master/embedding/images/embed-wizard-appearance.png differ diff --git a/_docs/master/embedding/images/theme-editor.png b/_docs/master/embedding/images/theme-editor.png new file mode 100644 index 0000000000..5dda4d4292 Binary files /dev/null and b/_docs/master/embedding/images/theme-editor.png differ diff --git a/_docs/master/embedding/images/themes.png b/_docs/master/embedding/images/themes.png new file mode 100644 index 0000000000..e193a4442d Binary files /dev/null and b/_docs/master/embedding/images/themes.png differ diff --git a/_docs/master/embedding/introduction.md b/_docs/master/embedding/introduction.md index 4449376b48..8f4a8853e6 100644 --- a/_docs/master/embedding/introduction.md +++ b/_docs/master/embedding/introduction.md @@ -14,8 +14,6 @@ redirect_from: # Embedding introduction -{% include shared/in-page-promo-embedding-workshop.html %} - You can embed Metabase tables, charts, and dashboards—even Metabase's query builder—in your website or application. Here are the different ways you can embed Metabase: - [Modular embedding](#modular-embedding) @@ -103,6 +101,12 @@ The modular embeds that you can set up in the [in-app wizard](./modular-embeddin If you're using an AI agent to help you embed Metabase in your app, check out [AI agent resources](./ai-agent-resources). +## Tracking embed usage + +{% include plans-blockquote.html feature="Tracking embed usage" %} + +[Usage Analytics](../usage-and-performance-tools/usage-analytics) tracks embed usage, including embedding context, authentication methods, hostname, and other metadata. Check out the [Embedding usage dashboard](../usage-and-performance-tools/usage-analytics-reference#embedding-usage). + ## Further reading - [Strategies for delivering customer-facing analytics](/learn/metabase-basics/embedding/overview). diff --git a/_docs/master/embedding/modular-embedding.md b/_docs/master/embedding/modular-embedding.md index 0ee2750871..7c4faeb071 100644 --- a/_docs/master/embedding/modular-embedding.md +++ b/_docs/master/embedding/modular-embedding.md @@ -14,8 +14,6 @@ redirect_from: # Modular embedding -{% include shared/in-page-promo-embedding-workshop.html %} - ![Modular embedding wizard](./images/modular-embedding-wizard.png) Modular embedding lets you embed and customize Metabase [components](./components) (like dashboards, the query builder, AI chat, and more) into your own application. You don't need to write embedding code on your own - just use the wizard to create a code snippet and paste it into your app. @@ -70,7 +68,13 @@ The exact customization options you see will depend on what type of entity you'r ![Embed flow options for AI chat](./images/embed-flow-options.png) -If you are on Metabase OSS/Starter plans, you'll be able to select light or dark themes for your components. On Metabase Pro/Enterprise, you'll also be able to pick specific colors for brand, text, and background in the embed wizard, and add more customization options through [appearance settings](./appearance) later. +If you're on Metabase OSS/Starter plans, you can select light or dark themes for your components. + +On Metabase Pro/Enterprise, you can also: + +- Pick a [saved theme](./appearance#embedding-themes) you've created in **Admin settings > Embedding > Themes**. +- Pick specific colors for brand, text, and background in the embed wizard. +- Add more [advanced theme options](./appearance#advanced-theming) by editing the generated snippet later. All the customization options you select in this wizard will be reflected in the code snippet that the embed wizard will generate for you, and you'll be able to add more options later. @@ -179,6 +183,10 @@ When you're creating a new embed using **Admin > Embedding > Setup guide > Embed - **Allow alerts**: lets people set up [alerts](../questions/alerts) on embedded questions. Requires [email setup](../configuring-metabase/email). Only for authenticated (SSO) question embeds. +## Pass parameter values to embedded components + +See [Modular embedding parameters](./parameters#pass-parameter-values-to-embedded-components). + ## Page-level config To define the configuration that applies to every embed on the page, use the `defineMetabaseConfig()` function. Its parameters include: diff --git a/_docs/master/embedding/parameters.md b/_docs/master/embedding/parameters.md new file mode 100644 index 0000000000..9e8a1d5bd8 --- /dev/null +++ b/_docs/master/embedding/parameters.md @@ -0,0 +1,182 @@ +--- +version: master +has_magic_breadcrumbs: true +show_category_breadcrumb: true +show_title_breadcrumb: true +category: Embedding +title: 'Modular embedding parameters' +source_url: 'https://github.com/metabase/metabase/blob/master/docs/embedding/parameters.md' +layout: new-docs +summary: 'Pass parameter values to embedded dashboards and SQL questions in modular embedding (React SDK and web components).' +--- + +# Modular embedding parameters + +This page covers how to pass parameter values to embedded dashboards and SQL questions. + +## Modular embedding SDK (React) + +### Pass parameter values to a dashboard + +You can set initial values for embeds (uncontrolled), and optionally keep your app in sync with values as people change them (controlled). You can pick either `initialParameters` and `parameters`, but don't combine them. + +#### `initialParameters` (uncontrolled) + +Set the filter values once on load. Your app won't know when people change filters in the dashboard. Pick this when you don't need to track those changes. + +```typescript +{% include_file "{{ dirname }}/snippets/parameters/dashboards/initial-parameters.tsx" snippet="example" %} +``` + +See [How parameter values are resolved](#how-parameter-values-are-resolved) for null / missing-slug semantics. + +#### `parameters` + `onParametersChange` (controlled) + +Push values from your app, and observe every applied change via `onParametersChange`. This works like a controlled ``. Your app holds the source of truth, the dashboard re-renders when the prop changes, and you receive a callback whenever applied values change. + +```typescript +{% include_file "{{ dirname }}/snippets/parameters/dashboards/controlled-parameters.tsx" snippet="example-controlled" %} +``` + +`onParametersChange` receives the [dashboard parameter change payload](#dashboard-parameter-change-payload). + + +> Don't combine `initialParameters` and `parameters` - pick one. For controlled behavior, only use `parameters`. + +### Pass parameters to SQL questions + +You can pass [parameter](../questions/native-editor/sql-parameters) values to SQL questions in the format `{parameter_name: parameter_value}`. You can set initial values for embeds (uncontrolled), and optionally keep your app in sync with values as people change them (controlled). + +These props only work with SQL questions, not query-builder questions. + +#### `initialSqlParameters` (uncontrolled) + +Set the parameter values once on load. Your app won't know when people change parameters in the question. Pick this when you don't need to track those changes. + +```typescript +{% include_file "{{ dirname }}/snippets/parameters/questions/initial-sql-parameters.tsx" snippet="example" %} +``` + +See [How parameter values are resolved](#how-parameter-values-are-resolved) for null / missing-slug semantics. + +#### `sqlParameters` + `onSqlParametersChange` (controlled) + +Push values from your app, and observe every applied change via `onSqlParametersChange`. This works like a controlled `` - your app holds the source of truth, the question re-renders when the prop changes, and you receive a callback whenever applied values change. + +```typescript +{% include_file "{{ dirname }}/snippets/parameters/questions/controlled-sql-parameters.tsx" snippet="example-controlled" %} +``` + +`onSqlParametersChange` receives the [SQL question parameter change payload](#sql-question-parameter-change-payload). + +## Modular embedding (web components) + +### Pass parameter values to embedded components + +You can set dashboard filters and SQL parameters from your page, push new values at runtime, and listen for applied changes. + +#### Seed values once with `initial-parameters` / `initial-sql-parameters` + +Set values on mount via attributes. The component reads them once on load and ignores any subsequent changes to the attribute. User widget edits are not reflected back to your page. + +```html + + + +``` + +Attributes carry JSON. Pass an object whose keys are parameter slugs (dashboards) or SQL variable names (questions). See [How parameter values are resolved](#how-parameter-values-are-resolved) for null / missing-slug semantics. + +#### Push values at runtime with `parameters` / `sqlParameters` + +For controlled behavior, set the JS property on the element instead of the attribute. The component re-renders to apply the new values. + +```html + + + +``` + +The same pattern works for `metabase-question` via the `sqlParameters` property. + +To switch a component back to uncontrolled mode (leaving the last applied values in place), set the property to `undefined`. + +#### Clearing parameters + +To clear a single parameter, set its value to `null`. This strictly clears the parameter and ignores its default value. + +```html + +``` + +To clear every parameter, assign an empty object `{}`. + +```html + +``` + +#### Observe applied changes with `parameters-change` / `sql-parameters-change` + +Listen for events to keep your page in sync with what's actually applied: + +```html + + + +``` + +The `event.detail` carries the [dashboard parameter change payload](#dashboard-parameter-change-payload). + +For SQL questions, listen for `sql-parameters-change` on ``. Its `event.detail` carries the [SQL question parameter change payload](#sql-question-parameter-change-payload). + +## How parameter values are resolved + +These rules apply to all four props — `initialParameters` / `parameters` (dashboards) and `initialSqlParameters` / `sqlParameters` (SQL questions) — and to the matching web component attributes (`initial-parameters`, `parameters`, etc.). For each parameter slug: + +- **Set a value**: Pass a `string` for a single-option filter, and an array of `string`s for multi-option filters. +- **Clear a value:** Set to `null`: the parameter is cleared and its default is not used. +- **Reset to the default value**: Omit a value (or set to `undefined`) and the embed will fall back to the parameter's default (or `null` if it has no default). + +## Dashboard parameter change payload + +Delivered to `onParametersChange` (SDK) and as `event.detail` for the `parameters-change` event (web components). + +{% include_file "{{ dirname }}/sdk/api/snippets/ParameterChangePayload.md" snippet="properties" %} + +`source` indicates why the callback fired: + +{% include_file "{{ dirname }}/sdk/api/snippets/ParameterChangeSource.md" %} + +## SQL question parameter change payload + +Delivered to `onSqlParametersChange` (SDK) and as `event.detail` for the `sql-parameters-change` event (web components). + +{% include_file "{{ dirname }}/sdk/api/snippets/SqlParameterChangePayload.md" snippet="properties" %} + +`source` indicates why the callback fired: + +{% include_file "{{ dirname }}/sdk/api/snippets/SqlParameterChangeSource.md" %} diff --git a/_docs/master/embedding/sdk/ai-chat.md b/_docs/master/embedding/sdk/ai-chat.md index 6154e151ed..b95a2a2176 100644 --- a/_docs/master/embedding/sdk/ai-chat.md +++ b/_docs/master/embedding/sdk/ai-chat.md @@ -63,3 +63,33 @@ Use the `layout` prop to specify which layout to use for the Metabot component: - `auto` (default): Metabot uses the `stacked` layout on mobile screens, and a `sidebar` layout on larger screens. - `stacked`: the question visualization stacks on top of the chat interface. - `sidebar`: the question visualization appears to the left of the chat interface, which is on a sidebar on the right. + +## Building custom AI chat UIs with `useMetabot` + +If `MetabotQuestion`'s built-in layouts don't fit your app, use the `useMetabot` hook to read Metabot's conversation state directly and render your own UI. The hook gives you the messages, the chart the agent most recently produced, processing and error state, and actions to submit, cancel, retry, or reset the conversation. + +### AI chat with inline charts + +![AI chat inline charts](../images/ai-chat-inline-chart.png) + +When an agent responds, the message can contain a `Chart` component. You can walk the agent's messages and render charts inline alongside the chat transcript: + +```typescript +{% include_file "{{ dirname }}/snippets/questions/use-metabot-inline-charts.tsx" %} +``` + +### AI chat with dedicated chart panel + +![AI chat dedicated chart](../images/ai-chat-dedicated-chart.png) + +The `CurrentChart` component is bound to the latest chart the agent produced. Render `CurrentChart` once, and it will swap in new charts as the agent creates them. You'll want to filter chart messages out of the transcript so they don't render twice: + +```typescript +{% include_file "{{ dirname }}/snippets/questions/use-metabot-dedicated-chart.tsx" %} +``` + +### Notes on `useMetabot` + +- **Guard against null while waiting for the SDK bundle**: `useMetabot` returns `null` until the SDK bundle has loaded and `` has mounted. Always guard before use. If you don't guard it, the first render will throw `Cannot read properties of null` when you reach for `metabot.messages`, `metabot.submitMessage`, etc., because the SDK ships its Metabot internals via a code-split chunk that isn't available synchronously. +- **Bring your own Markdown renderer**: `MetabotQuestion` renders agent text messages internally, including markdown formatting, transcript scrolling, and input styling. The `useMetabot` hook hands you the raw conversation state, which means you own the rendering. In particular, agent text messages (`message.type === 'text'`) contain **markdown**: links, bold, lists, inline code. The snippets above render `message.message` as plain text for brevity, but production usage should pass the text through a markdown renderer (`react-markdown`, `markdown-to-jsx`, or your own) so links and formatting display correctly. +- **Strip links returned by the agent**: the agent text may include links pointing back to the host Metabase (like a link to a chart it created). Those links require an authenticated Metabase session, so people won't be able to view the links. diff --git a/_docs/master/embedding/sdk/api/CreateQuestion.html b/_docs/master/embedding/sdk/api/CreateQuestion.html index 6589b81e54..b5caf116eb 100644 --- a/_docs/master/embedding/sdk/api/CreateQuestion.html +++ b/_docs/master/embedding/sdk/api/CreateQuestion.html @@ -14,19 +14,44 @@
  • OptionalentityTypes?: EmbeddingEntityType[]

    An array that specifies which entity types are available in the data picker

  • Optionalheight?: Height<string | number>

    A number or string specifying a CSS size value that specifies the height of the component

  • OptionalhiddenParameters?: string[]

    A list of parameters to hide.

    -
  • OptionalinitialSqlParameters?: SqlParameterValues

    Initial values for the SQL parameters.

    +
  • OptionalinitialCollection?: SdkCollectionId

    The collection to preselect in the save modal's collection picker. Unlike targetCollection, the picker remains visible and the user can choose a different collection. Ignored when targetCollection is set.

    +
  • OptionalinitialSqlParameters?: SqlParameterValues

    Initial values for SQL parameters, slug-keyed. Applied once on mount; user widget edits afterwards are not reflected back to the host. +
    +For each parameter: +

    +
      +
    • set to a value: that value is applied. +
    • +
    • set to null: strictly cleared, ignoring the parameter's default. +
    • +
    • omitted (or set to undefined): falls back to the parameter's default (or null if it has no default).
    • +
  • OptionalisSaveEnabled?: boolean

    Whether to show the save button.

  • OptionalonBeforeSave?: (
        question: MetabaseQuestion | undefined,
        context: { isNewQuestion: boolean },
    ) => Promise<void>

    A callback function that triggers before saving. Only relevant when isSaveEnabled = true

  • OptionalonNavigateBack?: () => void

    A callback function that triggers when a user clicks the back button.

  • OptionalonRun?: (question: MetabaseQuestion | undefined) => void

    A callback function that triggers when a question is updated, including when a user clicks the Visualize button in the question editor

  • OptionalonSave?: (
        question: MetabaseQuestion,
        context: { dashboardTabId?: number; isNewQuestion: boolean },
    ) => void

    A callback function that triggers when a user saves the question. Only relevant when isSaveEnabled = true

    +
  • OptionalonSqlParametersChange?: (payload: SqlParameterChangePayload) => void

    Fires on SQL parameters change. The payload's source distinguishes the initial state on load ('initial-state'), user edits in the UI ('manual-change'), and auto-updates ('auto-change').

  • OptionalonVisualizationChange?: (
        display:
            | "object"
            | "table"
            | "bar"
            | "line"
            | "pie"
            | "scalar"
            | "row"
            | "area"
            | "combo"
            | "pivot"
            | "smartscalar"
            | "gauge"
            | "progress"
            | "funnel"
            | "map"
            | "scatter"
            | "boxplot"
            | "waterfall"
            | "sankey"
            | "list",
    ) => void

    A callback function that triggers when the visualization type changes.

    -
  • Optionalplugins?: MetabasePluginsConfig
  • Optionalstyle?: CSSProperties

    A custom style object to be added to the root element.

    +
  • Optionalplugins?: MetabasePluginsConfig
  • OptionalsqlParameters?: SqlParameterValues

    Controlled SQL parameter values, slug-keyed. On every render, this object replaces the question's parameter values: +

    +
      +
    • a parameter set to a value uses that value. +
    • +
    • a parameter set to null is cleared, even if it has a default. +
    • +
    • a parameter omitted from the object (or set to undefined) uses its default (or null if it has no default). +
      +
      +Pair with onSqlParametersChange to stay in sync with user edits.
    • +
    +
  • Optionalstyle?: CSSProperties

    A custom style object to be added to the root element.

  • OptionaltargetCollection?: SdkCollectionId

    The collection to save the question to. This will hide the collection picker from the save modal. Only applicable to interactive questions.

  • Optionaltitle?: SdkQuestionTitleProps

    Determines whether the question title is displayed, and allows a custom title to be displayed instead of the default question title. Shown by default.

  • Optionalwidth?: Width<string | number>

    A number or string specifying a CSS size value that specifies the width of the component

  • OptionalwithAlerts?: boolean

    Enables the ability to set up alerts on the question.

  • OptionalwithChartTypeSelector?: boolean

    Determines whether the chart type selector and corresponding settings button are shown. Only relevant when using the default layout.

  • OptionalwithDownloads?: boolean

    Enables the ability to download results in the question.

    +
  • OptionalwithEditorButton?: boolean

    Determines whether the editor button is shown. Only relevant when using the default layout.

  • undefined
  • Returns Element

    Use <InteractiveQuestion questionId="new" /> instead.

    diff --git a/_docs/master/embedding/sdk/api/CreateQuestionProps.html b/_docs/master/embedding/sdk/api/CreateQuestionProps.html index 489cac2b93..b624b8b91d 100644 --- a/_docs/master/embedding/sdk/api/CreateQuestionProps.html +++ b/_docs/master/embedding/sdk/api/CreateQuestionProps.html @@ -9,19 +9,22 @@ layout: docs-api --- -CreateQuestionProps | Embedded analytics SDK API{% include docs/embedded-analytics-sdk-metadata.html %}

    Interface CreateQuestionProps

    interface CreateQuestionProps {
        className?: string;
        dataPicker?: EmbeddingDataPicker;
        entityTypes?: EmbeddingEntityType[];
        height?: Height<string | number>;
        hiddenParameters?: string[];
        initialSqlParameters?: SqlParameterValues;
        isSaveEnabled?: boolean;
        onBeforeSave?: (
            question: MetabaseQuestion | undefined,
            context: { isNewQuestion: boolean },
        ) => Promise<void>;
        onNavigateBack?: () => void;
        onRun?: (question: MetabaseQuestion | undefined) => void;
        onSave?: (
            question: MetabaseQuestion,
            context: { dashboardTabId?: number; isNewQuestion: boolean },
        ) => void;
        onVisualizationChange?: (
            display:
                | "object"
                | "table"
                | "bar"
                | "line"
                | "pie"
                | "scalar"
                | "row"
                | "area"
                | "combo"
                | "pivot"
                | "smartscalar"
                | "gauge"
                | "progress"
                | "funnel"
                | "map"
                | "scatter"
                | "boxplot"
                | "waterfall"
                | "sankey"
                | "list",
        ) => void;
        plugins?: MetabasePluginsConfig;
        style?: CSSProperties;
        targetCollection?: SdkCollectionId;
        title?: SdkQuestionTitleProps;
        width?: Width<string | number>;
        withAlerts?: boolean;
        withChartTypeSelector?: boolean;
        withDownloads?: boolean;
    }
    Index

    Properties

    className? +CreateQuestionProps | Embedded analytics SDK API{% include docs/embedded-analytics-sdk-metadata.html %}

    Interface CreateQuestionProps

    interface CreateQuestionProps {
        className?: string;
        dataPicker?: EmbeddingDataPicker;
        entityTypes?: EmbeddingEntityType[];
        height?: Height<string | number>;
        hiddenParameters?: string[];
        initialCollection?: SdkCollectionId;
        initialSqlParameters?: SqlParameterValues;
        isSaveEnabled?: boolean;
        onBeforeSave?: (
            question: MetabaseQuestion | undefined,
            context: { isNewQuestion: boolean },
        ) => Promise<void>;
        onNavigateBack?: () => void;
        onRun?: (question: MetabaseQuestion | undefined) => void;
        onSave?: (
            question: MetabaseQuestion,
            context: { dashboardTabId?: number; isNewQuestion: boolean },
        ) => void;
        onSqlParametersChange?: (payload: SqlParameterChangePayload) => void;
        onVisualizationChange?: (
            display:
                | "object"
                | "table"
                | "bar"
                | "line"
                | "pie"
                | "scalar"
                | "row"
                | "area"
                | "combo"
                | "pivot"
                | "smartscalar"
                | "gauge"
                | "progress"
                | "funnel"
                | "map"
                | "scatter"
                | "boxplot"
                | "waterfall"
                | "sankey"
                | "list",
        ) => void;
        plugins?: MetabasePluginsConfig;
        sqlParameters?: SqlParameterValues;
        style?: CSSProperties;
        targetCollection?: SdkCollectionId;
        title?: SdkQuestionTitleProps;
        width?: Width<string | number>;
        withAlerts?: boolean;
        withChartTypeSelector?: boolean;
        withDownloads?: boolean;
        withEditorButton?: boolean;
    }
    Index

    Properties

    className?: string

    A custom class name to be added to the root element.

    dataPicker?: EmbeddingDataPicker

    Controls the menu for selecting data sources in questions. You can opt for the full data picker by setting dataPicker = "staged".

    entityTypes?: EmbeddingEntityType[]

    An array that specifies which entity types are available in the data picker

    height?: Height<string | number>

    A number or string specifying a CSS size value that specifies the height of the component

    hiddenParameters?: string[]

    A list of parameters to hide.

    -
    initialSqlParameters?: SqlParameterValues

    Initial values for the SQL parameters.

    +
    initialCollection?: SdkCollectionId

    The collection to preselect in the save modal's collection picker. Unlike targetCollection, the picker remains visible and the user can choose a different collection. Ignored when targetCollection is set.

    +
    initialSqlParameters?: SqlParameterValues

    Initial values for SQL parameters, slug-keyed. Applied once on mount; user widget edits afterwards are not reflected back to the host. +
    +For each parameter: +

    +
      +
    • set to a value: that value is applied. +
    • +
    • set to null: strictly cleared, ignoring the parameter's default. +
    • +
    • omitted (or set to undefined): falls back to the parameter's default (or null if it has no default).
    • +
    isSaveEnabled?: boolean

    Whether to show the save button.

    onBeforeSave?: (
        question: MetabaseQuestion | undefined,
        context: { isNewQuestion: boolean },
    ) => Promise<void>

    A callback function that triggers before saving. Only relevant when isSaveEnabled = true

    onNavigateBack?: () => void

    A callback function that triggers when a user clicks the back button.

    onRun?: (question: MetabaseQuestion | undefined) => void

    A callback function that triggers when a question is updated, including when a user clicks the Visualize button in the question editor

    onSave?: (
        question: MetabaseQuestion,
        context: { dashboardTabId?: number; isNewQuestion: boolean },
    ) => void

    A callback function that triggers when a user saves the question. Only relevant when isSaveEnabled = true

    +
    onSqlParametersChange?: (payload: SqlParameterChangePayload) => void

    Fires on SQL parameters change. The payload's source distinguishes the initial state on load ('initial-state'), user edits in the UI ('manual-change'), and auto-updates ('auto-change').

    onVisualizationChange?: (
        display:
            | "object"
            | "table"
            | "bar"
            | "line"
            | "pie"
            | "scalar"
            | "row"
            | "area"
            | "combo"
            | "pivot"
            | "smartscalar"
            | "gauge"
            | "progress"
            | "funnel"
            | "map"
            | "scatter"
            | "boxplot"
            | "waterfall"
            | "sankey"
            | "list",
    ) => void

    A callback function that triggers when the visualization type changes.

    Type Declaration

      • (
            display:
                | "object"
                | "table"
                | "bar"
                | "line"
                | "pie"
                | "scalar"
                | "row"
                | "area"
                | "combo"
                | "pivot"
                | "smartscalar"
                | "gauge"
                | "progress"
                | "funnel"
                | "map"
                | "scatter"
                | "boxplot"
                | "waterfall"
                | "sankey"
                | "list",
        ): void
      • Parameters

        • display:
              | "object"
              | "table"
              | "bar"
              | "line"
              | "pie"
              | "scalar"
              | "row"
              | "area"
              | "combo"
              | "pivot"
              | "smartscalar"
              | "gauge"
              | "progress"
              | "funnel"
              | "map"
              | "scatter"
              | "boxplot"
              | "waterfall"
              | "sankey"
              | "list"

          the new display type

          -

        Returns void

    A custom style object to be added to the root element.

    +

    Returns void

    sqlParameters?: SqlParameterValues

    Controlled SQL parameter values, slug-keyed. On every render, this object replaces the question's parameter values: +

    +
      +
    • a parameter set to a value uses that value. +
    • +
    • a parameter set to null is cleared, even if it has a default. +
    • +
    • a parameter omitted from the object (or set to undefined) uses its default (or null if it has no default). +
      +
      +Pair with onSqlParametersChange to stay in sync with user edits.
    • +
    +

    A custom style object to be added to the root element.

    targetCollection?: SdkCollectionId

    The collection to save the question to. This will hide the collection picker from the save modal. Only applicable to interactive questions.

    Determines whether the question title is displayed, and allows a custom title to be displayed instead of the default question title. Shown by default.

    width?: Width<string | number>

    A number or string specifying a CSS size value that specifies the width of the component

    withAlerts?: boolean

    Enables the ability to set up alerts on the question.

    withChartTypeSelector?: boolean

    Determines whether the chart type selector and corresponding settings button are shown. Only relevant when using the default layout.

    withDownloads?: boolean

    Enables the ability to download results in the question.

    -

    +
    withEditorButton?: boolean

    Determines whether the editor button is shown. Only relevant when using the default layout.

    +

    diff --git a/_docs/master/embedding/sdk/api/DrillThroughQuestionProps.html b/_docs/master/embedding/sdk/api/DrillThroughQuestionProps.html index 98f7b97161..53d3ddfe31 100644 --- a/_docs/master/embedding/sdk/api/DrillThroughQuestionProps.html +++ b/_docs/master/embedding/sdk/api/DrillThroughQuestionProps.html @@ -10,11 +10,12 @@ --- DrillThroughQuestionProps | Embedded analytics SDK API{% include docs/embedded-analytics-sdk-metadata.html %}

    Interface DrillThroughQuestionProps

    Props for the drill-through question

    -
    interface DrillThroughQuestionProps {
        children?: ReactNode;
        className?: string;
        dataPicker?: EmbeddingDataPicker;
        entityTypes?: EmbeddingEntityType[];
        height?: Height<string | number>;
        initialSqlParameters?: SqlParameterValues;
        isSaveEnabled?: boolean;
        onBeforeSave?: (
            question: MetabaseQuestion | undefined,
            context: { isNewQuestion: boolean },
        ) => Promise<void>;
        onRun?: (question: MetabaseQuestion | undefined) => void;
        onSave?: (
            question: MetabaseQuestion,
            context: { dashboardTabId?: number; isNewQuestion: boolean },
        ) => void;
        plugins?: MetabasePluginsConfig;
        style?: CSSProperties;
        targetCollection?: SdkCollectionId;
        title?: SdkQuestionTitleProps;
        width?: Width<string | number>;
        withAlerts?: boolean;
        withChartTypeSelector?: boolean;
        withDownloads?: boolean;
    }
    Index

    Properties

    interface DrillThroughQuestionProps {
        children?: ReactNode;
        className?: string;
        dataPicker?: EmbeddingDataPicker;
        entityTypes?: EmbeddingEntityType[];
        height?: Height<string | number>;
        initialCollection?: SdkCollectionId;
        initialSqlParameters?: SqlParameterValues;
        isSaveEnabled?: boolean;
        onBeforeSave?: (
            question: MetabaseQuestion | undefined,
            context: { isNewQuestion: boolean },
        ) => Promise<void>;
        onRun?: (question: MetabaseQuestion | undefined) => void;
        onSave?: (
            question: MetabaseQuestion,
            context: { dashboardTabId?: number; isNewQuestion: boolean },
        ) => void;
        plugins?: MetabasePluginsConfig;
        style?: CSSProperties;
        targetCollection?: SdkCollectionId;
        title?: SdkQuestionTitleProps;
        width?: Width<string | number>;
        withAlerts?: boolean;
        withChartTypeSelector?: boolean;
        withDownloads?: boolean;
        withEditorButton?: boolean;
    }
    Index

    Properties

    children?: ReactNode

    The children of the component

    className?: string

    A custom class name to be added to the root element.

    dataPicker?: EmbeddingDataPicker

    Controls the menu for selecting data sources in questions. You can opt for the full data picker by setting dataPicker = "staged".

    entityTypes?: EmbeddingEntityType[]

    An array that specifies which entity types are available in the data picker

    height?: Height<string | number>

    A number or string specifying a CSS size value that specifies the height of the component

    -
    initialSqlParameters?: SqlParameterValues

    Initial values for the SQL parameters.

    +
    initialCollection?: SdkCollectionId

    The collection to preselect in the save modal's collection picker. Unlike targetCollection, the picker remains visible and the user can choose a different collection. Ignored when targetCollection is set.

    +
    initialSqlParameters?: SqlParameterValues

    Initial values for SQL parameters, slug-keyed. Applied once on mount; user widget edits afterwards are not reflected back to the host. +
    +For each parameter: +

    +
      +
    • set to a value: that value is applied. +
    • +
    • set to null: strictly cleared, ignoring the parameter's default. +
    • +
    • omitted (or set to undefined): falls back to the parameter's default (or null if it has no default).
    • +
    isSaveEnabled?: boolean

    Whether to show the save button.

    onBeforeSave?: (
        question: MetabaseQuestion | undefined,
        context: { isNewQuestion: boolean },
    ) => Promise<void>

    A callback function that triggers before saving. Only relevant when isSaveEnabled = true

    onRun?: (question: MetabaseQuestion | undefined) => void

    A callback function that triggers when a question is updated, including when a user clicks the Visualize button in the question editor

    @@ -45,4 +58,5 @@
    withAlerts?: boolean

    Enables the ability to set up alerts on the question.

    withChartTypeSelector?: boolean

    Determines whether the chart type selector and corresponding settings button are shown. Only relevant when using the default layout.

    withDownloads?: boolean

    Enables the ability to download results in the question.

    -

    +
    withEditorButton?: boolean

    Determines whether the editor button is shown. Only relevant when using the default layout.

    +

    diff --git a/_docs/master/embedding/sdk/api/EditableDashboard.html b/_docs/master/embedding/sdk/api/EditableDashboard.html index b8c709c1cb..6c27198dda 100644 --- a/_docs/master/embedding/sdk/api/EditableDashboard.html +++ b/_docs/master/embedding/sdk/api/EditableDashboard.html @@ -33,17 +33,43 @@
  • Combining initialParameters and hiddenParameters to declutter the user interface is fine.
  • -
  • OptionalinitialParameters?: ParameterValues

    Query parameters for the dashboard. For a single option, use a string value, and use a list of strings for multiple options. +

  • OptionalinitialParameters?: ParameterValues

    Initial values for query parameters, slug-keyed. Applied once on mount; user widget edits afterwards are not reflected back to the host. +
    +For each parameter:

      +
    • set to a value (string for a single option, array of strings for multiple): that value is applied. +
    • +
    • set to null: strictly cleared, ignoring the parameter's default. +
    • +
    • omitted (or set to undefined): falls back to the parameter's default (or null if it has no default). +
      +
    • Combining initialParameters and hiddenParameters to filter data on the frontend is a security risk.
    • Combining initialParameters and hiddenParameters to declutter the user interface is fine.
  • OptionalonLoad?: (dashboard: MetabaseDashboard | null) => void

    Callback that is called when the dashboard is loaded.

  • OptionalonLoadWithoutCards?: (dashboard: MetabaseDashboard | null) => void

    Callback that is called when the dashboard is loaded without cards.

    +
  • OptionalonParametersChange?: (payload: ParameterChangePayload) => void

    Fires on parameters change. The payload's source distinguishes the initial state on load ('initial-state'), user edits in the UI ('manual-change'), and auto-updates ('auto-change').

  • OptionalonVisualizationChange?: (
        visualization:
            | "object"
            | "table"
            | "bar"
            | "line"
            | "pie"
            | "scalar"
            | "row"
            | "area"
            | "combo"
            | "pivot"
            | "smartscalar"
            | "gauge"
            | "progress"
            | "funnel"
            | "map"
            | "scatter"
            | "boxplot"
            | "waterfall"
            | "sankey"
            | "list",
    ) => void

    A callback function that triggers when a question is opened from a dashboard card or when the user changes the visualization type of a question.

    +
  • Optionalparameters?: ParameterValues

    Controlled parameter values, slug-keyed. On every render, this object replaces the dashboard's parameter values: +

    +
      +
    • a parameter set to a value uses that value. +
    • +
    • a parameter set to null is cleared, even if it has a default. +
    • +
    • a parameter omitted from the object (or set to undefined) uses its default (or null if it has no default). +
      +
      +Pair with onParametersChange to stay in sync with user edits. +
    • +
    • Combining parameters and hiddenParameters to filter data on the frontend is a security risk. +
    • +
    • Combining parameters and hiddenParameters to declutter the user interface is fine.
    • +
  • Optionalplugins?: MetabasePluginsConfig

    Additional mapper function to override or add drill-down menu. See the implementing custom actions section for more details.

  • OptionalrenderDrillThroughQuestion?: () => ReactNode

    A custom React component to render the question layout. Use namespaced InteractiveQuestion components to build the layout.

    diff --git a/_docs/master/embedding/sdk/api/EditableDashboardProps.html b/_docs/master/embedding/sdk/api/EditableDashboardProps.html index 44f519570f..6dee40c0ca 100644 --- a/_docs/master/embedding/sdk/api/EditableDashboardProps.html +++ b/_docs/master/embedding/sdk/api/EditableDashboardProps.html @@ -9,7 +9,7 @@ layout: docs-api --- -EditableDashboardProps | Embedded analytics SDK API{% include docs/embedded-analytics-sdk-metadata.html %}

    Interface EditableDashboardProps

    interface EditableDashboardProps {
        autoRefreshInterval?: number;
        className?: string;
        dashboardId: string | number;
        dataPickerProps?: Pick<SdkQuestionProps, "entityTypes">;
        drillThroughQuestionHeight?: Height<string | number>;
        drillThroughQuestionProps?: DrillThroughQuestionProps;
        enableEntityNavigation?: boolean;
        hiddenParameters?: string[];
        initialParameters?: ParameterValues;
        onLoad?: (dashboard: MetabaseDashboard | null) => void;
        onLoadWithoutCards?: (dashboard: MetabaseDashboard | null) => void;
        onVisualizationChange?: (
            visualization:
                | "object"
                | "table"
                | "bar"
                | "line"
                | "pie"
                | "scalar"
                | "row"
                | "area"
                | "combo"
                | "pivot"
                | "smartscalar"
                | "gauge"
                | "progress"
                | "funnel"
                | "map"
                | "scatter"
                | "boxplot"
                | "waterfall"
                | "sankey"
                | "list",
        ) => void;
        plugins?: MetabasePluginsConfig;
        renderDrillThroughQuestion?: () => ReactNode;
        style?: CSSProperties;
        token?: string | null;
        withCardTitle?: boolean;
        withDownloads?: boolean;
        withSubscriptions?: boolean;
        withTitle?: boolean;
    }
    Index

    Properties

    autoRefreshInterval? +EditableDashboardProps | Embedded analytics SDK API{% include docs/embedded-analytics-sdk-metadata.html %}

    Interface EditableDashboardProps

    interface EditableDashboardProps {
        autoRefreshInterval?: number;
        className?: string;
        dashboardId: string | number;
        dataPickerProps?: Pick<SdkQuestionProps, "entityTypes">;
        drillThroughQuestionHeight?: Height<string | number>;
        drillThroughQuestionProps?: DrillThroughQuestionProps;
        enableEntityNavigation?: boolean;
        hiddenParameters?: string[];
        initialParameters?: ParameterValues;
        onLoad?: (dashboard: MetabaseDashboard | null) => void;
        onLoadWithoutCards?: (dashboard: MetabaseDashboard | null) => void;
        onParametersChange?: (payload: ParameterChangePayload) => void;
        onVisualizationChange?: (
            visualization:
                | "object"
                | "table"
                | "bar"
                | "line"
                | "pie"
                | "scalar"
                | "row"
                | "area"
                | "combo"
                | "pivot"
                | "smartscalar"
                | "gauge"
                | "progress"
                | "funnel"
                | "map"
                | "scatter"
                | "boxplot"
                | "waterfall"
                | "sankey"
                | "list",
        ) => void;
        parameters?: ParameterValues;
        plugins?: MetabasePluginsConfig;
        renderDrillThroughQuestion?: () => ReactNode;
        style?: CSSProperties;
        token?: string | null;
        withCardTitle?: boolean;
        withDownloads?: boolean;
        withSubscriptions?: boolean;
        withTitle?: boolean;
    }
    Index
  • OptionaldataPicker?: EmbeddingDataPicker

    Controls the menu for selecting data sources in questions. You can opt for the full data picker by setting dataPicker = "staged".

  • OptionalentityTypes?: EmbeddingEntityType[]

    An array that specifies which entity types are available in the data picker

  • Optionalheight?: Height<string | number>

    A number or string specifying a CSS size value that specifies the height of the component

    -
  • OptionalinitialSqlParameters?: SqlParameterValues

    Initial values for the SQL parameters.

    +
  • OptionalinitialCollection?: SdkCollectionId

    The collection to preselect in the save modal's collection picker. Unlike targetCollection, the picker remains visible and the user can choose a different collection. Ignored when targetCollection is set.

    +
  • OptionalinitialSqlParameters?: SqlParameterValues

    Initial values for SQL parameters, slug-keyed. Applied once on mount; user widget edits afterwards are not reflected back to the host. +
    +For each parameter: +

    +
      +
    • set to a value: that value is applied. +
    • +
    • set to null: strictly cleared, ignoring the parameter's default. +
    • +
    • omitted (or set to undefined): falls back to the parameter's default (or null if it has no default).
    • +
  • OptionalisSaveEnabled?: boolean

    Whether to show the save button.

  • OptionalonBeforeSave?: (
        question: MetabaseQuestion | undefined,
        context: { isNewQuestion: boolean },
    ) => Promise<void>

    A callback function that triggers before saving. Only relevant when isSaveEnabled = true

  • OptionalonRun?: (question: MetabaseQuestion | undefined) => void

    A callback function that triggers when a question is updated, including when a user clicks the Visualize button in the question editor

    @@ -61,6 +74,7 @@
  • OptionalwithAlerts?: boolean

    Enables the ability to set up alerts on the question.

  • OptionalwithChartTypeSelector?: boolean

    Determines whether the chart type selector and corresponding settings button are shown. Only relevant when using the default layout.

  • OptionalwithDownloads?: boolean

    Enables the ability to download results in the question.

    +
  • OptionalwithEditorButton?: boolean

    Determines whether the editor button is shown. Only relevant when using the default layout.

  • enableEntityNavigation?: boolean

    When true, internal click behaviors (links to dashboards/questions) are preserved. When false (default for SDK), these click behaviors are filtered out.

    hiddenParameters?: string[]

    A list of parameters to hide. @@ -70,19 +84,45 @@

  • Combining initialParameters and hiddenParameters to declutter the user interface is fine.
  • -
    initialParameters?: ParameterValues

    Query parameters for the dashboard. For a single option, use a string value, and use a list of strings for multiple options. +

    initialParameters?: ParameterValues

    Initial values for query parameters, slug-keyed. Applied once on mount; user widget edits afterwards are not reflected back to the host. +
    +For each parameter:

      +
    • set to a value (string for a single option, array of strings for multiple): that value is applied. +
    • +
    • set to null: strictly cleared, ignoring the parameter's default. +
    • +
    • omitted (or set to undefined): falls back to the parameter's default (or null if it has no default). +
      +
    • Combining initialParameters and hiddenParameters to filter data on the frontend is a security risk.
    • Combining initialParameters and hiddenParameters to declutter the user interface is fine.
    onLoad?: (dashboard: MetabaseDashboard | null) => void

    Callback that is called when the dashboard is loaded.

    onLoadWithoutCards?: (dashboard: MetabaseDashboard | null) => void

    Callback that is called when the dashboard is loaded without cards.

    +
    onParametersChange?: (payload: ParameterChangePayload) => void

    Fires on parameters change. The payload's source distinguishes the initial state on load ('initial-state'), user edits in the UI ('manual-change'), and auto-updates ('auto-change').

    onVisualizationChange?: (
        visualization:
            | "object"
            | "table"
            | "bar"
            | "line"
            | "pie"
            | "scalar"
            | "row"
            | "area"
            | "combo"
            | "pivot"
            | "smartscalar"
            | "gauge"
            | "progress"
            | "funnel"
            | "map"
            | "scatter"
            | "boxplot"
            | "waterfall"
            | "sankey"
            | "list",
    ) => void

    A callback function that triggers when a question is opened from a dashboard card or when the user changes the visualization type of a question.

    Type Declaration

      • (
            visualization:
                | "object"
                | "table"
                | "bar"
                | "line"
                | "pie"
                | "scalar"
                | "row"
                | "area"
                | "combo"
                | "pivot"
                | "smartscalar"
                | "gauge"
                | "progress"
                | "funnel"
                | "map"
                | "scatter"
                | "boxplot"
                | "waterfall"
                | "sankey"
                | "list",
        ): void
      • Parameters

        • visualization:
              | "object"
              | "table"
              | "bar"
              | "line"
              | "pie"
              | "scalar"
              | "row"
              | "area"
              | "combo"
              | "pivot"
              | "smartscalar"
              | "gauge"
              | "progress"
              | "funnel"
              | "map"
              | "scatter"
              | "boxplot"
              | "waterfall"
              | "sankey"
              | "list"

          the new visualization type

          -

        Returns void

    Additional mapper function to override or add drill-down menu. See the implementing custom actions section for more details.

    +

    Returns void

    parameters?: ParameterValues

    Controlled parameter values, slug-keyed. On every render, this object replaces the dashboard's parameter values: +

    +
      +
    • a parameter set to a value uses that value. +
    • +
    • a parameter set to null is cleared, even if it has a default. +
    • +
    • a parameter omitted from the object (or set to undefined) uses its default (or null if it has no default). +
      +
      +Pair with onParametersChange to stay in sync with user edits. +
    • +
    • Combining parameters and hiddenParameters to filter data on the frontend is a security risk. +
    • +
    • Combining parameters and hiddenParameters to declutter the user interface is fine.
    • +
    +

    Additional mapper function to override or add drill-down menu. See the implementing custom actions section for more details.

    renderDrillThroughQuestion?: () => ReactNode

    A custom React component to render the question layout. Use namespaced InteractiveQuestion components to build the layout.

    A custom style object to be added to the root element.

    @@ -90,4 +130,4 @@
    withDownloads?: boolean

    Whether to hide the download button.

    withSubscriptions?: boolean

    Whether to show the subscriptions button.

    withTitle?: boolean

    Whether the dashboard should display a title.

    -

    +

    diff --git a/_docs/master/embedding/sdk/api/IconName.html b/_docs/master/embedding/sdk/api/IconName.html index 814724bbaa..ebde530b8d 100644 --- a/_docs/master/embedding/sdk/api/IconName.html +++ b/_docs/master/embedding/sdk/api/IconName.html @@ -9,4 +9,4 @@ layout: docs-api --- -IconName | Embedded analytics SDK API{% include docs/embedded-analytics-sdk-metadata.html %}

    Type Alias IconName

    IconName:
        | "string"
        | "number"
        | "function"
        | "collection"
        | "dashboard"
        | "question"
        | "model"
        | "archive"
        | "table"
        | "bar"
        | "line"
        | "pie"
        | "scalar"
        | "area"
        | "smartscalar"
        | "gauge"
        | "progress"
        | "funnel"
        | "boxplot"
        | "waterfall"
        | "sankey"
        | "list"
        | "revert"
        | "add"
        | "add_collection"
        | "add_column"
        | "add_data"
        | "add_folder"
        | "add_list"
        | "add_row"
        | "add_to_dash"
        | "add_comment"
        | "ai"
        | "alert"
        | "alert_filled"
        | "alert_confirm"
        | "attachment"
        | "arrow_up"
        | "arrow_down"
        | "arrow_left"
        | "arrow_left_to_line"
        | "arrow_right"
        | "arrow_split"
        | "audit"
        | "badge"
        | "ban"
        | "bell"
        | "birthday"
        | "book_open"
        | "bookmark"
        | "bookmark_filled"
        | "bolt"
        | "bolt_filled"
        | "breakout"
        | "bubble"
        | "broken_link"
        | "burger"
        | "calendar"
        | "camera"
        | "chart_layout_default"
        | "chart_layout_stack"
        | "check"
        | "check_filled"
        | "code_block"
        | "chevrondown"
        | "chevronleft"
        | "chevronright"
        | "chevronup"
        | "click"
        | "clipboard"
        | "clock"
        | "clone"
        | "close"
        | "cloud"
        | "cloud_filled"
        | "collection2"
        | "compare"
        | "combine"
        | "company"
        | "comment"
        | "currency"
        | "connections"
        | "contract"
        | "copy"
        | "corner_up_right"
        | "curved"
        | "database"
        | "database_routing"
        | "dependencies"
        | "data_studio"
        | "dash"
        | "curve"
        | "document"
        | "download"
        | "dyno"
        | "edit_document"
        | "edit_document_outlined"
        | "ellipsis"
        | "embed"
        | "embed_interactive"
        | "embed_modular"
        | "embed_static"
        | "empty"
        | "enter_or_return"
        | "exit"
        | "expand"
        | "expand_arrow"
        | "extract"
        | "eye"
        | "eye_crossed_out"
        | "eye_outline"
        | "factory"
        | "field"
        | "fields"
        | "filter"
        | "filter_plus"
        | "find_replace"
        | "bug"
        | "format_code"
        | "formula"
        | "funnel_outline"
        | "folder"
        | "folder_database"
        | "folder_filled"
        | "gear"
        | "gear_settings_filled"
        | "gem"
        | "ghost"
        | "globe"
        | "glossary"
        | "git_branch"
        | "grabber"
        | "grid"
        | "grid_2x2"
        | "grid_bordered"
        | "group"
        | "google"
        | "google_drive"
        | "google_sheet"
        | "history"
        | "home"
        | "horizontal_bar"
        | "hourglass"
        | "info"
        | "info_outline"
        | "insight"
        | "int"
        | "io"
        | "join_full_outer"
        | "join_inner"
        | "join_left_outer"
        | "join_right_outer"
        | "index"
        | "key"
        | "label"
        | "layout_grid"
        | "ldap"
        | "learn"
        | "lightbulb"
        | "link"
        | "lines"
        | "lineandbar"
        | "line_style_dashed"
        | "line_style_dotted"
        | "line_style_solid"
        | "location"
        | "lock"
        | "lock_filled"
        | "mail"
        | "mail_filled"
        | "medallion"
        | "message_circle"
        | "metabot"
        | "metabot_sad"
        | "metric"
        | "mode"
        | "model_with_badge"
        | "moon"
        | "move"
        | "move_card"
        | "network"
        | "new_folder"
        | "notebook"
        | "octagon_alert"
        | "package"
        | "palette"
        | "pause"
        | "pencil"
        | "pencil_lines"
        | "permissions_limited"
        | "person"
        | "pie_slice"
        | "pin"
        | "pinmap"
        | "pivot_table"
        | "play"
        | "play_outlined"
        | "popover"
        | "popular"
        | "publish"
        | "published"
        | "pulse"
        | "receipt"
        | "recents"
        | "share"
        | "send"
        | "settings"
        | "smile"
        | "split"
        | "sql"
        | "subscription"
        | "straight"
        | "stepped"
        | "sticky_note"
        | "sort"
        | "sort_arrows"
        | "sum"
        | "sync"
        | "synced_collection"
        | "transform"
        | "quote"
        | "redo"
        | "return"
        | "reference"
        | "refresh"
        | "refresh_downstream"
        | "rename"
        | "repository"
        | "rocket"
        | "ruler"
        | "schema"
        | "search"
        | "search_check"
        | "section"
        | "segment"
        | "shield"
        | "shield_outline"
        | "sidebar_closed"
        | "sidebar_open"
        | "slack"
        | "slack_colorized"
        | "snail"
        | "snippet"
        | "sparkles"
        | "star_filled"
        | "star"
        | "stop"
        | "store"
        | "sun"
        | "t-shirt"
        | "tab"
        | "table2"
        | "text_bold"
        | "text_italic"
        | "text_strike"
        | "thumbs_down"
        | "thumbs_up"
        | "time_history"
        | "trash"
        | "trash_filled"
        | "triangle_left"
        | "triangle_right"
        | "unarchive"
        | "undo"
        | "unknown"
        | "unpin"
        | "unpublish"
        | "unreferenced"
        | "unsubscribe"
        | "upload"
        | "variable"
        | "verified"
        | "official_collection"
        | "open_folder"
        | "ordered_list"
        | "verified_filled"
        | "verified_round"
        | "view_archive"
        | "warning"
        | "warning_round_filled"
        | "warning_triangle_filled"
        | "webhook"
        | "10k"
        | "1m"
        | "zap"
        | "zoom_in"
        | "zoom_out"
        | "cake"
        | "external"
        | "beaker"
        | "test_tube"
        | "eye_filled"

    +IconName | Embedded analytics SDK API{% include docs/embedded-analytics-sdk-metadata.html %}

    Type Alias IconName

    IconName:
        | "string"
        | "number"
        | "function"
        | "collection"
        | "dashboard"
        | "question"
        | "model"
        | "archive"
        | "table"
        | "bar"
        | "line"
        | "pie"
        | "scalar"
        | "area"
        | "smartscalar"
        | "gauge"
        | "progress"
        | "funnel"
        | "boxplot"
        | "waterfall"
        | "sankey"
        | "list"
        | "revert"
        | "add"
        | "add_collection"
        | "add_column"
        | "add_data"
        | "add_folder"
        | "add_list"
        | "add_row"
        | "add_to_dash"
        | "add_comment"
        | "ai"
        | "alert"
        | "alert_filled"
        | "alert_confirm"
        | "attachment"
        | "arrow_up"
        | "arrow_down"
        | "arrow_left"
        | "arrow_left_to_line"
        | "arrow_right"
        | "arrow_split"
        | "audit"
        | "badge"
        | "ban"
        | "bell"
        | "birthday"
        | "book_open"
        | "bookmark"
        | "bookmark_filled"
        | "bolt"
        | "bolt_filled"
        | "breakout"
        | "bubble"
        | "broken_link"
        | "burger"
        | "calendar"
        | "camera"
        | "chart_layout_default"
        | "chart_layout_stack"
        | "check"
        | "check_filled"
        | "code_block"
        | "chevrondown"
        | "chevronleft"
        | "chevronright"
        | "chevronup"
        | "click"
        | "clipboard"
        | "clock"
        | "clone"
        | "close"
        | "cloud"
        | "cloud_filled"
        | "collection2"
        | "compare"
        | "combine"
        | "company"
        | "comment"
        | "currency"
        | "connections"
        | "contract"
        | "copy"
        | "corner_up_right"
        | "curved"
        | "database"
        | "database_routing"
        | "dependencies"
        | "data_studio"
        | "dash"
        | "curve"
        | "document"
        | "download"
        | "dyno"
        | "edit_document"
        | "edit_document_outlined"
        | "ellipsis"
        | "embed"
        | "embed_interactive"
        | "embed_modular"
        | "embed_static"
        | "empty"
        | "enter_or_return"
        | "exit"
        | "expand"
        | "expand_arrow"
        | "extract"
        | "eye"
        | "eye_crossed_out"
        | "eye_outline"
        | "factory"
        | "field"
        | "fields"
        | "filter"
        | "filter_plus"
        | "find_replace"
        | "bug"
        | "format_code"
        | "formula"
        | "funnel_outline"
        | "folder"
        | "folder_database"
        | "folder_filled"
        | "gear"
        | "gear_settings_filled"
        | "gem"
        | "ghost"
        | "globe"
        | "glossary"
        | "git_branch"
        | "grabber"
        | "grid"
        | "grid_2x2"
        | "grid_bordered"
        | "group"
        | "google"
        | "google_drive"
        | "google_sheet"
        | "history"
        | "home"
        | "horizontal_bar"
        | "hourglass"
        | "info"
        | "info_outline"
        | "insight"
        | "int"
        | "io"
        | "join_full_outer"
        | "join_inner"
        | "join_left_outer"
        | "join_right_outer"
        | "index"
        | "key"
        | "label"
        | "layout_grid"
        | "ldap"
        | "learn"
        | "lightbulb"
        | "link"
        | "lines"
        | "lineandbar"
        | "line_style_dashed"
        | "line_style_dotted"
        | "line_style_solid"
        | "location"
        | "lock"
        | "lock_filled"
        | "mail"
        | "mail_filled"
        | "mcp"
        | "medallion"
        | "message_circle"
        | "metabot"
        | "metabot_sad"
        | "metric"
        | "mode"
        | "model_with_badge"
        | "moon"
        | "move"
        | "move_card"
        | "network"
        | "new_folder"
        | "notebook"
        | "octagon_alert"
        | "package"
        | "palette"
        | "pause"
        | "pencil"
        | "pencil_lines"
        | "permissions_limited"
        | "person"
        | "pie_slice"
        | "pin"
        | "pinmap"
        | "pivot_table"
        | "play"
        | "play_outlined"
        | "popover"
        | "popular"
        | "publish"
        | "published"
        | "pulse"
        | "receipt"
        | "recents"
        | "share"
        | "send"
        | "settings"
        | "smile"
        | "split"
        | "sql"
        | "subscription"
        | "straight"
        | "stepped"
        | "sticky_note"
        | "sort"
        | "sort_arrows"
        | "sum"
        | "sync"
        | "synced_collection"
        | "transform"
        | "quote"
        | "redo"
        | "return"
        | "reference"
        | "refresh"
        | "refresh_downstream"
        | "rename"
        | "repository"
        | "rocket"
        | "ruler"
        | "schema"
        | "search"
        | "search_check"
        | "section"
        | "segment"
        | "shield"
        | "shield_outline"
        | "shield_stroke"
        | "sidebar_closed"
        | "sidebar_open"
        | "slack"
        | "slack_colorized"
        | "snail"
        | "snippet"
        | "sparkles"
        | "star_filled"
        | "star"
        | "stop"
        | "store"
        | "sun"
        | "t-shirt"
        | "tab"
        | "table2"
        | "text_bold"
        | "text_italic"
        | "text_strike"
        | "thumbs_down"
        | "thumbs_up"
        | "time_history"
        | "trash"
        | "trash_filled"
        | "triangle_left"
        | "triangle_right"
        | "unarchive"
        | "undo"
        | "unknown"
        | "unpin"
        | "unpublish"
        | "unreferenced"
        | "unsubscribe"
        | "upload"
        | "variable"
        | "verified"
        | "official_collection"
        | "open_folder"
        | "ordered_list"
        | "verified_filled"
        | "verified_round"
        | "view_archive"
        | "warning"
        | "warning_round_filled"
        | "warning_triangle_filled"
        | "webhook"
        | "10k"
        | "1m"
        | "zap"
        | "zoom_in"
        | "zoom_out"
        | "cake"
        | "external"
        | "beaker"
        | "test_tube"
        | "eye_filled"

    diff --git a/_docs/master/embedding/sdk/api/InteractiveDashboard.html b/_docs/master/embedding/sdk/api/InteractiveDashboard.html index 51e2ca2972..286d4998ad 100644 --- a/_docs/master/embedding/sdk/api/InteractiveDashboard.html +++ b/_docs/master/embedding/sdk/api/InteractiveDashboard.html @@ -9,8 +9,8 @@ layout: docs-api --- -InteractiveDashboard | Embedded analytics SDK API{% include docs/embedded-analytics-sdk-metadata.html %}

    Function InteractiveDashboard

    • A dashboard component with drill downs, click behaviors, and the ability to view and click into questions.

      -

      Parameters

      • props: {
            autoRefreshInterval?: number;
            dashboardId: SdkDashboardId;
            drillThroughQuestionHeight?: Height<string | number>;
            drillThroughQuestionProps?: DrillThroughQuestionProps;
            initialParameters?: ParameterValues;
            plugins?: MetabasePluginsConfig;
            renderDrillThroughQuestion?: () => ReactNode;
        } & { dashboardId?: SdkDashboardId
        | null; token?: string | null } & {
            enableEntityNavigation?: boolean;
            hiddenParameters?: string[];
            initialParameters?: ParameterValues;
            withCardTitle?: boolean;
            withDownloads?: boolean;
            withSubscriptions?: boolean;
            withTitle?: boolean;
        } & { className?: string; style?: CSSProperties } & {
            onLoad?: (dashboard: MetabaseDashboard | null) => void;
            onLoadWithoutCards?: (dashboard: MetabaseDashboard | null) => void;
            onVisualizationChange?: (
                visualization:
                    | "object"
                    | "table"
                    | "bar"
                    | "line"
                    | "pie"
                    | "scalar"
                    | "row"
                    | "area"
                    | "combo"
                    | "pivot"
                    | "smartscalar"
                    | "gauge"
                    | "progress"
                    | "funnel"
                    | "map"
                    | "scatter"
                    | "boxplot"
                    | "waterfall"
                    | "sankey"
                    | "list",
            ) => void;
        } & { dataPickerProps?: Pick<SdkQuestionProps, "entityTypes"> } & {}
        • OptionalautoRefreshInterval?: number

          The interval between auto refreshes on the dashboard, in seconds.

          +InteractiveDashboard | Embedded analytics SDK API{% include docs/embedded-analytics-sdk-metadata.html %}

          Function InteractiveDashboard

          • A dashboard component with drill downs, click behaviors, and the ability to view and click into questions.

            +

            Parameters

            • props: {
                  autoRefreshInterval?: number;
                  dashboardId: SdkDashboardId;
                  drillThroughQuestionHeight?: Height<string | number>;
                  drillThroughQuestionProps?: DrillThroughQuestionProps;
                  initialParameters?: ParameterValues;
                  onParametersChange?: (payload: ParameterChangePayload) => void;
                  parameters?: ParameterValues;
                  plugins?: MetabasePluginsConfig;
                  renderDrillThroughQuestion?: () => ReactNode;
              } & { dashboardId?: SdkDashboardId
              | null; token?: string | null } & {
                  enableEntityNavigation?: boolean;
                  hiddenParameters?: string[];
                  initialParameters?: ParameterValues;
                  withCardTitle?: boolean;
                  withDownloads?: boolean;
                  withSubscriptions?: boolean;
                  withTitle?: boolean;
              } & { className?: string; style?: CSSProperties } & {
                  onLoad?: (dashboard: MetabaseDashboard | null) => void;
                  onLoadWithoutCards?: (dashboard: MetabaseDashboard | null) => void;
                  onVisualizationChange?: (
                      visualization:
                          | "object"
                          | "table"
                          | "bar"
                          | "line"
                          | "pie"
                          | "scalar"
                          | "row"
                          | "area"
                          | "combo"
                          | "pivot"
                          | "smartscalar"
                          | "gauge"
                          | "progress"
                          | "funnel"
                          | "map"
                          | "scatter"
                          | "boxplot"
                          | "waterfall"
                          | "sankey"
                          | "list",
                  ) => void;
              } & { dataPickerProps?: Pick<SdkQuestionProps, "entityTypes"> } & {}
              • OptionalautoRefreshInterval?: number

                The interval between auto refreshes on the dashboard, in seconds.

              • dashboardId: SdkDashboardId

                The ID of the dashboard.
                This is either: @@ -22,13 +22,39 @@

          • OptionaldrillThroughQuestionHeight?: Height<string | number>

            Height of a question component when drilled from the dashboard to a question level.

          • OptionaldrillThroughQuestionProps?: DrillThroughQuestionProps

            Props of a question component when drilled from the dashboard to a question level.

            -
          • OptionalinitialParameters?: ParameterValues

            Query parameters for the dashboard. For a single option, use a string value, and use a list of strings for multiple options. +

          • OptionalinitialParameters?: ParameterValues

            Initial values for query parameters, slug-keyed. Applied once on mount; user widget edits afterwards are not reflected back to the host. +
            +For each parameter:

              +
            • set to a value (string for a single option, array of strings for multiple): that value is applied. +
            • +
            • set to null: strictly cleared, ignoring the parameter's default. +
            • +
            • omitted (or set to undefined): falls back to the parameter's default (or null if it has no default). +
              +
            • Combining initialParameters and hiddenParameters to filter data on the frontend is a security risk.
            • Combining initialParameters and hiddenParameters to declutter the user interface is fine.
            +
          • OptionalonParametersChange?: (payload: ParameterChangePayload) => void

            Fires on parameters change. The payload's source distinguishes the initial state on load ('initial-state'), user edits in the UI ('manual-change'), and auto-updates ('auto-change').

            +
          • Optionalparameters?: ParameterValues

            Controlled parameter values, slug-keyed. On every render, this object replaces the dashboard's parameter values: +

            +
              +
            • a parameter set to a value uses that value. +
            • +
            • a parameter set to null is cleared, even if it has a default. +
            • +
            • a parameter omitted from the object (or set to undefined) uses its default (or null if it has no default). +
              +
              +Pair with onParametersChange to stay in sync with user edits. +
            • +
            • Combining parameters and hiddenParameters to filter data on the frontend is a security risk. +
            • +
            • Combining parameters and hiddenParameters to declutter the user interface is fine.
            • +
          • Optionalplugins?: MetabasePluginsConfig

            Additional mapper function to override or add drill-down menu. See the implementing custom actions section for more details.

          • OptionalrenderDrillThroughQuestion?: () => ReactNode

            A custom React component to render the question layout. Use namespaced InteractiveQuestion components to build the layout.

            diff --git a/_docs/master/embedding/sdk/api/InteractiveDashboardProps.html b/_docs/master/embedding/sdk/api/InteractiveDashboardProps.html index fac5d71383..8b0e504ecd 100644 --- a/_docs/master/embedding/sdk/api/InteractiveDashboardProps.html +++ b/_docs/master/embedding/sdk/api/InteractiveDashboardProps.html @@ -9,7 +9,7 @@ layout: docs-api --- -InteractiveDashboardProps | Embedded analytics SDK API{% include docs/embedded-analytics-sdk-metadata.html %}

            Interface InteractiveDashboardProps

            interface InteractiveDashboardProps {
                autoRefreshInterval?: number;
                className?: string;
                dashboardId: string | number;
                dataPickerProps?: Pick<SdkQuestionProps, "entityTypes">;
                drillThroughQuestionHeight?: Height<string | number>;
                drillThroughQuestionProps?: DrillThroughQuestionProps;
                enableEntityNavigation?: boolean;
                hiddenParameters?: string[];
                initialParameters?: ParameterValues;
                onLoad?: (dashboard: MetabaseDashboard | null) => void;
                onLoadWithoutCards?: (dashboard: MetabaseDashboard | null) => void;
                onVisualizationChange?: (
                    visualization:
                        | "object"
                        | "table"
                        | "bar"
                        | "line"
                        | "pie"
                        | "scalar"
                        | "row"
                        | "area"
                        | "combo"
                        | "pivot"
                        | "smartscalar"
                        | "gauge"
                        | "progress"
                        | "funnel"
                        | "map"
                        | "scatter"
                        | "boxplot"
                        | "waterfall"
                        | "sankey"
                        | "list",
                ) => void;
                plugins?: MetabasePluginsConfig;
                renderDrillThroughQuestion?: () => ReactNode;
                style?: CSSProperties;
                token?: string | null;
                withCardTitle?: boolean;
                withDownloads?: boolean;
                withSubscriptions?: boolean;
                withTitle?: boolean;
            }
            Index

            Properties

            autoRefreshInterval? +InteractiveDashboardProps | Embedded analytics SDK API{% include docs/embedded-analytics-sdk-metadata.html %}

            Interface InteractiveDashboardProps

            interface InteractiveDashboardProps {
                autoRefreshInterval?: number;
                className?: string;
                dashboardId: string | number;
                dataPickerProps?: Pick<SdkQuestionProps, "entityTypes">;
                drillThroughQuestionHeight?: Height<string | number>;
                drillThroughQuestionProps?: DrillThroughQuestionProps;
                enableEntityNavigation?: boolean;
                hiddenParameters?: string[];
                initialParameters?: ParameterValues;
                onLoad?: (dashboard: MetabaseDashboard | null) => void;
                onLoadWithoutCards?: (dashboard: MetabaseDashboard | null) => void;
                onParametersChange?: (payload: ParameterChangePayload) => void;
                onVisualizationChange?: (
                    visualization:
                        | "object"
                        | "table"
                        | "bar"
                        | "line"
                        | "pie"
                        | "scalar"
                        | "row"
                        | "area"
                        | "combo"
                        | "pivot"
                        | "smartscalar"
                        | "gauge"
                        | "progress"
                        | "funnel"
                        | "map"
                        | "scatter"
                        | "boxplot"
                        | "waterfall"
                        | "sankey"
                        | "list",
                ) => void;
                parameters?: ParameterValues;
                plugins?: MetabasePluginsConfig;
                renderDrillThroughQuestion?: () => ReactNode;
                style?: CSSProperties;
                token?: string | null;
                withCardTitle?: boolean;
                withDownloads?: boolean;
                withSubscriptions?: boolean;
                withTitle?: boolean;
            }
            Index
          • OptionaldataPicker?: EmbeddingDataPicker

            Controls the menu for selecting data sources in questions. You can opt for the full data picker by setting dataPicker = "staged".

          • OptionalentityTypes?: EmbeddingEntityType[]

            An array that specifies which entity types are available in the data picker

          • Optionalheight?: Height<string | number>

            A number or string specifying a CSS size value that specifies the height of the component

            -
          • OptionalinitialSqlParameters?: SqlParameterValues

            Initial values for the SQL parameters.

            +
          • OptionalinitialCollection?: SdkCollectionId

            The collection to preselect in the save modal's collection picker. Unlike targetCollection, the picker remains visible and the user can choose a different collection. Ignored when targetCollection is set.

            +
          • OptionalinitialSqlParameters?: SqlParameterValues

            Initial values for SQL parameters, slug-keyed. Applied once on mount; user widget edits afterwards are not reflected back to the host. +
            +For each parameter: +

            +
              +
            • set to a value: that value is applied. +
            • +
            • set to null: strictly cleared, ignoring the parameter's default. +
            • +
            • omitted (or set to undefined): falls back to the parameter's default (or null if it has no default).
            • +
          • OptionalisSaveEnabled?: boolean

            Whether to show the save button.

          • OptionalonBeforeSave?: (
                question: MetabaseQuestion | undefined,
                context: { isNewQuestion: boolean },
            ) => Promise<void>

            A callback function that triggers before saving. Only relevant when isSaveEnabled = true

          • OptionalonRun?: (question: MetabaseQuestion | undefined) => void

            A callback function that triggers when a question is updated, including when a user clicks the Visualize button in the question editor

            @@ -61,6 +74,7 @@
          • OptionalwithAlerts?: boolean

            Enables the ability to set up alerts on the question.

          • OptionalwithChartTypeSelector?: boolean

            Determines whether the chart type selector and corresponding settings button are shown. Only relevant when using the default layout.

          • OptionalwithDownloads?: boolean

            Enables the ability to download results in the question.

            +
          • OptionalwithEditorButton?: boolean

            Determines whether the editor button is shown. Only relevant when using the default layout.

    enableEntityNavigation?: boolean

    When true, internal click behaviors (links to dashboards/questions) are preserved. When false (default for SDK), these click behaviors are filtered out.

    hiddenParameters?: string[]

    A list of parameters to hide. @@ -70,19 +84,45 @@

  • Combining initialParameters and hiddenParameters to declutter the user interface is fine.
  • -
    initialParameters?: ParameterValues

    Query parameters for the dashboard. For a single option, use a string value, and use a list of strings for multiple options. +

    initialParameters?: ParameterValues

    Initial values for query parameters, slug-keyed. Applied once on mount; user widget edits afterwards are not reflected back to the host. +
    +For each parameter:

      +
    • set to a value (string for a single option, array of strings for multiple): that value is applied. +
    • +
    • set to null: strictly cleared, ignoring the parameter's default. +
    • +
    • omitted (or set to undefined): falls back to the parameter's default (or null if it has no default). +
      +
    • Combining initialParameters and hiddenParameters to filter data on the frontend is a security risk.
    • Combining initialParameters and hiddenParameters to declutter the user interface is fine.
    onLoad?: (dashboard: MetabaseDashboard | null) => void

    Callback that is called when the dashboard is loaded.

    onLoadWithoutCards?: (dashboard: MetabaseDashboard | null) => void

    Callback that is called when the dashboard is loaded without cards.

    +
    onParametersChange?: (payload: ParameterChangePayload) => void

    Fires on parameters change. The payload's source distinguishes the initial state on load ('initial-state'), user edits in the UI ('manual-change'), and auto-updates ('auto-change').

    onVisualizationChange?: (
        visualization:
            | "object"
            | "table"
            | "bar"
            | "line"
            | "pie"
            | "scalar"
            | "row"
            | "area"
            | "combo"
            | "pivot"
            | "smartscalar"
            | "gauge"
            | "progress"
            | "funnel"
            | "map"
            | "scatter"
            | "boxplot"
            | "waterfall"
            | "sankey"
            | "list",
    ) => void

    A callback function that triggers when a question is opened from a dashboard card or when the user changes the visualization type of a question.

    Type Declaration

      • (
            visualization:
                | "object"
                | "table"
                | "bar"
                | "line"
                | "pie"
                | "scalar"
                | "row"
                | "area"
                | "combo"
                | "pivot"
                | "smartscalar"
                | "gauge"
                | "progress"
                | "funnel"
                | "map"
                | "scatter"
                | "boxplot"
                | "waterfall"
                | "sankey"
                | "list",
        ): void
      • Parameters

        • visualization:
              | "object"
              | "table"
              | "bar"
              | "line"
              | "pie"
              | "scalar"
              | "row"
              | "area"
              | "combo"
              | "pivot"
              | "smartscalar"
              | "gauge"
              | "progress"
              | "funnel"
              | "map"
              | "scatter"
              | "boxplot"
              | "waterfall"
              | "sankey"
              | "list"

          the new visualization type

          -

        Returns void

    Additional mapper function to override or add drill-down menu. See the implementing custom actions section for more details.

    +

    Returns void

    parameters?: ParameterValues

    Controlled parameter values, slug-keyed. On every render, this object replaces the dashboard's parameter values: +

    +
      +
    • a parameter set to a value uses that value. +
    • +
    • a parameter set to null is cleared, even if it has a default. +
    • +
    • a parameter omitted from the object (or set to undefined) uses its default (or null if it has no default). +
      +
      +Pair with onParametersChange to stay in sync with user edits. +
    • +
    • Combining parameters and hiddenParameters to filter data on the frontend is a security risk. +
    • +
    • Combining parameters and hiddenParameters to declutter the user interface is fine.
    • +
    +

    Additional mapper function to override or add drill-down menu. See the implementing custom actions section for more details.

    renderDrillThroughQuestion?: () => ReactNode

    A custom React component to render the question layout. Use namespaced InteractiveQuestion components to build the layout.

    A custom style object to be added to the root element.

    @@ -90,4 +130,4 @@
    withDownloads?: boolean

    Whether to hide the download button.

    withSubscriptions?: boolean

    Whether to show the subscriptions button.

    withTitle?: boolean

    Whether the dashboard should display a title.

    -

    +

    diff --git a/_docs/master/embedding/sdk/api/InteractiveQuestion.html b/_docs/master/embedding/sdk/api/InteractiveQuestion.html index ebcb94cd92..5d6e65094b 100644 --- a/_docs/master/embedding/sdk/api/InteractiveQuestion.html +++ b/_docs/master/embedding/sdk/api/InteractiveQuestion.html @@ -15,20 +15,59 @@
  • OptionalentityTypes?: EmbeddingEntityType[]

    An array that specifies which entity types are available in the data picker

  • Optionalheight?: Height<string | number>

    A number or string specifying a CSS size value that specifies the height of the component

  • OptionalhiddenParameters?: string[]

    A list of parameters to hide.

    -
  • OptionalinitialSqlParameters?: SqlParameterValues

    Initial values for the SQL parameters.

    +
  • OptionalinitialCollection?: SdkCollectionId

    The collection to preselect in the save modal's collection picker. Unlike targetCollection, the picker remains visible and the user can choose a different collection. Ignored when targetCollection is set.

    +
  • OptionalinitialSqlParameters?: SqlParameterValues

    Initial values for SQL parameters, slug-keyed. Applied once on mount; user widget edits afterwards are not reflected back to the host. +
    +For each parameter: +

    +
      +
    • set to a value: that value is applied. +
    • +
    • set to null: strictly cleared, ignoring the parameter's default. +
    • +
    • omitted (or set to undefined): falls back to the parameter's default (or null if it has no default).
    • +
  • OptionalisSaveEnabled?: boolean

    Whether to show the save button.

  • OptionalonBeforeSave?: (
        question: MetabaseQuestion | undefined,
        context: { isNewQuestion: boolean },
    ) => Promise<void>

    A callback function that triggers before saving. Only relevant when isSaveEnabled = true

  • OptionalonNavigateBack?: () => void

    A callback function that triggers when a user clicks the back button.

  • OptionalonRun?: (question: MetabaseQuestion | undefined) => void

    A callback function that triggers when a question is updated, including when a user clicks the Visualize button in the question editor

  • OptionalonSave?: (
        question: MetabaseQuestion,
        context: { dashboardTabId?: number; isNewQuestion: boolean },
    ) => void

    A callback function that triggers when a user saves the question. Only relevant when isSaveEnabled = true

    +
  • OptionalonSqlParametersChange?: (payload: SqlParameterChangePayload) => void

    Fires on SQL parameters change. The payload's source distinguishes the initial state on load ('initial-state'), user edits in the UI ('manual-change'), and auto-updates ('auto-change').

  • OptionalonVisualizationChange?: (
        display:
            | "object"
            | "table"
            | "bar"
            | "line"
            | "pie"
            | "scalar"
            | "row"
            | "area"
            | "combo"
            | "pivot"
            | "smartscalar"
            | "gauge"
            | "progress"
            | "funnel"
            | "map"
            | "scatter"
            | "boxplot"
            | "waterfall"
            | "sankey"
            | "list",
    ) => void

    A callback function that triggers when the visualization type changes.

    -
  • Optionalplugins?: MetabasePluginsConfig
  • OptionalquestionId?: SdkQuestionId | null
  • Optionalstyle?: CSSProperties

    A custom style object to be added to the root element.

    +
  • Optionalplugins?: MetabasePluginsConfig
  • Optionalquery?: undefined
  • OptionalquestionId?: SdkQuestionId | null

    The ID of the question. +
    +This is either: +

    +
      +
    • the numerical ID when accessing a question link, i.e. http://localhost:3000/question/1-my-question where the ID is 1 +
    • +
    • the string ID found in the entity_id key of the question object when using the API directly or using the SDK Collection Browser to return data +
    • +
    • new to show the notebook editor for creating new questions +
    • +
    • new-native to show the SQL editor for creating new native questions
    • +
    +
  • OptionalsqlParameters?: SqlParameterValues

    Controlled SQL parameter values, slug-keyed. On every render, this object replaces the question's parameter values: +

    +
      +
    • a parameter set to a value uses that value. +
    • +
    • a parameter set to null is cleared, even if it has a default. +
    • +
    • a parameter omitted from the object (or set to undefined) uses its default (or null if it has no default). +
      +
      +Pair with onSqlParametersChange to stay in sync with user edits.
    • +
    +
  • Optionalstyle?: CSSProperties

    A custom style object to be added to the root element.

  • OptionaltargetCollection?: SdkCollectionId

    The collection to save the question to. This will hide the collection picker from the save modal. Only applicable to interactive questions.

  • Optionaltitle?: SdkQuestionTitleProps

    Determines whether the question title is displayed, and allows a custom title to be displayed instead of the default question title. Shown by default.

    +
  • Optionaltoken?: string | null

    A valid JWT token for the guest embed.

  • Optionalwidth?: Width<string | number>

    A number or string specifying a CSS size value that specifies the width of the component

  • OptionalwithAlerts?: boolean

    Enables the ability to set up alerts on the question.

  • OptionalwithChartTypeSelector?: boolean

    Determines whether the chart type selector and corresponding settings button are shown. Only relevant when using the default layout.

  • OptionalwithDownloads?: boolean

    Enables the ability to download results in the question.

    +
  • OptionalwithEditorButton?: boolean

    Determines whether the editor button is shown. Only relevant when using the default layout.

  • Returns Element

    Index

    InteractiveQuestion

    BackButton Breakout BreakoutDropdown diff --git a/_docs/master/embedding/sdk/api/InteractiveQuestionProps.html b/_docs/master/embedding/sdk/api/InteractiveQuestionProps.html index 191ad03973..f99127b9a1 100644 --- a/_docs/master/embedding/sdk/api/InteractiveQuestionProps.html +++ b/_docs/master/embedding/sdk/api/InteractiveQuestionProps.html @@ -9,45 +9,90 @@ layout: docs-api --- -InteractiveQuestionProps | Embedded analytics SDK API{% include docs/embedded-analytics-sdk-metadata.html %}

    Interface InteractiveQuestionProps

    interface InteractiveQuestionProps {
        className?: string;
        dataPicker?: EmbeddingDataPicker;
        entityTypes?: EmbeddingEntityType[];
        height?: Height<string | number>;
        hiddenParameters?: string[];
        initialSqlParameters?: SqlParameterValues;
        isSaveEnabled?: boolean;
        onBeforeSave?: (
            question: MetabaseQuestion | undefined,
            context: { isNewQuestion: boolean },
        ) => Promise<void>;
        onNavigateBack?: () => void;
        onRun?: (question: MetabaseQuestion | undefined) => void;
        onSave?: (
            question: MetabaseQuestion,
            context: { dashboardTabId?: number; isNewQuestion: boolean },
        ) => void;
        onVisualizationChange?: (
            display:
                | "object"
                | "table"
                | "bar"
                | "line"
                | "pie"
                | "scalar"
                | "row"
                | "area"
                | "combo"
                | "pivot"
                | "smartscalar"
                | "gauge"
                | "progress"
                | "funnel"
                | "map"
                | "scatter"
                | "boxplot"
                | "waterfall"
                | "sankey"
                | "list",
        ) => void;
        plugins?: MetabasePluginsConfig;
        questionId?: SdkQuestionId
        | null;
        style?: CSSProperties;
        targetCollection?: SdkCollectionId;
        title?: SdkQuestionTitleProps;
        width?: Width<string | number>;
        withAlerts?: boolean;
        withChartTypeSelector?: boolean;
        withDownloads?: boolean;
    }
    Index

    Properties

    className? +InteractiveQuestionProps | Embedded analytics SDK API{% include docs/embedded-analytics-sdk-metadata.html %}

    Interface InteractiveQuestionProps

    interface InteractiveQuestionProps {
        className?: string;
        dataPicker?: EmbeddingDataPicker;
        entityTypes?: EmbeddingEntityType[];
        height?: Height<string | number>;
        hiddenParameters?: string[];
        initialCollection?: SdkCollectionId;
        initialSqlParameters?: SqlParameterValues;
        isSaveEnabled?: boolean;
        onBeforeSave?: (
            question: MetabaseQuestion | undefined,
            context: { isNewQuestion: boolean },
        ) => Promise<void>;
        onNavigateBack?: () => void;
        onRun?: (question: MetabaseQuestion | undefined) => void;
        onSave?: (
            question: MetabaseQuestion,
            context: { dashboardTabId?: number; isNewQuestion: boolean },
        ) => void;
        onSqlParametersChange?: (payload: SqlParameterChangePayload) => void;
        onVisualizationChange?: (
            display:
                | "object"
                | "table"
                | "bar"
                | "line"
                | "pie"
                | "scalar"
                | "row"
                | "area"
                | "combo"
                | "pivot"
                | "smartscalar"
                | "gauge"
                | "progress"
                | "funnel"
                | "map"
                | "scatter"
                | "boxplot"
                | "waterfall"
                | "sankey"
                | "list",
        ) => void;
        plugins?: MetabasePluginsConfig;
        query?: undefined;
        questionId?: SdkQuestionId
        | null;
        sqlParameters?: SqlParameterValues;
        style?: CSSProperties;
        targetCollection?: SdkCollectionId;
        title?: SdkQuestionTitleProps;
        token?: string | null;
        width?: Width<string | number>;
        withAlerts?: boolean;
        withChartTypeSelector?: boolean;
        withDownloads?: boolean;
        withEditorButton?: boolean;
    }
    Index

    Properties

    className?: string

    A custom class name to be added to the root element.

    dataPicker?: EmbeddingDataPicker

    Controls the menu for selecting data sources in questions. You can opt for the full data picker by setting dataPicker = "staged".

    entityTypes?: EmbeddingEntityType[]

    An array that specifies which entity types are available in the data picker

    height?: Height<string | number>

    A number or string specifying a CSS size value that specifies the height of the component

    hiddenParameters?: string[]

    A list of parameters to hide.

    -
    initialSqlParameters?: SqlParameterValues

    Initial values for the SQL parameters.

    +
    initialCollection?: SdkCollectionId

    The collection to preselect in the save modal's collection picker. Unlike targetCollection, the picker remains visible and the user can choose a different collection. Ignored when targetCollection is set.

    +
    initialSqlParameters?: SqlParameterValues

    Initial values for SQL parameters, slug-keyed. Applied once on mount; user widget edits afterwards are not reflected back to the host. +
    +For each parameter: +

    +
      +
    • set to a value: that value is applied. +
    • +
    • set to null: strictly cleared, ignoring the parameter's default. +
    • +
    • omitted (or set to undefined): falls back to the parameter's default (or null if it has no default).
    • +
    isSaveEnabled?: boolean

    Whether to show the save button.

    onBeforeSave?: (
        question: MetabaseQuestion | undefined,
        context: { isNewQuestion: boolean },
    ) => Promise<void>

    A callback function that triggers before saving. Only relevant when isSaveEnabled = true

    onNavigateBack?: () => void

    A callback function that triggers when a user clicks the back button.

    onRun?: (question: MetabaseQuestion | undefined) => void

    A callback function that triggers when a question is updated, including when a user clicks the Visualize button in the question editor

    onSave?: (
        question: MetabaseQuestion,
        context: { dashboardTabId?: number; isNewQuestion: boolean },
    ) => void

    A callback function that triggers when a user saves the question. Only relevant when isSaveEnabled = true

    +
    onSqlParametersChange?: (payload: SqlParameterChangePayload) => void

    Fires on SQL parameters change. The payload's source distinguishes the initial state on load ('initial-state'), user edits in the UI ('manual-change'), and auto-updates ('auto-change').

    onVisualizationChange?: (
        display:
            | "object"
            | "table"
            | "bar"
            | "line"
            | "pie"
            | "scalar"
            | "row"
            | "area"
            | "combo"
            | "pivot"
            | "smartscalar"
            | "gauge"
            | "progress"
            | "funnel"
            | "map"
            | "scatter"
            | "boxplot"
            | "waterfall"
            | "sankey"
            | "list",
    ) => void

    A callback function that triggers when the visualization type changes.

    Type Declaration

      • (
            display:
                | "object"
                | "table"
                | "bar"
                | "line"
                | "pie"
                | "scalar"
                | "row"
                | "area"
                | "combo"
                | "pivot"
                | "smartscalar"
                | "gauge"
                | "progress"
                | "funnel"
                | "map"
                | "scatter"
                | "boxplot"
                | "waterfall"
                | "sankey"
                | "list",
        ): void
      • Parameters

        • display:
              | "object"
              | "table"
              | "bar"
              | "line"
              | "pie"
              | "scalar"
              | "row"
              | "area"
              | "combo"
              | "pivot"
              | "smartscalar"
              | "gauge"
              | "progress"
              | "funnel"
              | "map"
              | "scatter"
              | "boxplot"
              | "waterfall"
              | "sankey"
              | "list"

          the new display type

          -

        Returns void

    questionId?: SdkQuestionId | null

    A custom style object to be added to the root element.

    +

    Returns void

    query?: undefined
    questionId?: SdkQuestionId | null

    The ID of the question. +
    +This is either: +

    +
      +
    • the numerical ID when accessing a question link, i.e. http://localhost:3000/question/1-my-question where the ID is 1 +
    • +
    • the string ID found in the entity_id key of the question object when using the API directly or using the SDK Collection Browser to return data +
    • +
    • new to show the notebook editor for creating new questions +
    • +
    • new-native to show the SQL editor for creating new native questions
    • +
    +
    sqlParameters?: SqlParameterValues

    Controlled SQL parameter values, slug-keyed. On every render, this object replaces the question's parameter values: +

    +
      +
    • a parameter set to a value uses that value. +
    • +
    • a parameter set to null is cleared, even if it has a default. +
    • +
    • a parameter omitted from the object (or set to undefined) uses its default (or null if it has no default). +
      +
      +Pair with onSqlParametersChange to stay in sync with user edits.
    • +
    +

    A custom style object to be added to the root element.

    targetCollection?: SdkCollectionId

    The collection to save the question to. This will hide the collection picker from the save modal. Only applicable to interactive questions.

    Determines whether the question title is displayed, and allows a custom title to be displayed instead of the default question title. Shown by default.

    +
    token?: string | null

    A valid JWT token for the guest embed.

    width?: Width<string | number>

    A number or string specifying a CSS size value that specifies the width of the component

    withAlerts?: boolean

    Enables the ability to set up alerts on the question.

    withChartTypeSelector?: boolean

    Determines whether the chart type selector and corresponding settings button are shown. Only relevant when using the default layout.

    withDownloads?: boolean

    Enables the ability to download results in the question.

    -

    +
    withEditorButton?: boolean

    Determines whether the editor button is shown. Only relevant when using the default layout.

    +

    diff --git a/_docs/master/embedding/sdk/api/MetabaseColorKey.html b/_docs/master/embedding/sdk/api/MetabaseColorKey.html index c47c6e6284..1625310d29 100644 --- a/_docs/master/embedding/sdk/api/MetabaseColorKey.html +++ b/_docs/master/embedding/sdk/api/MetabaseColorKey.html @@ -9,6 +9,6 @@ layout: docs-api --- -MetabaseColorKey | Embedded analytics SDK API{% include docs/embedded-analytics-sdk-metadata.html %}

    Type Alias MetabaseColorKey

    MetabaseColorKey:
        | | "accent0"
        | "accent0-light"
        | "accent0-dark"
        | "accent1"
        | "accent1-light"
        | "accent1-dark"
        | "accent2"
        | "accent2-light"
        | "accent2-dark"
        | "accent3"
        | "accent3-light"
        | "accent3-dark"
        | "accent4"
        | "accent4-light"
        | "accent4-dark"
        | "accent5"
        | "accent5-light"
        | "accent5-dark"
        | "accent6"
        | "accent6-light"
        | "accent6-dark"
        | "accent7"
        | "accent7-light"
        | "accent7-dark"
        | "accent-gray"
        | "accent-gray-light"
        | "accent-gray-dark"
        | ProtectedColorKey
        | "background-brand"
        | "background-filter"
        | "background-disabled"
        | "background-disabled-inverse"
        | "background-error"
        | "background-error-secondary"
        | "background-highlight"
        | "background-hover"
        | "background-info"
        | "background-primary"
        | "background-primary-inverse"
        | "background-secondary"
        | "background-secondary-inverse"
        | "background-selected"
        | "background-success"
        | "background-tertiary"
        | "background-tertiary-inverse"
        | "background-warning"
        | "border"
        | "border-brand"
        | "border-filter"
        | "border-strong"
        | "border-stronger"
        | "border-subtle"
        | "brand"
        | "brand-hover"
        | "bronze"
        | "copper"
        | "danger"
        | "error"
        | "filter"
        | "focus"
        | "gold"
        | "icon-brand"
        | "icon-disabled"
        | "icon-primary"
        | "icon-secondary"
        | "illustration-brand-secondary"
        | "illustration-brand-tertiary"
        | "info"
        | "overlay"
        | "saturated-blue"
        | "saturated-green"
        | "saturated-purple"
        | "saturated-red"
        | "saturated-yellow"
        | "shadow"
        | "silver"
        | "success"
        | "success-secondary"
        | "summarize"
        | "switch-off"
        | "syntax-parameters"
        | "syntax-parameters-active"
        | "text-brand"
        | "text-filter"
        | "text-hover"
        | "text-primary"
        | "text-primary-inverse"
        | "text-secondary"
        | "text-secondary-inverse"
        | "text-secondary-opaque"
        | "text-selected"
        | "text-tertiary"
        | "text-tertiary-inverse"
        | "tooltip-background"
        | "tooltip-background-focused"
        | "tooltip-text"
        | "tooltip-text-secondary"
        | "warning"
        | "white"

    All color keys available in Metabase themes.

    +MetabaseColorKey | Embedded analytics SDK API{% include docs/embedded-analytics-sdk-metadata.html %}

    Type Alias MetabaseColorKey

    MetabaseColorKey:
        | | "accent0"
        | "accent0-light"
        | "accent0-dark"
        | "accent1"
        | "accent1-light"
        | "accent1-dark"
        | "accent2"
        | "accent2-light"
        | "accent2-dark"
        | "accent3"
        | "accent3-light"
        | "accent3-dark"
        | "accent4"
        | "accent4-light"
        | "accent4-dark"
        | "accent5"
        | "accent5-light"
        | "accent5-dark"
        | "accent6"
        | "accent6-light"
        | "accent6-dark"
        | "accent7"
        | "accent7-light"
        | "accent7-dark"
        | "accent-gray"
        | "accent-gray-light"
        | "accent-gray-dark"
        | ProtectedColorKey
        | "background-brand"
        | "background-filter"
        | "background-disabled"
        | "background-disabled-inverse"
        | "background-error"
        | "background-error-secondary"
        | "background-highlight"
        | "background-hover"
        | "background-info"
        | "background-primary"
        | "background-primary-inverse"
        | "background-secondary"
        | "background-secondary-inverse"
        | "background-selected"
        | "background-success"
        | "background-success-secondary"
        | "background-tertiary"
        | "background-tertiary-inverse"
        | "background-warning"
        | "background-warning-secondary"
        | "border"
        | "border-brand"
        | "border-filter"
        | "border-strong"
        | "border-stronger"
        | "border-subtle"
        | "brand"
        | "brand-hover"
        | "bronze"
        | "copper"
        | "danger"
        | "error"
        | "filter"
        | "focus"
        | "gold"
        | "icon-brand"
        | "icon-disabled"
        | "icon-primary"
        | "icon-secondary"
        | "illustration-brand-secondary"
        | "illustration-brand-tertiary"
        | "info"
        | "overlay"
        | "saturated-blue"
        | "saturated-green"
        | "saturated-purple"
        | "saturated-red"
        | "saturated-yellow"
        | "shadow"
        | "silver"
        | "success"
        | "success-secondary"
        | "summarize"
        | "switch-off"
        | "syntax-parameters"
        | "syntax-parameters-active"
        | "text-brand"
        | "text-filter"
        | "text-hover"
        | "text-primary"
        | "text-primary-inverse"
        | "text-secondary"
        | "text-secondary-inverse"
        | "text-secondary-opaque"
        | "text-selected"
        | "text-tertiary"
        | "text-tertiary-inverse"
        | "tooltip-background"
        | "tooltip-background-focused"
        | "tooltip-text"
        | "tooltip-text-secondary"
        | "warning"
        | "white"

    All color keys available in Metabase themes.

    Both the light and dark theme must define all of these colors.

    diff --git a/_docs/master/embedding/sdk/api/MetabaseEmbeddingColorKeyV2.html b/_docs/master/embedding/sdk/api/MetabaseEmbeddingColorKeyV2.html index b95f25dc2f..5dd99ec692 100644 --- a/_docs/master/embedding/sdk/api/MetabaseEmbeddingColorKeyV2.html +++ b/_docs/master/embedding/sdk/api/MetabaseEmbeddingColorKeyV2.html @@ -9,6 +9,6 @@ layout: docs-api --- -MetabaseEmbeddingColorKeyV2 | Embedded analytics SDK API{% include docs/embedded-analytics-sdk-metadata.html %}

    Type Alias MetabaseEmbeddingColorKeyV2

    MetabaseEmbeddingColorKeyV2: Exclude<
        | "filter"
        | "info"
        | "warning"
        | "success"
        | "error"
        | "shadow"
        | "accent0"
        | "accent0-light"
        | "accent0-dark"
        | "accent1"
        | "accent1-light"
        | "accent1-dark"
        | "accent2"
        | "accent2-light"
        | "accent2-dark"
        | "accent3"
        | "accent3-light"
        | "accent3-dark"
        | "accent4"
        | "accent4-light"
        | "accent4-dark"
        | "accent5"
        | "accent5-light"
        | "accent5-dark"
        | "accent6"
        | "accent6-light"
        | "accent6-dark"
        | "accent7"
        | "accent7-light"
        | "accent7-dark"
        | "accent-gray"
        | "accent-gray-light"
        | "accent-gray-dark"
        | "metabase-brand"
        | "metabase-brand-hover"
        | "admin-navbar"
        | "admin-navbar-secondary"
        | "admin-navbar-inverse"
        | "upsell-primary"
        | "upsell-secondary"
        | "upsell-gem"
        | "background-brand"
        | "background-filter"
        | "background-disabled"
        | "background-disabled-inverse"
        | "background-error"
        | "background-error-secondary"
        | "background-highlight"
        | "background-hover"
        | "background-info"
        | "background-primary"
        | "background-primary-inverse"
        | "background-secondary"
        | "background-secondary-inverse"
        | "background-selected"
        | "background-success"
        | "background-tertiary"
        | "background-tertiary-inverse"
        | "background-warning"
        | "border"
        | "border-brand"
        | "border-filter"
        | "border-strong"
        | "border-stronger"
        | "border-subtle"
        | "brand"
        | "brand-hover"
        | "bronze"
        | "copper"
        | "danger"
        | "focus"
        | "gold"
        | "icon-brand"
        | "icon-disabled"
        | "icon-primary"
        | "icon-secondary"
        | "illustration-brand-secondary"
        | "illustration-brand-tertiary"
        | "overlay"
        | "saturated-blue"
        | "saturated-green"
        | "saturated-purple"
        | "saturated-red"
        | "saturated-yellow"
        | "silver"
        | "success-secondary"
        | "summarize"
        | "switch-off"
        | "syntax-parameters"
        | "syntax-parameters-active"
        | "text-brand"
        | "text-filter"
        | "text-hover"
        | "text-primary"
        | "text-primary-inverse"
        | "text-secondary"
        | "text-secondary-inverse"
        | "text-secondary-opaque"
        | "text-selected"
        | "text-tertiary"
        | "text-tertiary-inverse"
        | "tooltip-background"
        | "tooltip-background-focused"
        | "tooltip-text"
        | "tooltip-text-secondary"
        | "white",
        ProtectedColorKey,
    >

    Color keys available for theming in modular embedding.

    +MetabaseEmbeddingColorKeyV2 | Embedded analytics SDK API{% include docs/embedded-analytics-sdk-metadata.html %}

    Type Alias MetabaseEmbeddingColorKeyV2

    MetabaseEmbeddingColorKeyV2: Exclude<
        | "filter"
        | "info"
        | "warning"
        | "success"
        | "error"
        | "shadow"
        | "accent0"
        | "accent0-light"
        | "accent0-dark"
        | "accent1"
        | "accent1-light"
        | "accent1-dark"
        | "accent2"
        | "accent2-light"
        | "accent2-dark"
        | "accent3"
        | "accent3-light"
        | "accent3-dark"
        | "accent4"
        | "accent4-light"
        | "accent4-dark"
        | "accent5"
        | "accent5-light"
        | "accent5-dark"
        | "accent6"
        | "accent6-light"
        | "accent6-dark"
        | "accent7"
        | "accent7-light"
        | "accent7-dark"
        | "accent-gray"
        | "accent-gray-light"
        | "accent-gray-dark"
        | "metabase-brand"
        | "metabase-brand-hover"
        | "admin-navbar"
        | "admin-navbar-secondary"
        | "admin-navbar-inverse"
        | "upsell-primary"
        | "upsell-secondary"
        | "upsell-gem"
        | "background-brand"
        | "background-filter"
        | "background-disabled"
        | "background-disabled-inverse"
        | "background-error"
        | "background-error-secondary"
        | "background-highlight"
        | "background-hover"
        | "background-info"
        | "background-primary"
        | "background-primary-inverse"
        | "background-secondary"
        | "background-secondary-inverse"
        | "background-selected"
        | "background-success"
        | "background-success-secondary"
        | "background-tertiary"
        | "background-tertiary-inverse"
        | "background-warning"
        | "background-warning-secondary"
        | "border"
        | "border-brand"
        | "border-filter"
        | "border-strong"
        | "border-stronger"
        | "border-subtle"
        | "brand"
        | "brand-hover"
        | "bronze"
        | "copper"
        | "danger"
        | "focus"
        | "gold"
        | "icon-brand"
        | "icon-disabled"
        | "icon-primary"
        | "icon-secondary"
        | "illustration-brand-secondary"
        | "illustration-brand-tertiary"
        | "overlay"
        | "saturated-blue"
        | "saturated-green"
        | "saturated-purple"
        | "saturated-red"
        | "saturated-yellow"
        | "silver"
        | "success-secondary"
        | "summarize"
        | "switch-off"
        | "syntax-parameters"
        | "syntax-parameters-active"
        | "text-brand"
        | "text-filter"
        | "text-hover"
        | "text-primary"
        | "text-primary-inverse"
        | "text-secondary"
        | "text-secondary-inverse"
        | "text-secondary-opaque"
        | "text-selected"
        | "text-tertiary"
        | "text-tertiary-inverse"
        | "tooltip-background"
        | "tooltip-background-focused"
        | "tooltip-text"
        | "tooltip-text-secondary"
        | "white",
        ProtectedColorKey,
    >

    Color keys available for theming in modular embedding.

    Excludes protected colors such as admin colors that should not be exposed.

    diff --git a/_docs/master/embedding/sdk/api/MetabaseEmbeddingThemeV2.html b/_docs/master/embedding/sdk/api/MetabaseEmbeddingThemeV2.html index 39481d5ae2..92f61c19f0 100644 --- a/_docs/master/embedding/sdk/api/MetabaseEmbeddingThemeV2.html +++ b/_docs/master/embedding/sdk/api/MetabaseEmbeddingThemeV2.html @@ -10,11 +10,11 @@ --- MetabaseEmbeddingThemeV2 | Embedded analytics SDK API{% include docs/embedded-analytics-sdk-metadata.html %}

    Interface MetabaseEmbeddingThemeV2

    Version 2 theme configuration for embedded Metabase components.

    -
    interface MetabaseEmbeddingThemeV2 {
        chartColors?: ChartColorV2[];
        colors?: Partial<
            Record<
                | "filter"
                | "info"
                | "warning"
                | "success"
                | "error"
                | "shadow"
                | "accent0-light"
                | "accent0-dark"
                | "accent1-light"
                | "accent1-dark"
                | "accent2-light"
                | "accent2-dark"
                | "accent3-light"
                | "accent3-dark"
                | "accent4-light"
                | "accent4-dark"
                | "accent5-light"
                | "accent5-dark"
                | "accent6-light"
                | "accent6-dark"
                | "accent7-light"
                | "accent7-dark"
                | "accent-gray"
                | "accent-gray-light"
                | "accent-gray-dark"
                | "background-brand"
                | "background-filter"
                | "background-disabled"
                | "background-disabled-inverse"
                | "background-error"
                | "background-error-secondary"
                | "background-highlight"
                | "background-hover"
                | "background-info"
                | "background-primary"
                | "background-primary-inverse"
                | "background-secondary"
                | "background-secondary-inverse"
                | "background-selected"
                | "background-success"
                | "background-tertiary"
                | "background-tertiary-inverse"
                | "background-warning"
                | "border"
                | "border-brand"
                | "border-filter"
                | "border-strong"
                | "border-stronger"
                | "border-subtle"
                | "brand"
                | "brand-hover"
                | "bronze"
                | "copper"
                | "danger"
                | "focus"
                | "gold"
                | "icon-brand"
                | "icon-disabled"
                | "icon-primary"
                | "icon-secondary"
                | "illustration-brand-secondary"
                | "illustration-brand-tertiary"
                | "overlay"
                | "saturated-blue"
                | "saturated-green"
                | "saturated-purple"
                | "saturated-red"
                | "saturated-yellow"
                | "silver"
                | "success-secondary"
                | "summarize"
                | "switch-off"
                | "syntax-parameters"
                | "syntax-parameters-active"
                | "text-brand"
                | "text-filter"
                | "text-hover"
                | "text-primary"
                | "text-primary-inverse"
                | "text-secondary"
                | "text-secondary-inverse"
                | "text-secondary-opaque"
                | "text-selected"
                | "text-tertiary"
                | "text-tertiary-inverse"
                | "tooltip-background"
                | "tooltip-background-focused"
                | "tooltip-text"
                | "tooltip-text-secondary"
                | "white",
                string,
            >,
        >;
        version: 2;
    }
    Index

    Properties

    interface MetabaseEmbeddingThemeV2 {
        chartColors?: ChartColorV2[];
        colors?: Partial<
            Record<
                | "filter"
                | "info"
                | "warning"
                | "success"
                | "error"
                | "shadow"
                | "accent0-light"
                | "accent0-dark"
                | "accent1-light"
                | "accent1-dark"
                | "accent2-light"
                | "accent2-dark"
                | "accent3-light"
                | "accent3-dark"
                | "accent4-light"
                | "accent4-dark"
                | "accent5-light"
                | "accent5-dark"
                | "accent6-light"
                | "accent6-dark"
                | "accent7-light"
                | "accent7-dark"
                | "accent-gray"
                | "accent-gray-light"
                | "accent-gray-dark"
                | "background-brand"
                | "background-filter"
                | "background-disabled"
                | "background-disabled-inverse"
                | "background-error"
                | "background-error-secondary"
                | "background-highlight"
                | "background-hover"
                | "background-info"
                | "background-primary"
                | "background-primary-inverse"
                | "background-secondary"
                | "background-secondary-inverse"
                | "background-selected"
                | "background-success"
                | "background-success-secondary"
                | "background-tertiary"
                | "background-tertiary-inverse"
                | "background-warning"
                | "background-warning-secondary"
                | "border"
                | "border-brand"
                | "border-filter"
                | "border-strong"
                | "border-stronger"
                | "border-subtle"
                | "brand"
                | "brand-hover"
                | "bronze"
                | "copper"
                | "danger"
                | "focus"
                | "gold"
                | "icon-brand"
                | "icon-disabled"
                | "icon-primary"
                | "icon-secondary"
                | "illustration-brand-secondary"
                | "illustration-brand-tertiary"
                | "overlay"
                | "saturated-blue"
                | "saturated-green"
                | "saturated-purple"
                | "saturated-red"
                | "saturated-yellow"
                | "silver"
                | "success-secondary"
                | "summarize"
                | "switch-off"
                | "syntax-parameters"
                | "syntax-parameters-active"
                | "text-brand"
                | "text-filter"
                | "text-hover"
                | "text-primary"
                | "text-primary-inverse"
                | "text-secondary"
                | "text-secondary-inverse"
                | "text-secondary-opaque"
                | "text-selected"
                | "text-tertiary"
                | "text-tertiary-inverse"
                | "tooltip-background"
                | "tooltip-background-focused"
                | "tooltip-text"
                | "tooltip-text-secondary"
                | "white",
                string,
            >,
        >;
        version: 2;
    }
    Index

    Properties

    chartColors?: ChartColorV2[]

    Chart colors overrides. Each color can be a string or an object with base/tint/shade.

    -
    colors?: Partial<
        Record<
            | "filter"
            | "info"
            | "warning"
            | "success"
            | "error"
            | "shadow"
            | "accent0-light"
            | "accent0-dark"
            | "accent1-light"
            | "accent1-dark"
            | "accent2-light"
            | "accent2-dark"
            | "accent3-light"
            | "accent3-dark"
            | "accent4-light"
            | "accent4-dark"
            | "accent5-light"
            | "accent5-dark"
            | "accent6-light"
            | "accent6-dark"
            | "accent7-light"
            | "accent7-dark"
            | "accent-gray"
            | "accent-gray-light"
            | "accent-gray-dark"
            | "background-brand"
            | "background-filter"
            | "background-disabled"
            | "background-disabled-inverse"
            | "background-error"
            | "background-error-secondary"
            | "background-highlight"
            | "background-hover"
            | "background-info"
            | "background-primary"
            | "background-primary-inverse"
            | "background-secondary"
            | "background-secondary-inverse"
            | "background-selected"
            | "background-success"
            | "background-tertiary"
            | "background-tertiary-inverse"
            | "background-warning"
            | "border"
            | "border-brand"
            | "border-filter"
            | "border-strong"
            | "border-stronger"
            | "border-subtle"
            | "brand"
            | "brand-hover"
            | "bronze"
            | "copper"
            | "danger"
            | "focus"
            | "gold"
            | "icon-brand"
            | "icon-disabled"
            | "icon-primary"
            | "icon-secondary"
            | "illustration-brand-secondary"
            | "illustration-brand-tertiary"
            | "overlay"
            | "saturated-blue"
            | "saturated-green"
            | "saturated-purple"
            | "saturated-red"
            | "saturated-yellow"
            | "silver"
            | "success-secondary"
            | "summarize"
            | "switch-off"
            | "syntax-parameters"
            | "syntax-parameters-active"
            | "text-brand"
            | "text-filter"
            | "text-hover"
            | "text-primary"
            | "text-primary-inverse"
            | "text-secondary"
            | "text-secondary-inverse"
            | "text-secondary-opaque"
            | "text-selected"
            | "text-tertiary"
            | "text-tertiary-inverse"
            | "tooltip-background"
            | "tooltip-background-focused"
            | "tooltip-text"
            | "tooltip-text-secondary"
            | "white",
            string,
        >,
    >

    Color overrides.

    +
    colors?: Partial<
        Record<
            | "filter"
            | "info"
            | "warning"
            | "success"
            | "error"
            | "shadow"
            | "accent0-light"
            | "accent0-dark"
            | "accent1-light"
            | "accent1-dark"
            | "accent2-light"
            | "accent2-dark"
            | "accent3-light"
            | "accent3-dark"
            | "accent4-light"
            | "accent4-dark"
            | "accent5-light"
            | "accent5-dark"
            | "accent6-light"
            | "accent6-dark"
            | "accent7-light"
            | "accent7-dark"
            | "accent-gray"
            | "accent-gray-light"
            | "accent-gray-dark"
            | "background-brand"
            | "background-filter"
            | "background-disabled"
            | "background-disabled-inverse"
            | "background-error"
            | "background-error-secondary"
            | "background-highlight"
            | "background-hover"
            | "background-info"
            | "background-primary"
            | "background-primary-inverse"
            | "background-secondary"
            | "background-secondary-inverse"
            | "background-selected"
            | "background-success"
            | "background-success-secondary"
            | "background-tertiary"
            | "background-tertiary-inverse"
            | "background-warning"
            | "background-warning-secondary"
            | "border"
            | "border-brand"
            | "border-filter"
            | "border-strong"
            | "border-stronger"
            | "border-subtle"
            | "brand"
            | "brand-hover"
            | "bronze"
            | "copper"
            | "danger"
            | "focus"
            | "gold"
            | "icon-brand"
            | "icon-disabled"
            | "icon-primary"
            | "icon-secondary"
            | "illustration-brand-secondary"
            | "illustration-brand-tertiary"
            | "overlay"
            | "saturated-blue"
            | "saturated-green"
            | "saturated-purple"
            | "saturated-red"
            | "saturated-yellow"
            | "silver"
            | "success-secondary"
            | "summarize"
            | "switch-off"
            | "syntax-parameters"
            | "syntax-parameters-active"
            | "text-brand"
            | "text-filter"
            | "text-hover"
            | "text-primary"
            | "text-primary-inverse"
            | "text-secondary"
            | "text-secondary-inverse"
            | "text-secondary-opaque"
            | "text-selected"
            | "text-tertiary"
            | "text-tertiary-inverse"
            | "tooltip-background"
            | "tooltip-background-focused"
            | "tooltip-text"
            | "tooltip-text-secondary"
            | "white",
            string,
        >,
    >

    Color overrides.

    version: 2

    Theme version must be 2 for version 2 themes.

    diff --git a/_docs/master/embedding/sdk/api/MetabaseFontFamily.html b/_docs/master/embedding/sdk/api/MetabaseFontFamily.html index 580b850df9..db42b23941 100644 --- a/_docs/master/embedding/sdk/api/MetabaseFontFamily.html +++ b/_docs/master/embedding/sdk/api/MetabaseFontFamily.html @@ -9,4 +9,4 @@ layout: docs-api --- -MetabaseFontFamily | Embedded analytics SDK API{% include docs/embedded-analytics-sdk-metadata.html %}

    Type Alias MetabaseFontFamily

    MetabaseFontFamily:
        | "Roboto"
        | "Merriweather"
        | "Open Sans"
        | "Lato"
        | "Noto Sans"
        | "Roboto Slab"
        | "Source Sans Pro"
        | "Raleway"
        | "Slabo 27px"
        | "PT Sans"
        | "Poppins"
        | "PT Serif"
        | "Roboto Mono"
        | "Roboto Condensed"
        | "Playfair Display"
        | "Oswald"
        | "Ubuntu"
        | "Montserrat"
        | "Lora"
        | "Custom"

    +MetabaseFontFamily | Embedded analytics SDK API{% include docs/embedded-analytics-sdk-metadata.html %}

    Type Alias MetabaseFontFamily

    MetabaseFontFamily:
        | "Roboto"
        | "Merriweather"
        | "Open Sans"
        | "Lato"
        | "Inter"
        | "Noto Sans"
        | "Roboto Slab"
        | "Source Sans Pro"
        | "Raleway"
        | "Slabo 27px"
        | "PT Sans"
        | "Poppins"
        | "PT Serif"
        | "Roboto Mono"
        | "Roboto Condensed"
        | "Playfair Display"
        | "Oswald"
        | "Ubuntu"
        | "Montserrat"
        | "Lora"
        | "Custom"

    diff --git a/_docs/master/embedding/sdk/api/MetabotAgentChartMessage.html b/_docs/master/embedding/sdk/api/MetabotAgentChartMessage.html new file mode 100644 index 0000000000..0e21640556 --- /dev/null +++ b/_docs/master/embedding/sdk/api/MetabotAgentChartMessage.html @@ -0,0 +1,19 @@ +--- +version: master +has_magic_breadcrumbs: true +show_category_breadcrumb: true +show_title_breadcrumb: true +category: Embedding +title: MetabotAgentChartMessage +source_url: 'https://github.com/metabase/metabase/blob/master/docs/embedding/sdk/api/MetabotAgentChartMessage.html' +layout: docs-api +--- + +MetabotAgentChartMessage | Embedded analytics SDK API{% include docs/embedded-analytics-sdk-metadata.html %}

    Type Alias MetabotAgentChartMessage

    type MetabotAgentChartMessage = {
        Chart: React_2.ComponentType<MetabotChartProps>;
        id: string;
        questionPath: string;
        role: "agent";
        type: "chart";
    }
    Index

    Properties

    Properties

    A pre-wired React component that renders the chart.

    +
    id: string
    questionPath: string

    URL path to the question, e.g. /question#<base64>

    +
    role: "agent"
    type: "chart"

    diff --git a/_docs/master/embedding/sdk/api/MetabotAgentMessage.html b/_docs/master/embedding/sdk/api/MetabotAgentMessage.html new file mode 100644 index 0000000000..25727ef5e0 --- /dev/null +++ b/_docs/master/embedding/sdk/api/MetabotAgentMessage.html @@ -0,0 +1,12 @@ +--- +version: master +has_magic_breadcrumbs: true +show_category_breadcrumb: true +show_title_breadcrumb: true +category: Embedding +title: MetabotAgentMessage +source_url: 'https://github.com/metabase/metabase/blob/master/docs/embedding/sdk/api/MetabotAgentMessage.html' +layout: docs-api +--- + +MetabotAgentMessage | Embedded analytics SDK API{% include docs/embedded-analytics-sdk-metadata.html %}

    Type Alias MetabotAgentMessage

    diff --git a/_docs/master/embedding/sdk/api/MetabotAgentTextMessage.html b/_docs/master/embedding/sdk/api/MetabotAgentTextMessage.html new file mode 100644 index 0000000000..e0e351fe4d --- /dev/null +++ b/_docs/master/embedding/sdk/api/MetabotAgentTextMessage.html @@ -0,0 +1,16 @@ +--- +version: master +has_magic_breadcrumbs: true +show_category_breadcrumb: true +show_title_breadcrumb: true +category: Embedding +title: MetabotAgentTextMessage +source_url: 'https://github.com/metabase/metabase/blob/master/docs/embedding/sdk/api/MetabotAgentTextMessage.html' +layout: docs-api +--- + +MetabotAgentTextMessage | Embedded analytics SDK API{% include docs/embedded-analytics-sdk-metadata.html %}

    Type Alias MetabotAgentTextMessage

    type MetabotAgentTextMessage = {
        id: string;
        message: string;
        role: "agent";
        type: "text";
    }
    Index

    Properties

    Properties

    id: string
    message: string
    role: "agent"
    type: "text"

    diff --git a/_docs/master/embedding/sdk/api/MetabotChartProps.html b/_docs/master/embedding/sdk/api/MetabotChartProps.html new file mode 100644 index 0000000000..44edae2f44 --- /dev/null +++ b/_docs/master/embedding/sdk/api/MetabotChartProps.html @@ -0,0 +1,12 @@ +--- +version: master +has_magic_breadcrumbs: true +show_category_breadcrumb: true +show_title_breadcrumb: true +category: Embedding +title: MetabotChartProps +source_url: 'https://github.com/metabase/metabase/blob/master/docs/embedding/sdk/api/MetabotChartProps.html' +layout: docs-api +--- + +MetabotChartProps | Embedded analytics SDK API{% include docs/embedded-analytics-sdk-metadata.html %}

    Type Alias MetabotChartProps

    MetabotChartProps:
        | Omit<StaticQuestionProps, "questionId" | "token" | "query"> & {
            drills?: false;
        }
        | Omit<InteractiveQuestionProps, "questionId" | "token" | "query"> & {
            drills: true;
        }

    diff --git a/_docs/master/embedding/sdk/api/MetabotErrorMessage.html b/_docs/master/embedding/sdk/api/MetabotErrorMessage.html new file mode 100644 index 0000000000..5e376f8dde --- /dev/null +++ b/_docs/master/embedding/sdk/api/MetabotErrorMessage.html @@ -0,0 +1,15 @@ +--- +version: master +has_magic_breadcrumbs: true +show_category_breadcrumb: true +show_title_breadcrumb: true +category: Embedding +title: MetabotErrorMessage +source_url: 'https://github.com/metabase/metabase/blob/master/docs/embedding/sdk/api/MetabotErrorMessage.html' +layout: docs-api +--- + +MetabotErrorMessage | Embedded analytics SDK API{% include docs/embedded-analytics-sdk-metadata.html %}

    Type Alias MetabotErrorMessage

    type MetabotErrorMessage = {
        message: string;
        type: "message" | "alert" | "locked";
    }
    Index

    Properties

    Properties

    message: string
    type: "message" | "alert" | "locked"

    "alert" renders with a warning icon and error color; "message" renders as plain text.

    +

    diff --git a/_docs/master/embedding/sdk/api/MetabotMessage.html b/_docs/master/embedding/sdk/api/MetabotMessage.html new file mode 100644 index 0000000000..3129b8a018 --- /dev/null +++ b/_docs/master/embedding/sdk/api/MetabotMessage.html @@ -0,0 +1,12 @@ +--- +version: master +has_magic_breadcrumbs: true +show_category_breadcrumb: true +show_title_breadcrumb: true +category: Embedding +title: MetabotMessage +source_url: 'https://github.com/metabase/metabase/blob/master/docs/embedding/sdk/api/MetabotMessage.html' +layout: docs-api +--- + +MetabotMessage | Embedded analytics SDK API{% include docs/embedded-analytics-sdk-metadata.html %}

    Type Alias MetabotMessage

    diff --git a/_docs/master/embedding/sdk/api/MetabotUserTextMessage.html b/_docs/master/embedding/sdk/api/MetabotUserTextMessage.html new file mode 100644 index 0000000000..c40c6afbe2 --- /dev/null +++ b/_docs/master/embedding/sdk/api/MetabotUserTextMessage.html @@ -0,0 +1,16 @@ +--- +version: master +has_magic_breadcrumbs: true +show_category_breadcrumb: true +show_title_breadcrumb: true +category: Embedding +title: MetabotUserTextMessage +source_url: 'https://github.com/metabase/metabase/blob/master/docs/embedding/sdk/api/MetabotUserTextMessage.html' +layout: docs-api +--- + +MetabotUserTextMessage | Embedded analytics SDK API{% include docs/embedded-analytics-sdk-metadata.html %}

    Type Alias MetabotUserTextMessage

    type MetabotUserTextMessage = {
        id: string;
        message: string;
        role: "user";
        type: "text";
    }
    Index

    Properties

    Properties

    id: string
    message: string
    role: "user"
    type: "text"

    diff --git a/_docs/master/embedding/sdk/api/ParameterChangePayload.html b/_docs/master/embedding/sdk/api/ParameterChangePayload.html new file mode 100644 index 0000000000..074e3f3392 --- /dev/null +++ b/_docs/master/embedding/sdk/api/ParameterChangePayload.html @@ -0,0 +1,17 @@ +--- +version: master +has_magic_breadcrumbs: true +show_category_breadcrumb: true +show_title_breadcrumb: true +category: Embedding +title: ParameterChangePayload +source_url: 'https://github.com/metabase/metabase/blob/master/docs/embedding/sdk/api/ParameterChangePayload.html' +layout: docs-api +--- + +ParameterChangePayload | Embedded analytics SDK API{% include docs/embedded-analytics-sdk-metadata.html %}

    Type Alias ParameterChangePayload

    Payload passed to onParametersChange callback

    +
    Index

    Properties

    defaultParameters: ParameterValues
    lastUsedParameters: ParameterValues
    parameters: ParameterValues

    diff --git a/_docs/master/embedding/sdk/api/ParameterChangeSource.html b/_docs/master/embedding/sdk/api/ParameterChangeSource.html new file mode 100644 index 0000000000..91953e6fcc --- /dev/null +++ b/_docs/master/embedding/sdk/api/ParameterChangeSource.html @@ -0,0 +1,18 @@ +--- +version: master +has_magic_breadcrumbs: true +show_category_breadcrumb: true +show_title_breadcrumb: true +category: Embedding +title: ParameterChangeSource +source_url: 'https://github.com/metabase/metabase/blob/master/docs/embedding/sdk/api/ParameterChangeSource.html' +layout: docs-api +--- + +ParameterChangeSource | Embedded analytics SDK API{% include docs/embedded-analytics-sdk-metadata.html %}

    Type Alias ParameterChangeSource

    ParameterChangeSource: "initial-state" | "manual-change" | "auto-change"

    Source of a parameter-change event:

    +
      +
    • initial-state - first applied snapshot, fired once per dashboard load.
    • +
    • manual-change - user edited parameters in UI.
    • +
    • auto-change - in the case of auto-updates, e.g. to pass normalized values back to parent.
    • +
    +

    diff --git a/_docs/master/embedding/sdk/api/SdkQuestionEntityPublicProps.html b/_docs/master/embedding/sdk/api/SdkQuestionEntityPublicProps.html index 3e891e1846..e992836694 100644 --- a/_docs/master/embedding/sdk/api/SdkQuestionEntityPublicProps.html +++ b/_docs/master/embedding/sdk/api/SdkQuestionEntityPublicProps.html @@ -9,7 +9,7 @@ layout: docs-api --- -SdkQuestionEntityPublicProps | Embedded analytics SDK API{% include docs/embedded-analytics-sdk-metadata.html %}

    Type Alias SdkQuestionEntityPublicProps

    SdkQuestionEntityPublicProps:
        | { questionId: SdkQuestionId
        | null; token?: never }
        | { questionId?: never; token: SdkEntityToken | null }

    Type Declaration

    • { questionId: SdkQuestionId | null; token?: never }
      • questionId: SdkQuestionId | null

        The ID of the question. +SdkQuestionEntityPublicProps | Embedded analytics SDK API{% include docs/embedded-analytics-sdk-metadata.html %}

        Type Alias SdkQuestionEntityPublicProps

        SdkQuestionEntityPublicProps:
            | { query?: never; questionId: SdkQuestionId
            | null; token?: never }
            | { query?: never; questionId?: never; token: SdkEntityToken | null }

        Type Declaration

        • { query?: never; questionId: SdkQuestionId | null; token?: never }
          • Optionalquery?: never
          • questionId: SdkQuestionId | null

            The ID of the question.
            This is either:

            @@ -22,5 +22,5 @@
          • new-native to show the SQL editor for creating new native questions
          -
      • Optionaltoken?: never
    • { questionId?: never; token: SdkEntityToken | null }
      • OptionalquestionId?: never
      • token: SdkEntityToken | null

        A valid JWT token for the guest embed.

        +
      • Optionaltoken?: never
    • { query?: never; questionId?: never; token: SdkEntityToken | null }
      • Optionalquery?: never
      • OptionalquestionId?: never
      • token: SdkEntityToken | null

        A valid JWT token for the guest embed.

    diff --git a/_docs/master/embedding/sdk/api/SdkQuestionId.html b/_docs/master/embedding/sdk/api/SdkQuestionId.html index b2b4e1cfa1..aa510d4e28 100644 --- a/_docs/master/embedding/sdk/api/SdkQuestionId.html +++ b/_docs/master/embedding/sdk/api/SdkQuestionId.html @@ -10,7 +10,7 @@ --- SdkQuestionId | Embedded analytics SDK API{% include docs/embedded-analytics-sdk-metadata.html %}

    Type Alias SdkQuestionId

    SdkQuestionId: number | "new" | "new-native" | SdkEntityId

    Represents the identifier for a question in the Metabase SDK.

    -
    // Numerical ID from question URL
    const questionId: SdkQuestionId = 123;

    // Entity ID string
    const questionId: SdkQuestionId = "abc123def456";

    // Create new notebook-style question
    const questionId: SdkQuestionId = "new";

    // Create new native SQL question
    const questionId: SdkQuestionId = "new-native"; +
    // Numerical ID from question URL
    const questionId: SdkQuestionId = 123;

    // Entity ID string
    const questionId: SdkQuestionId = "abc123def456";

    // Create new notebook-style question
    const questionId: SdkQuestionId = "new";

    // Create new native SQL question
    const questionId: SdkQuestionId = "new-native";

    diff --git a/_docs/master/embedding/sdk/api/SdkQuestionProps.html b/_docs/master/embedding/sdk/api/SdkQuestionProps.html index 99f9d119bc..21dbcb2574 100644 --- a/_docs/master/embedding/sdk/api/SdkQuestionProps.html +++ b/_docs/master/embedding/sdk/api/SdkQuestionProps.html @@ -9,20 +9,23 @@ layout: docs-api --- -SdkQuestionProps | Embedded analytics SDK API{% include docs/embedded-analytics-sdk-metadata.html %}

    Interface SdkQuestionProps

    interface SdkQuestionProps {
        className?: string;
        dataPicker?: EmbeddingDataPicker;
        entityTypes?: EmbeddingEntityType[];
        height?: Height<string | number>;
        hiddenParameters?: string[];
        initialSqlParameters?: SqlParameterValues;
        isSaveEnabled?: boolean;
        onBeforeSave?: (
            question: MetabaseQuestion | undefined,
            context: { isNewQuestion: boolean },
        ) => Promise<void>;
        onNavigateBack?: () => void;
        onRun?: (question: MetabaseQuestion | undefined) => void;
        onSave?: (
            question: MetabaseQuestion,
            context: { dashboardTabId?: number; isNewQuestion: boolean },
        ) => void;
        onVisualizationChange?: (
            display:
                | "object"
                | "table"
                | "bar"
                | "line"
                | "pie"
                | "scalar"
                | "row"
                | "area"
                | "combo"
                | "pivot"
                | "smartscalar"
                | "gauge"
                | "progress"
                | "funnel"
                | "map"
                | "scatter"
                | "boxplot"
                | "waterfall"
                | "sankey"
                | "list",
        ) => void;
        plugins?: MetabasePluginsConfig;
        questionId?: SdkQuestionId
        | null;
        style?: CSSProperties;
        targetCollection?: SdkCollectionId;
        title?: SdkQuestionTitleProps;
        token?: string | null;
        width?: Width<string | number>;
        withAlerts?: boolean;
        withChartTypeSelector?: boolean;
        withDownloads?: boolean;
    }
    Index

    Properties

    className? +SdkQuestionProps | Embedded analytics SDK API{% include docs/embedded-analytics-sdk-metadata.html %}

    Interface SdkQuestionProps

    interface SdkQuestionProps {
        className?: string;
        dataPicker?: EmbeddingDataPicker;
        entityTypes?: EmbeddingEntityType[];
        height?: Height<string | number>;
        hiddenParameters?: string[];
        initialCollection?: SdkCollectionId;
        initialSqlParameters?: SqlParameterValues;
        isSaveEnabled?: boolean;
        onBeforeSave?: (
            question: MetabaseQuestion | undefined,
            context: { isNewQuestion: boolean },
        ) => Promise<void>;
        onNavigateBack?: () => void;
        onRun?: (question: MetabaseQuestion | undefined) => void;
        onSave?: (
            question: MetabaseQuestion,
            context: { dashboardTabId?: number; isNewQuestion: boolean },
        ) => void;
        onSqlParametersChange?: (payload: SqlParameterChangePayload) => void;
        onVisualizationChange?: (
            display:
                | "object"
                | "table"
                | "bar"
                | "line"
                | "pie"
                | "scalar"
                | "row"
                | "area"
                | "combo"
                | "pivot"
                | "smartscalar"
                | "gauge"
                | "progress"
                | "funnel"
                | "map"
                | "scatter"
                | "boxplot"
                | "waterfall"
                | "sankey"
                | "list",
        ) => void;
        plugins?: MetabasePluginsConfig;
        questionId?: SdkQuestionId
        | null;
        sqlParameters?: SqlParameterValues;
        style?: CSSProperties;
        targetCollection?: SdkCollectionId;
        title?: SdkQuestionTitleProps;
        token?: string | null;
        width?: Width<string | number>;
        withAlerts?: boolean;
        withChartTypeSelector?: boolean;
        withDownloads?: boolean;
        withEditorButton?: boolean;
    }
    Index

    Properties

    className?: string

    A custom class name to be added to the root element.

    dataPicker?: EmbeddingDataPicker

    Controls the menu for selecting data sources in questions. You can opt for the full data picker by setting dataPicker = "staged".

    entityTypes?: EmbeddingEntityType[]

    An array that specifies which entity types are available in the data picker

    height?: Height<string | number>

    A number or string specifying a CSS size value that specifies the height of the component

    hiddenParameters?: string[]

    A list of parameters to hide.

    -
    initialSqlParameters?: SqlParameterValues

    Initial values for the SQL parameters.

    +
    initialCollection?: SdkCollectionId

    The collection to preselect in the save modal's collection picker. Unlike targetCollection, the picker remains visible and the user can choose a different collection. Ignored when targetCollection is set.

    +
    initialSqlParameters?: SqlParameterValues

    Initial values for SQL parameters, slug-keyed. Applied once on mount; user widget edits afterwards are not reflected back to the host. +
    +For each parameter: +

    +
      +
    • set to a value: that value is applied. +
    • +
    • set to null: strictly cleared, ignoring the parameter's default. +
    • +
    • omitted (or set to undefined): falls back to the parameter's default (or null if it has no default).
    • +
    isSaveEnabled?: boolean

    Whether to show the save button.

    onBeforeSave?: (
        question: MetabaseQuestion | undefined,
        context: { isNewQuestion: boolean },
    ) => Promise<void>

    A callback function that triggers before saving. Only relevant when isSaveEnabled = true

    onNavigateBack?: () => void

    A callback function that triggers when a user clicks the back button.

    onRun?: (question: MetabaseQuestion | undefined) => void

    A callback function that triggers when a question is updated, including when a user clicks the Visualize button in the question editor

    onSave?: (
        question: MetabaseQuestion,
        context: { dashboardTabId?: number; isNewQuestion: boolean },
    ) => void

    A callback function that triggers when a user saves the question. Only relevant when isSaveEnabled = true

    +
    onSqlParametersChange?: (payload: SqlParameterChangePayload) => void

    Fires on SQL parameters change. The payload's source distinguishes the initial state on load ('initial-state'), user edits in the UI ('manual-change'), and auto-updates ('auto-change').

    onVisualizationChange?: (
        display:
            | "object"
            | "table"
            | "bar"
            | "line"
            | "pie"
            | "scalar"
            | "row"
            | "area"
            | "combo"
            | "pivot"
            | "smartscalar"
            | "gauge"
            | "progress"
            | "funnel"
            | "map"
            | "scatter"
            | "boxplot"
            | "waterfall"
            | "sankey"
            | "list",
    ) => void

    A callback function that triggers when the visualization type changes.

    Type Declaration

      • (
            display:
                | "object"
                | "table"
                | "bar"
                | "line"
                | "pie"
                | "scalar"
                | "row"
                | "area"
                | "combo"
                | "pivot"
                | "smartscalar"
                | "gauge"
                | "progress"
                | "funnel"
                | "map"
                | "scatter"
                | "boxplot"
                | "waterfall"
                | "sankey"
                | "list",
        ): void
      • Parameters

        • display:
              | "object"
              | "table"
              | "bar"
              | "line"
              | "pie"
              | "scalar"
              | "row"
              | "area"
              | "combo"
              | "pivot"
              | "smartscalar"
              | "gauge"
              | "progress"
              | "funnel"
              | "map"
              | "scatter"
              | "boxplot"
              | "waterfall"
              | "sankey"
              | "list"

          the new display type

          -

        Returns void

    questionId?: SdkQuestionId | null

    A custom style object to be added to the root element.

    +

    Returns void

    questionId?: SdkQuestionId | null
    sqlParameters?: SqlParameterValues

    Controlled SQL parameter values, slug-keyed. On every render, this object replaces the question's parameter values: +

    +
      +
    • a parameter set to a value uses that value. +
    • +
    • a parameter set to null is cleared, even if it has a default. +
    • +
    • a parameter omitted from the object (or set to undefined) uses its default (or null if it has no default). +
      +
      +Pair with onSqlParametersChange to stay in sync with user edits.
    • +
    +

    A custom style object to be added to the root element.

    targetCollection?: SdkCollectionId

    The collection to save the question to. This will hide the collection picker from the save modal. Only applicable to interactive questions.

    Determines whether the question title is displayed, and allows a custom title to be displayed instead of the default question title. Shown by default.

    token?: string | null
    width?: Width<string | number>

    A number or string specifying a CSS size value that specifies the width of the component

    withAlerts?: boolean

    Enables the ability to set up alerts on the question.

    withChartTypeSelector?: boolean

    Determines whether the chart type selector and corresponding settings button are shown. Only relevant when using the default layout.

    withDownloads?: boolean

    Enables the ability to download results in the question.

    -

    +
    withEditorButton?: boolean

    Determines whether the editor button is shown. Only relevant when using the default layout.

    +

    diff --git a/_docs/master/embedding/sdk/api/SqlParameterChangePayload.html b/_docs/master/embedding/sdk/api/SqlParameterChangePayload.html new file mode 100644 index 0000000000..b6c5936eba --- /dev/null +++ b/_docs/master/embedding/sdk/api/SqlParameterChangePayload.html @@ -0,0 +1,16 @@ +--- +version: master +has_magic_breadcrumbs: true +show_category_breadcrumb: true +show_title_breadcrumb: true +category: Embedding +title: SqlParameterChangePayload +source_url: 'https://github.com/metabase/metabase/blob/master/docs/embedding/sdk/api/SqlParameterChangePayload.html' +layout: docs-api +--- + +SqlParameterChangePayload | Embedded analytics SDK API{% include docs/embedded-analytics-sdk-metadata.html %}

    Type Alias SqlParameterChangePayload

    Payload passed to onSqlParametersChange callback

    +
    type SqlParameterChangePayload = {
        defaultParameters: ParameterValues;
        parameters: ParameterValues;
        source: SqlParameterChangeSource;
    }
    Index

    Properties

    defaultParameters: ParameterValues
    parameters: ParameterValues

    diff --git a/_docs/master/embedding/sdk/api/SqlParameterChangeSource.html b/_docs/master/embedding/sdk/api/SqlParameterChangeSource.html new file mode 100644 index 0000000000..9d275315dc --- /dev/null +++ b/_docs/master/embedding/sdk/api/SqlParameterChangeSource.html @@ -0,0 +1,18 @@ +--- +version: master +has_magic_breadcrumbs: true +show_category_breadcrumb: true +show_title_breadcrumb: true +category: Embedding +title: SqlParameterChangeSource +source_url: 'https://github.com/metabase/metabase/blob/master/docs/embedding/sdk/api/SqlParameterChangeSource.html' +layout: docs-api +--- + +SqlParameterChangeSource | Embedded analytics SDK API{% include docs/embedded-analytics-sdk-metadata.html %}

    Type Alias SqlParameterChangeSource

    SqlParameterChangeSource: "initial-state" | "manual-change" | "auto-change"

    Source of a sql-parameter-change event:

    +
      +
    • initial-state - first applied state, fired once per question load.
    • +
    • manual-change - user edited parameters in UI.
    • +
    • auto-change - in the case of auto-updates, e.g. to pass normalized values back to parent.
    • +
    +

    diff --git a/_docs/master/embedding/sdk/api/StaticDashboard.html b/_docs/master/embedding/sdk/api/StaticDashboard.html index b43db3db74..c60b3bf0cd 100644 --- a/_docs/master/embedding/sdk/api/StaticDashboard.html +++ b/_docs/master/embedding/sdk/api/StaticDashboard.html @@ -29,17 +29,43 @@
  • Combining initialParameters and hiddenParameters to declutter the user interface is fine.
  • -
  • OptionalinitialParameters?: ParameterValues

    Query parameters for the dashboard. For a single option, use a string value, and use a list of strings for multiple options. +

  • OptionalinitialParameters?: ParameterValues

    Initial values for query parameters, slug-keyed. Applied once on mount; user widget edits afterwards are not reflected back to the host. +
    +For each parameter:

      +
    • set to a value (string for a single option, array of strings for multiple): that value is applied. +
    • +
    • set to null: strictly cleared, ignoring the parameter's default. +
    • +
    • omitted (or set to undefined): falls back to the parameter's default (or null if it has no default). +
      +
    • Combining initialParameters and hiddenParameters to filter data on the frontend is a security risk.
    • Combining initialParameters and hiddenParameters to declutter the user interface is fine.
  • OptionalonLoad?: (dashboard: MetabaseDashboard | null) => void

    Callback that is called when the dashboard is loaded.

  • OptionalonLoadWithoutCards?: (dashboard: MetabaseDashboard | null) => void

    Callback that is called when the dashboard is loaded without cards.

    +
  • OptionalonParametersChange?: (payload: ParameterChangePayload) => void

    Fires on parameters change. The payload's source distinguishes the initial state on load ('initial-state'), user edits in the UI ('manual-change'), and auto-updates ('auto-change').

  • OptionalonVisualizationChange?: (
        visualization:
            | "object"
            | "table"
            | "bar"
            | "line"
            | "pie"
            | "scalar"
            | "row"
            | "area"
            | "combo"
            | "pivot"
            | "smartscalar"
            | "gauge"
            | "progress"
            | "funnel"
            | "map"
            | "scatter"
            | "boxplot"
            | "waterfall"
            | "sankey"
            | "list",
    ) => void

    A callback function that triggers when a question is opened from a dashboard card or when the user changes the visualization type of a question.

    +
  • Optionalparameters?: ParameterValues

    Controlled parameter values, slug-keyed. On every render, this object replaces the dashboard's parameter values: +

    +
      +
    • a parameter set to a value uses that value. +
    • +
    • a parameter set to null is cleared, even if it has a default. +
    • +
    • a parameter omitted from the object (or set to undefined) uses its default (or null if it has no default). +
      +
      +Pair with onParametersChange to stay in sync with user edits. +
    • +
    • Combining parameters and hiddenParameters to filter data on the frontend is a security risk. +
    • +
    • Combining parameters and hiddenParameters to declutter the user interface is fine.
    • +
  • Optionalplugins?: MetabasePluginsConfig

    Additional mapper function to override or add drill-down menu. See the implementing custom actions section for more details.

  • Optionalstyle?: CSSProperties

    A custom style object to be added to the root element.

  • Optionaltoken?: string | null

    A valid JWT token for the guest embed.

    diff --git a/_docs/master/embedding/sdk/api/StaticDashboardProps.html b/_docs/master/embedding/sdk/api/StaticDashboardProps.html index 04c134a0ac..2205e47ed8 100644 --- a/_docs/master/embedding/sdk/api/StaticDashboardProps.html +++ b/_docs/master/embedding/sdk/api/StaticDashboardProps.html @@ -9,7 +9,7 @@ layout: docs-api --- -StaticDashboardProps | Embedded analytics SDK API{% include docs/embedded-analytics-sdk-metadata.html %}

    Interface StaticDashboardProps

    interface StaticDashboardProps {
        autoRefreshInterval?: number;
        className?: string;
        dashboardId?: SdkDashboardId | null;
        dataPickerProps?: Pick<SdkQuestionProps, "entityTypes">;
        hiddenParameters?: string[];
        initialParameters?: ParameterValues;
        onLoad?: (dashboard: MetabaseDashboard | null) => void;
        onLoadWithoutCards?: (dashboard: MetabaseDashboard | null) => void;
        onVisualizationChange?: (
            visualization:
                | "object"
                | "table"
                | "bar"
                | "line"
                | "pie"
                | "scalar"
                | "row"
                | "area"
                | "combo"
                | "pivot"
                | "smartscalar"
                | "gauge"
                | "progress"
                | "funnel"
                | "map"
                | "scatter"
                | "boxplot"
                | "waterfall"
                | "sankey"
                | "list",
        ) => void;
        plugins?: MetabasePluginsConfig;
        style?: CSSProperties;
        token?: string
        | null;
        withCardTitle?: boolean;
        withDownloads?: boolean;
        withSubscriptions?: boolean;
        withTitle?: boolean;
    }
    Index

    Properties

    autoRefreshInterval? +StaticDashboardProps | Embedded analytics SDK API{% include docs/embedded-analytics-sdk-metadata.html %}

    Interface StaticDashboardProps

    interface StaticDashboardProps {
        autoRefreshInterval?: number;
        className?: string;
        dashboardId?: SdkDashboardId | null;
        dataPickerProps?: Pick<SdkQuestionProps, "entityTypes">;
        hiddenParameters?: string[];
        initialParameters?: ParameterValues;
        onLoad?: (dashboard: MetabaseDashboard | null) => void;
        onLoadWithoutCards?: (dashboard: MetabaseDashboard | null) => void;
        onParametersChange?: (payload: ParameterChangePayload) => void;
        onVisualizationChange?: (
            visualization:
                | "object"
                | "table"
                | "bar"
                | "line"
                | "pie"
                | "scalar"
                | "row"
                | "area"
                | "combo"
                | "pivot"
                | "smartscalar"
                | "gauge"
                | "progress"
                | "funnel"
                | "map"
                | "scatter"
                | "boxplot"
                | "waterfall"
                | "sankey"
                | "list",
        ) => void;
        parameters?: ParameterValues;
        plugins?: MetabasePluginsConfig;
        style?: CSSProperties;
        token?: string
        | null;
        withCardTitle?: boolean;
        withDownloads?: boolean;
        withSubscriptions?: boolean;
        withTitle?: boolean;
    }
    Index
  • Combining initialParameters and hiddenParameters to declutter the user interface is fine.
  • -
    initialParameters?: ParameterValues

    Query parameters for the dashboard. For a single option, use a string value, and use a list of strings for multiple options. +

    initialParameters?: ParameterValues

    Initial values for query parameters, slug-keyed. Applied once on mount; user widget edits afterwards are not reflected back to the host. +
    +For each parameter:

      +
    • set to a value (string for a single option, array of strings for multiple): that value is applied. +
    • +
    • set to null: strictly cleared, ignoring the parameter's default. +
    • +
    • omitted (or set to undefined): falls back to the parameter's default (or null if it has no default). +
      +
    • Combining initialParameters and hiddenParameters to filter data on the frontend is a security risk.
    • Combining initialParameters and hiddenParameters to declutter the user interface is fine.
    onLoad?: (dashboard: MetabaseDashboard | null) => void

    Callback that is called when the dashboard is loaded.

    onLoadWithoutCards?: (dashboard: MetabaseDashboard | null) => void

    Callback that is called when the dashboard is loaded without cards.

    +
    onParametersChange?: (payload: ParameterChangePayload) => void

    Fires on parameters change. The payload's source distinguishes the initial state on load ('initial-state'), user edits in the UI ('manual-change'), and auto-updates ('auto-change').

    onVisualizationChange?: (
        visualization:
            | "object"
            | "table"
            | "bar"
            | "line"
            | "pie"
            | "scalar"
            | "row"
            | "area"
            | "combo"
            | "pivot"
            | "smartscalar"
            | "gauge"
            | "progress"
            | "funnel"
            | "map"
            | "scatter"
            | "boxplot"
            | "waterfall"
            | "sankey"
            | "list",
    ) => void

    A callback function that triggers when a question is opened from a dashboard card or when the user changes the visualization type of a question.

    Type Declaration

      • (
            visualization:
                | "object"
                | "table"
                | "bar"
                | "line"
                | "pie"
                | "scalar"
                | "row"
                | "area"
                | "combo"
                | "pivot"
                | "smartscalar"
                | "gauge"
                | "progress"
                | "funnel"
                | "map"
                | "scatter"
                | "boxplot"
                | "waterfall"
                | "sankey"
                | "list",
        ): void
      • Parameters

        • visualization:
              | "object"
              | "table"
              | "bar"
              | "line"
              | "pie"
              | "scalar"
              | "row"
              | "area"
              | "combo"
              | "pivot"
              | "smartscalar"
              | "gauge"
              | "progress"
              | "funnel"
              | "map"
              | "scatter"
              | "boxplot"
              | "waterfall"
              | "sankey"
              | "list"

          the new visualization type

          -

        Returns void

    Additional mapper function to override or add drill-down menu. See the implementing custom actions section for more details.

    +

    Returns void

    parameters?: ParameterValues

    Controlled parameter values, slug-keyed. On every render, this object replaces the dashboard's parameter values: +

    +
      +
    • a parameter set to a value uses that value. +
    • +
    • a parameter set to null is cleared, even if it has a default. +
    • +
    • a parameter omitted from the object (or set to undefined) uses its default (or null if it has no default). +
      +
      +Pair with onParametersChange to stay in sync with user edits. +
    • +
    • Combining parameters and hiddenParameters to filter data on the frontend is a security risk. +
    • +
    • Combining parameters and hiddenParameters to declutter the user interface is fine.
    • +
    +

    Additional mapper function to override or add drill-down menu. See the implementing custom actions section for more details.

    A custom style object to be added to the root element.

    token?: string | null

    A valid JWT token for the guest embed.

    withCardTitle?: boolean

    Whether the dashboard cards should display a title.

    withDownloads?: boolean

    Whether to hide the download button.

    withSubscriptions?: boolean

    Whether to show the subscriptions button.

    withTitle?: boolean

    Whether the dashboard should display a title.

    -

    +

    diff --git a/_docs/master/embedding/sdk/api/StaticQuestion.html b/_docs/master/embedding/sdk/api/StaticQuestion.html index 36f806fc76..3e8d1f5974 100644 --- a/_docs/master/embedding/sdk/api/StaticQuestion.html +++ b/_docs/master/embedding/sdk/api/StaticQuestion.html @@ -13,8 +13,19 @@

    Parameters

    • props: StaticQuestionProps
      • OptionalclassName?: string

        A custom class name to be added to the root element.

      • Optionalheight?: Height<string | number>

        A number or string specifying a CSS size value that specifies the height of the component

      • OptionalhiddenParameters?: string[]

        A list of parameters to hide.

        -
      • OptionalinitialSqlParameters?: SqlParameterValues

        Initial values for the SQL parameters.

        -
      • OptionalquestionId?: SdkQuestionId | null

        The ID of the question. +

      • OptionalinitialSqlParameters?: SqlParameterValues

        Initial values for SQL parameters, slug-keyed. Applied once on mount; user widget edits afterwards are not reflected back to the host. +
        +For each parameter: +

        +
          +
        • set to a value: that value is applied. +
        • +
        • set to null: strictly cleared, ignoring the parameter's default. +
        • +
        • omitted (or set to undefined): falls back to the parameter's default (or null if it has no default).
        • +
        +
      • OptionalonSqlParametersChange?: (payload: SqlParameterChangePayload) => void

        Fires on SQL parameters change. The payload's source distinguishes the initial state on load ('initial-state'), user edits in the UI ('manual-change'), and auto-updates ('auto-change').

        +
      • Optionalquery?: undefined
      • OptionalquestionId?: SdkQuestionId | null

        The ID of the question.
        This is either:

        @@ -27,6 +38,18 @@
      • new-native to show the SQL editor for creating new native questions
      +
  • OptionalsqlParameters?: SqlParameterValues

    Controlled SQL parameter values, slug-keyed. On every render, this object replaces the question's parameter values: +

    +
      +
    • a parameter set to a value uses that value. +
    • +
    • a parameter set to null is cleared, even if it has a default. +
    • +
    • a parameter omitted from the object (or set to undefined) uses its default (or null if it has no default). +
      +
      +Pair with onSqlParametersChange to stay in sync with user edits.
    • +
  • Optionalstyle?: CSSProperties

    A custom style object to be added to the root element.

  • Optionaltitle?: SdkQuestionTitleProps

    Determines whether the question title is displayed, and allows a custom title to be displayed instead of the default question title. Shown by default.

  • Optionaltoken?: string | null

    A valid JWT token for the guest embed.

    diff --git a/_docs/master/embedding/sdk/api/StaticQuestionProps.html b/_docs/master/embedding/sdk/api/StaticQuestionProps.html index 6125aa06b7..8b52db0ab6 100644 --- a/_docs/master/embedding/sdk/api/StaticQuestionProps.html +++ b/_docs/master/embedding/sdk/api/StaticQuestionProps.html @@ -9,11 +9,14 @@ layout: docs-api --- -StaticQuestionProps | Embedded analytics SDK API{% include docs/embedded-analytics-sdk-metadata.html %}

    Interface StaticQuestionProps

    interface StaticQuestionProps {
        className?: string;
        height?: Height<string | number>;
        hiddenParameters?: string[];
        initialSqlParameters?: SqlParameterValues;
        questionId?: SdkQuestionId | null;
        style?: CSSProperties;
        title?: SdkQuestionTitleProps;
        token?: string | null;
        width?: Width<string | number>;
        withAlerts?: boolean;
        withChartTypeSelector?: boolean;
        withDownloads?: boolean;
    }
    Index

    Properties

    className? +StaticQuestionProps | Embedded analytics SDK API{% include docs/embedded-analytics-sdk-metadata.html %}

    Interface StaticQuestionProps

    interface StaticQuestionProps {
        className?: string;
        height?: Height<string | number>;
        hiddenParameters?: string[];
        initialSqlParameters?: SqlParameterValues;
        onSqlParametersChange?: (payload: SqlParameterChangePayload) => void;
        query?: undefined;
        questionId?: SdkQuestionId | null;
        sqlParameters?: SqlParameterValues;
        style?: CSSProperties;
        title?: SdkQuestionTitleProps;
        token?: string | null;
        width?: Width<string | number>;
        withAlerts?: boolean;
        withChartTypeSelector?: boolean;
        withDownloads?: boolean;
    }
    Index

    Properties

    className?: string

    A custom class name to be added to the root element.

    height?: Height<string | number>

    A number or string specifying a CSS size value that specifies the height of the component

    hiddenParameters?: string[]

    A list of parameters to hide.

    -
    initialSqlParameters?: SqlParameterValues

    Initial values for the SQL parameters.

    -
    questionId?: SdkQuestionId | null

    The ID of the question. +

    initialSqlParameters?: SqlParameterValues

    Initial values for SQL parameters, slug-keyed. Applied once on mount; user widget edits afterwards are not reflected back to the host. +
    +For each parameter: +

    +
      +
    • set to a value: that value is applied. +
    • +
    • set to null: strictly cleared, ignoring the parameter's default. +
    • +
    • omitted (or set to undefined): falls back to the parameter's default (or null if it has no default).
    • +
    +
    onSqlParametersChange?: (payload: SqlParameterChangePayload) => void

    Fires on SQL parameters change. The payload's source distinguishes the initial state on load ('initial-state'), user edits in the UI ('manual-change'), and auto-updates ('auto-change').

    +
    query?: undefined
    questionId?: SdkQuestionId | null

    The ID of the question.
    This is either:

    @@ -38,6 +52,18 @@
  • new-native to show the SQL editor for creating new native questions
  • +
    sqlParameters?: SqlParameterValues

    Controlled SQL parameter values, slug-keyed. On every render, this object replaces the question's parameter values: +

    +
      +
    • a parameter set to a value uses that value. +
    • +
    • a parameter set to null is cleared, even if it has a default. +
    • +
    • a parameter omitted from the object (or set to undefined) uses its default (or null if it has no default). +
      +
      +Pair with onSqlParametersChange to stay in sync with user edits.
    • +

    A custom style object to be added to the root element.

    Determines whether the question title is displayed, and allows a custom title to be displayed instead of the default question title. Shown by default.

    token?: string | null

    A valid JWT token for the guest embed.

    @@ -45,4 +71,4 @@
    withAlerts?: boolean

    Enables the ability to set up alerts on the question.

    withChartTypeSelector?: boolean

    Determines whether the chart type selector and corresponding settings button are shown. Only relevant when using the default layout.

    withDownloads?: boolean

    Enables the ability to download results in the question.

    -

    +

    diff --git a/_docs/master/embedding/sdk/api/UseMetabotResult.html b/_docs/master/embedding/sdk/api/UseMetabotResult.html new file mode 100644 index 0000000000..76afd127e3 --- /dev/null +++ b/_docs/master/embedding/sdk/api/UseMetabotResult.html @@ -0,0 +1,35 @@ +--- +version: master +has_magic_breadcrumbs: true +show_category_breadcrumb: true +show_title_breadcrumb: true +category: Embedding +title: UseMetabotResult +source_url: 'https://github.com/metabase/metabase/blob/master/docs/embedding/sdk/api/UseMetabotResult.html' +layout: docs-api +--- + +UseMetabotResult | Embedded analytics SDK API{% include docs/embedded-analytics-sdk-metadata.html %}

    Type Alias UseMetabotResult

    type UseMetabotResult = {
        cancelRequest: () => void;
        CurrentChart: React_2.ComponentType<MetabotChartProps> | null;
        errorMessages: MetabotErrorMessage[];
        isProcessing: boolean;
        messages: MetabotMessage[];
        resetConversation: () => void;
        retryMessage: (messageId: string) => Promise<void>;
        submitMessage: (message: string) => Promise<void>;
    }
    Index

    Properties

    cancelRequest: () => void

    Cancel the current in-flight request.

    +

    A pre-wired component bound to the latest navigate_to path. +null until the agent sends a chart — lets consumers detect presence +and render a placeholder or swap panel content only when set.

    +
    {CurrentChart ? <CurrentChart /> : <Placeholder />}
    +
    + +
    errorMessages: MetabotErrorMessage[]

    Errors are conversation-level, not attached to individual messages.

    +
    isProcessing: boolean

    true from the moment a message is submitted until the response +completes — including success, error, or cancellation.

    +
    messages: MetabotMessage[]

    All messages in the conversation. Chart messages include a Chart property.

    +
    resetConversation: () => void

    Clear all messages and start fresh.

    +
    retryMessage: (messageId: string) => Promise<void>

    Rewinds the conversation to the user message preceding messageId and re-submits +that prompt. The agent message at messageId and anything after it is dropped.

    +
    submitMessage: (message: string) => Promise<void>

    Submit a new message to the conversation.

    +

    diff --git a/_docs/master/embedding/sdk/api/assets/highlight.css b/_docs/master/embedding/sdk/api/assets/highlight.css index 4119bd81e4..187da1588f 100644 --- a/_docs/master/embedding/sdk/api/assets/highlight.css +++ b/_docs/master/embedding/sdk/api/assets/highlight.css @@ -1,18 +1,24 @@ :root { --light-hl-0: #0000FF; --dark-hl-0: #569CD6; - --light-hl-1: #008000; - --dark-hl-1: #6A9955; - --light-hl-2: #000000; - --dark-hl-2: #D4D4D4; - --light-hl-3: #0070C1; - --dark-hl-3: #4FC1FF; - --light-hl-4: #267F99; - --dark-hl-4: #4EC9B0; - --light-hl-5: #098658; - --dark-hl-5: #B5CEA8; - --light-hl-6: #A31515; - --dark-hl-6: #CE9178; + --light-hl-1: #000000; + --dark-hl-1: #D4D4D4; + --light-hl-2: #0070C1; + --dark-hl-2: #4FC1FF; + --light-hl-3: #795E26; + --dark-hl-3: #DCDCAA; + --light-hl-4: #AF00DB; + --dark-hl-4: #C586C0; + --light-hl-5: #001080; + --dark-hl-5: #9CDCFE; + --light-hl-6: #267F99; + --dark-hl-6: #4EC9B0; + --light-hl-7: #A31515; + --dark-hl-7: #CE9178; + --light-hl-8: #008000; + --dark-hl-8: #6A9955; + --light-hl-9: #098658; + --dark-hl-9: #B5CEA8; --light-code-background: #FFFFFF; --dark-code-background: #1E1E1E; } @@ -25,6 +31,9 @@ --hl-4: var(--light-hl-4); --hl-5: var(--light-hl-5); --hl-6: var(--light-hl-6); + --hl-7: var(--light-hl-7); + --hl-8: var(--light-hl-8); + --hl-9: var(--light-hl-9); --code-background: var(--light-code-background); } } @@ -36,6 +45,9 @@ --hl-4: var(--dark-hl-4); --hl-5: var(--dark-hl-5); --hl-6: var(--dark-hl-6); + --hl-7: var(--dark-hl-7); + --hl-8: var(--dark-hl-8); + --hl-9: var(--dark-hl-9); --code-background: var(--dark-code-background); } } @@ -47,6 +59,9 @@ --hl-4: var(--light-hl-4); --hl-5: var(--light-hl-5); --hl-6: var(--light-hl-6); + --hl-7: var(--light-hl-7); + --hl-8: var(--light-hl-8); + --hl-9: var(--light-hl-9); --code-background: var(--light-code-background); } @@ -58,6 +73,9 @@ --hl-4: var(--dark-hl-4); --hl-5: var(--dark-hl-5); --hl-6: var(--dark-hl-6); + --hl-7: var(--dark-hl-7); + --hl-8: var(--dark-hl-8); + --hl-9: var(--dark-hl-9); --code-background: var(--dark-code-background); } @@ -68,4 +86,7 @@ .hl-4 { color: var(--hl-4); } .hl-5 { color: var(--hl-5); } .hl-6 { color: var(--hl-6); } +.hl-7 { color: var(--hl-7); } +.hl-8 { color: var(--hl-8); } +.hl-9 { color: var(--hl-9); } pre, code { background: var(--code-background); } diff --git a/_docs/master/embedding/sdk/api/assets/navigation.js b/_docs/master/embedding/sdk/api/assets/navigation.js index 802729db6b..2755dbda4a 100644 --- a/_docs/master/embedding/sdk/api/assets/navigation.js +++ b/_docs/master/embedding/sdk/api/assets/navigation.js @@ -1 +1 @@ -window.navigationData = "eJylWl1z3CYU/S969nRaT5NO/ebP1I7Tbr2285DJAyvdrOgiUBDy1snkv3fYDwnB5Ut9sodzOIcL6OqC9tP3QsG/qjgrLgVjUCoq+IUU2w5kcVKUNWWVBF6cfQryWqJqDPqpVg0rTooN5VVx9vbXHyd+mYUUbRfQ2uFTwdM3b398NjUlEAVXpKtXgsjqg6gI80WBU4/mCBqKBaHb4fgoKRH93UOnZyIYi0GaeB7b7fGfFCUjXVecFRW0EkqioCq81mg4EzAcyBC5J4briiqyYmDyDl4OFFiJW65AklLRF0wJQwNiS0UULREdCwhIOGO35hHH3akMR2iJeikhXSsmSxJDwwtuDCKyfXGmG4tvI5u7TFLGHmsp+nXt2bleSuKkH/tc1kSqx9cWrqRoK7G1fZK7ZPrqHSPkRa+UE1oKe5Zbqs8ch7j2HNXj3yUoRfm6S1+kYM+Zo3imXU8Y/UbSAvZ3y/R/gA5U6laxyZleSzL+fyNkEzdEe2S6PlLFIG410oIpsNp4dqWNZI7ygpSb1GWwuJbTz7//9sub04ibBLIRvUrf82iPGc5DgluCrt1SEgfeZYb3ldhyJkj1kVZryIg90O9/jyLXfa7rDWUKZHrMCH+2a6rbXBc7H+dn8LnOOj+lPrUWd45b3zRE0m8Z9QTeBfc2S7MPoMiKdDohvtDKe9Cr4AvlcCSf96q+FPwLXY9j8jECFRrifRCzkQwRa6pQOJSyQzHGonMX1+3xkar6vKXv4TWkO7LmOdxtVUz+bqvmaS9Jw2LimpOqftu905s4NOEOJXFjCxU5b7gs03kEYhtwZGL7z0LDh6X98Soyboc0OZsljHpKRE94GWN+rKGhfB2aZNLBdbOCqqJ8renwfOqus80IPai7auFSMCFNJbM1dQPu6OgDeURSlabjj8UX38RC1d6UjBVQomkFB64iddZAS0mEuzlAMuq+PUXB83QZSIqKZ0qxmUQuM0JT5GOEVNFiIOOtP+5TbO9Ge9sXove00z37hoeuTQ1W1KHvlGiGS55LfU8JvL9V0BgGflJMf9Jpr+PqB0hZ+rqTR1VD2Vr7oVwzaICrgPCEl+KCT7ONxJSGLHNFFFnQcmOWVgiYrHfNFVWv+oSG6I1gVG9g7o8D7+HVvAZF0GgNXQr+JzHTw7ElXn1TRYeLFZ0J+knydNGY4r1YU0fIaEx+KzFabs5LPHEa4Ay9BevXlHe+asvHzHifHvIO+tY4YPlq06cCx9NVD1ne81qZ4qmqyPcBB8rWiqwWzkt3UWQhKFd/rf6BEjk0WITsSuhYQgXLvZGUqn8Dqqwf4Kt+aT+KDfAbZLMhpGR9wdUNaShDqsIRS1V7x8SKsMhCIqRU/YjyLM3dxl9IfRPsqbr2YKreU4ed8J+cL8OuwoJI0oAC+UxYD0ZWtYCojhQKSgWVW/A7UExrWW2MxGN+D5wCCTrDA7x/8y36FaOle+nsp+V4WEM12nNU7gWprl8mxQ8KJ2juo7GGdWxM7r97uhGJXXuKipRCDjl/KjSBsrXchUTwFFU9n38QXjGQzoOO4wmqwze74NbzsjIcrBUemzM0sC88KJygqROPNaZ9U7TvV+ZNSC4WU9Oe+jMP8Opuqx6gawXvjHoEx+M3B30H523LaLmrXA+1MXaNgBIP5i7m3CjZni+EMv0jBv2O7AKWNs9wnEAxQ+u3NOct9Zui3NHYhdN/5mNvBBQO36HpEfRSAldP/h9cOSRj+GN7bNLMO9vhpOKxQ7mjqwsj5p//A6K3XmY=" \ No newline at end of file +window.navigationData = "eJylWsly3DYQ/ReeVanEFTsV3WQtjrdkopHsg8sHDNkeIgMCY7ApWU7531OYjSDQ2JiTVHgP72FtNMD59G+F8A2r8+pSCQE1ciVfavXYg67OqrrlotEgq/NPUd6WYUtBP7XYieqs2nDZVOcvfv1xFpZZaLXtI1o7fCr47PmLH59tTQ0M4Yr17Uox3bxXDROhXtDUozmBxvpC0N3uhCg5Pfp7gN6MRLQvFmnieSx3239W1YL1fXVeNbDVUDOEpgpak92ZgPGOnHoe6MN1w5GtBNi8g5cHRWbitUTQrEb+QClRaERsiQx5Teg4QETCa7szjjTuD2W8h45okBLTdfrkSFJoTG3BNOsAQV+2TK5hwZ6EYtYI0rij+PPvv/3y/FlYdakGXUNQdA/Tmp/pEU1sNJrpj3poy9n7QXMh7lqthnUb2GNBSubyONa5bJnGu6ctXGm1bdSj65NdpdDXrG2lXw6IXtdy2LPccn3mOKS156ge/y4Bkct1nz9J0ZozW/GB9wMT/DvL63C4WqH/LfSAuUvFJRd6Ldn4/43SXdqQrFHoesdRQNpqpEWDdbMJrEoXKWzlS1ZvcqfB4aaCN6WggW3UgPlrnqwxw/kU4JZgssycwEFXmeF9pR6lOe0+8mYNBX2P1PvfrSh1n+t6wwWCzu8zwZ/tmus218WNx+URfK6ziU+5u9bhznEbuo5p/r0gn6CrpLyXX0UqjwxSyrXdbDLESCeU7wHZivUmjD/wJniRbuALl3AkXwzYXir5ha/HJoQYkbyS8D6IuUiBiDPBJBw7aGJ9TPXOnzq/xkeO7cWWv4WnmO7Imufw5hFT8m8ecZ72knUiJW44ueqv+1dm68UG3KNkLmyFiVuSz7KdRyC1AEcmtf4cNP76sL++JtrtkSZ334xWT4nkDbqgzXctdFyuY4PMerjuVtA0XK4NHT488+fZZcQ26i7HuVRCaVvJLs1dgDs6uSGPSK7StP2p/qUXscI2GJKptE91WyVBYiI7PNFyAuFuDIiIui/PUQjsLgvJUQkMKTWSxGNRbIhCjJgqmcIU5CrjOqXWbrK2++D8jvem5tDJ2LO0xUo6DD2q7vSIdmnegUEOrxE6yyBMSulPKu11fP0IqUjfVAqoGqhYa9+UawEdSIwIT3g5LvQwu0hK6RRlrhiyBa83dmpFgNl61xI5Ppl7JaE3gkm9E3N/iXkLT/YzM4EmM/9ayT+ZHR6OJek7A0d+eg4ykWCYBE8fTSm+U2vuCVmF2aeS4PXmoqYDpwXO0FuIYc1lH8q2QsyC8/QQd8hT44CVq013BY3nqx6ifOBYmeK5qsT3Fw8q1krMFs3Ld0G2UFziX6t/oCYuDQ6hOBM6plDRdG8k5erfANbtLXw1h/ad2oC8IRYbQcrWVxJvWMcFkRWOWK7aK6FWTCQmkiDl6ieUZ2nuFv5Cm/frQNa1B3P17nvqhn/vfXkPKCi8WIPEXY70Hvqerd1dSzBKlKOiM/Tu4Ftc0yJk6prBisk6ePYnyg9MDGCdVg6Q1NEKoUZo/IuUByXfupqNFdDt17MpkKFzCoz7jGIxrASv/U8QYVqJh9NUq7xE5Z1izfXDJKkk4QzNfW+cZh0Ls+vvoiYhsSvPUdFa6dNZOhWaQMVa/kQSeI6qGc8/mGwEaC+A0niG6ukLbnTpBVkFDs4Mj8UFGtT3PhLO0DQxyGnTvqjkldsNSD6WUjOe5qMfyObNI95Cv1WytyImjadfZIYeLrZbwevdjeBw56CeZ0jiwdzHvJc61/OBcWF+fGNyjz5i6fIsxwmUMnR+A3ax5WFTkjsa+3D+z9PchUDC8bdJ04JBa5B4H/6hoEeymj+WpwbNfgs/3QADdiR3dPXhLHOFCUeFvo3CyIQcGLusin7bHqHMNGYXqEM5jA1m6oWkMlXuT8NwC/0gcBIkJkgoPHz+D9w00Bk=" \ No newline at end of file diff --git a/_docs/master/embedding/sdk/api/assets/search.js b/_docs/master/embedding/sdk/api/assets/search.js index 95dcccd5e3..8e145947b8 100644 --- a/_docs/master/embedding/sdk/api/assets/search.js +++ b/_docs/master/embedding/sdk/api/assets/search.js @@ -1 +1 @@ -window.searchData = "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"; \ No newline at end of file +window.searchData = "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u767T+abWCDfbt+MewbMu+fd65eUfTrB5away7S+a7+fqcOu97ArS1DGLGJDlHm2nPcDM40597q7NU39u6bgvfaNm3fuqvd/q+61OXWfiuOOdxuacza267Y9d7uPPdkQ+7g97BD7XHvGouzjJs0JtM+z6jDPae/urXR3M6p8YmszT/OxrHc2lz4dfVnG9N3R8Hsn++J915gp45uueVq75kvJuwG+5T20unV9cdzF2c9j2t1ivjjuxrdY861IV/BTVkwv3+db8dPpaciN4VvSkl73smbeU7nxiYS7BlStJV4aZVvcZ+8wLn7W9iF/LewdxIQ105uI2TagfcSEFZytxBV24N3EpC28DcV8e6b3FFOmzd9W3MXKefdv9uZito0T+4sJA2duMWZbl91lTNjF3mjMtii/15gwib/dmG0T2XFMGDKx6bhSO9x3sCxhbT2usCq7+5i0ir0BucKqsT3IpGFztiGzbQM7kQmD/hW+TPcjUyZMbElm62fsSiZMumJjMtvKeG8yYdD49mS27niHMqF7fJMyWzfep0zYwNuqXGVLulth2DK9YbnKFrxnYdjD27ZcZdPs53T7M8rsX/xbnFSJyC7Ixnvw9ze78rk47Tt7FKmEkzRD0YezkMYLmbw/E9ebnZ+smflpiWNqU1sr+bPTlZbedDv/Bfdxyu/82dJxXxta8f2LW72UyL66jmlwJRmLeJX0qD3XVdJjWMOocprYckW9U74lnOJVOYuuqWI1bdmsaqjUtJvqos6wjVMhNWvbNbVSp23jV02lhl1fP3WuVdc80ttrqk5bOV1dlVo1v84q14r5o9W1tVenLZquwkptmV+PlWvFNb5zfY3WaavmVmultt1at5VhIaOCa2LVFbVc+ZZccZeuru86bZVvyan0Su26pebrfMuu8f171IHlW8quCJsz8+rasNM2MqvEUsuurBc7bQ+vciw157oasjxrfOuparLIpmvryjIsm1NhNjHtllqzDNs4VWcTm66pPzvDlmuGiZtq0k7bNlmdltozu07ttA0zK9ZSi26sXQvtm9ihhyvByaBQ0pi/XydVadjCpwrUsC4pG/eJK1XxjZqqWzXTKtYzYj6dmc/ltWi90zJmCqriw2vReqe9YsoILyz7jGxlwG+zjGrq4tznRksmnsvkE5n5LEZzL646wJg1mn9+cdwExvHFuTag04vjRnAO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"; \ No newline at end of file diff --git a/_docs/master/embedding/sdk/api/index.html b/_docs/master/embedding/sdk/api/index.html index 08539de495..3f6f5efd08 100644 --- a/_docs/master/embedding/sdk/api/index.html +++ b/_docs/master/embedding/sdk/api/index.html @@ -9,4 +9,4 @@ layout: docs-api --- -Embedded analytics SDK API{% include docs/embedded-analytics-sdk-metadata.html %}

    Embedded analytics SDK API

    CollectionBrowser

    CollectionBrowser
    CollectionBrowserProps

    CreateDashboardModal

    CreateDashboardModal
    CreateDashboardModalProps

    CreateQuestion

    CreateQuestion
    CreateQuestionProps

    Dashboard

    EditableDashboard
    InteractiveDashboard
    StaticDashboard
    EditableDashboardProps
    InteractiveDashboardProps
    StaticDashboardProps

    InteractiveQuestion

    InteractiveQuestion
    DrillThroughQuestionProps
    InteractiveQuestionChartTypeDropdownProps
    InteractiveQuestionEditorButtonProps
    InteractiveQuestionEditorProps
    InteractiveQuestionProps
    InteractiveQuestionQuestionSettingsDropdownProps
    InteractiveQuestionQuestionVisualizationProps
    InteractiveQuestionResetButtonProps
    InteractiveQuestionSaveQuestionFormProps
    InteractiveQuestionTitleProps
    SdkQuestionProps
    InteractiveQuestionBackButtonProps
    InteractiveQuestionBreakoutDropdownProps
    InteractiveQuestionChartTypeSelectorProps
    InteractiveQuestionDownloadWidgetDropdownProps
    InteractiveQuestionDownloadWidgetProps
    InteractiveQuestionFilterDropdownProps
    InteractiveQuestionFilterProps
    InteractiveQuestionQuestionSettingsProps
    InteractiveQuestionSaveButtonProps
    InteractiveQuestionSummarizeDropdownProps

    MetabaseProvider

    defineMetabaseAuthConfig
    MetabaseProvider
    MetabaseProviderProps
    MetabaseAuthConfig
    MetabaseAuthConfigWithApiKey
    MetabaseAuthConfigWithJwt
    MetabaseAuthConfigWithSaml
    MetabaseIsGuestAuthConfig

    MetabotQuestion

    MetabotQuestion
    MetabotQuestionProps

    StaticQuestion

    StaticQuestion
    StaticQuestionProps

    Theming

    MetabaseEmbeddingThemeV2
    ChartColorV2
    MetabaseColorKey
    MetabaseEmbeddingTheme

    other

    InteractiveQuestionComponents
    MetabaseColors
    MetabaseQuestion
    MetabaseTheme
    StaticQuestionComponents
    ButtonProps
    ChartColor
    CollectionBrowserListColumns
    CustomDashboardCardMenuItem
    DashboardCardCustomMenuItem
    DashboardCardMenu
    DashboardCardMenuCustomElement
    DashCardMenuItem
    EmbeddingDataPicker
    EmbeddingEntityType
    EntityTypeFilterKeys
    IconName
    InitializationStatus
    LoginStatus
    MetabaseClickAction
    MetabaseClickActionPluginsConfig
    MetabaseCollection
    MetabaseCollectionItem
    MetabaseComponentTheme
    MetabaseDashboard
    MetabaseDashboardPluginsConfig
    MetabaseDataPointObject
    MetabaseEmbeddingColorKeyV2
    MetabaseFetchRequestTokenFn
    MetabaseFontFamily
    MetabaseGlobalPluginsConfig
    MetabasePluginsConfig
    MetabaseThemePreset
    MetabaseUser
    ParameterValues
    ProtectedColorKey
    SdkCollectionId
    SdkDashboardEntityPublicProps
    SdkDashboardId
    SdkDashboardLoadEvent
    SdkEntityId
    SdkEntityToken
    SdkErrorComponent
    SdkErrorComponentProps
    SdkEventHandlersConfig
    SdkQuestionEntityPublicProps
    SdkQuestionId
    SdkQuestionTitleProps
    SdkUserId
    SqlParameterValues
    UserBackendJwtResponse

    useApplicationName

    useApplicationName

    useAvailableFonts

    useAvailableFonts

    useCreateDashboardApi

    useCreateDashboardApi
    CreateDashboardValues

    useCurrentUser

    useCurrentUser

    useMetabaseAuthStatus

    useMetabaseAuthStatus

    +Embedded analytics SDK API{% include docs/embedded-analytics-sdk-metadata.html %}

    Embedded analytics SDK API

    CollectionBrowser

    CollectionBrowser
    CollectionBrowserProps

    CreateDashboardModal

    CreateDashboardModal
    CreateDashboardModalProps

    CreateQuestion

    CreateQuestion
    CreateQuestionProps

    Dashboard

    EditableDashboard
    InteractiveDashboard
    StaticDashboard
    EditableDashboardProps
    InteractiveDashboardProps
    StaticDashboardProps
    ParameterChangePayload
    ParameterChangeSource

    InteractiveQuestion

    InteractiveQuestion
    DrillThroughQuestionProps
    InteractiveQuestionChartTypeDropdownProps
    InteractiveQuestionEditorButtonProps
    InteractiveQuestionEditorProps
    InteractiveQuestionProps
    InteractiveQuestionQuestionSettingsDropdownProps
    InteractiveQuestionQuestionVisualizationProps
    InteractiveQuestionResetButtonProps
    InteractiveQuestionSaveQuestionFormProps
    InteractiveQuestionTitleProps
    SdkQuestionProps
    InteractiveQuestionBackButtonProps
    InteractiveQuestionBreakoutDropdownProps
    InteractiveQuestionChartTypeSelectorProps
    InteractiveQuestionDownloadWidgetDropdownProps
    InteractiveQuestionDownloadWidgetProps
    InteractiveQuestionFilterDropdownProps
    InteractiveQuestionFilterProps
    InteractiveQuestionQuestionSettingsProps
    InteractiveQuestionSaveButtonProps
    InteractiveQuestionSummarizeDropdownProps
    SqlParameterChangePayload
    SqlParameterChangeSource

    MetabaseProvider

    defineMetabaseAuthConfig
    MetabaseProvider
    MetabaseProviderProps
    MetabaseAuthConfig
    MetabaseAuthConfigWithApiKey
    MetabaseAuthConfigWithJwt
    MetabaseAuthConfigWithSaml
    MetabaseIsGuestAuthConfig

    MetabotQuestion

    MetabotQuestion
    MetabotQuestionProps

    StaticQuestion

    StaticQuestion
    StaticQuestionProps

    Theming

    MetabaseEmbeddingThemeV2
    ChartColorV2
    MetabaseColorKey
    MetabaseEmbeddingTheme

    other

    InteractiveQuestionComponents
    MetabaseColors
    MetabaseQuestion
    MetabaseTheme
    StaticQuestionComponents
    ButtonProps
    ChartColor
    CollectionBrowserListColumns
    CustomDashboardCardMenuItem
    DashboardCardCustomMenuItem
    DashboardCardMenu
    DashboardCardMenuCustomElement
    DashCardMenuItem
    EmbeddingDataPicker
    EmbeddingEntityType
    EntityTypeFilterKeys
    IconName
    InitializationStatus
    LoginStatus
    MetabaseClickAction
    MetabaseClickActionPluginsConfig
    MetabaseCollection
    MetabaseCollectionItem
    MetabaseComponentTheme
    MetabaseDashboard
    MetabaseDashboardPluginsConfig
    MetabaseDataPointObject
    MetabaseEmbeddingColorKeyV2
    MetabaseFetchRequestTokenFn
    MetabaseFontFamily
    MetabaseGlobalPluginsConfig
    MetabasePluginsConfig
    MetabaseThemePreset
    MetabaseUser
    MetabotAgentChartMessage
    MetabotAgentMessage
    MetabotAgentTextMessage
    MetabotUserTextMessage
    ParameterValues
    ProtectedColorKey
    SdkCollectionId
    SdkDashboardEntityPublicProps
    SdkDashboardId
    SdkDashboardLoadEvent
    SdkEntityId
    SdkEntityToken
    SdkErrorComponent
    SdkErrorComponentProps
    SdkEventHandlersConfig
    SdkQuestionEntityPublicProps
    SdkQuestionId
    SdkQuestionTitleProps
    SdkUserId
    SqlParameterValues
    UserBackendJwtResponse

    useApplicationName

    useApplicationName

    useAvailableFonts

    useAvailableFonts

    useCreateDashboardApi

    useCreateDashboardApi
    CreateDashboardValues

    useCurrentUser

    useCurrentUser

    useMetabaseAuthStatus

    useMetabaseAuthStatus

    useMetabot

    useMetabot
    MetabotChartProps
    MetabotErrorMessage
    MetabotMessage
    UseMetabotResult

    diff --git a/_docs/master/embedding/sdk/api/snippets/CreateQuestionProps.md b/_docs/master/embedding/sdk/api/snippets/CreateQuestionProps.md index fbb51ec980..c989ca8ad3 100644 --- a/_docs/master/embedding/sdk/api/snippets/CreateQuestionProps.md +++ b/_docs/master/embedding/sdk/api/snippets/CreateQuestionProps.md @@ -15,27 +15,31 @@ layout: new-docs -| Property | Type | Description | -| :---------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------- | -| `className?` | `string` | A custom class name to be added to the root element. | -| `dataPicker?` | [`EmbeddingDataPicker`](./api/EmbeddingDataPicker) | Controls the menu for selecting data sources in questions. You can opt for the full data picker by setting `dataPicker = "staged"`. | -| `entityTypes?` | [`EmbeddingEntityType`](./api/EmbeddingEntityType)[] | An array that specifies which entity types are available in the data picker | -| `height?` | `Height`\<`string` \| `number`\> | A number or string specifying a CSS size value that specifies the height of the component | -| `hiddenParameters?` | `string`[] | A list of parameters to hide. | -| `initialSqlParameters?` | [`SqlParameterValues`](./api/SqlParameterValues) | Initial values for the SQL parameters. | -| `isSaveEnabled?` | `boolean` | Whether to show the save button. | -| `onBeforeSave?` | (`question`: [`MetabaseQuestion`](./api/MetabaseQuestion) \| `undefined`, `context`: \{ `isNewQuestion`: `boolean`; \}) => [`Promise`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise)\<`void`\> | A callback function that triggers before saving. Only relevant when `isSaveEnabled = true` | -| `onNavigateBack?` | () => `void` | A callback function that triggers when a user clicks the back button. | -| `onRun?` | (`question`: [`MetabaseQuestion`](./api/MetabaseQuestion) \| `undefined`) => `void` | A callback function that triggers when a question is updated, including when a user clicks the `Visualize` button in the question editor | -| `onSave?` | (`question`: [`MetabaseQuestion`](./api/MetabaseQuestion), `context`: \{ `dashboardTabId?`: `number`; `isNewQuestion`: `boolean`; \}) => `void` | A callback function that triggers when a user saves the question. Only relevant when `isSaveEnabled = true` | -| `onVisualizationChange?` | (`display`: \| `"object"` \| `"table"` \| `"bar"` \| `"line"` \| `"pie"` \| `"scalar"` \| `"row"` \| `"area"` \| `"combo"` \| `"pivot"` \| `"smartscalar"` \| `"gauge"` \| `"progress"` \| `"funnel"` \| `"map"` \| `"scatter"` \| `"boxplot"` \| `"waterfall"` \| `"sankey"` \| `"list"`) => `void` | A callback function that triggers when the visualization type changes. | -| `plugins?` | [`MetabasePluginsConfig`](./api/MetabasePluginsConfig) | - | -| `style?` | [`CSSProperties`](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/0b728411cd1dfb4bd26992bb35a73cf8edaa22e7/types/react/index.d.ts#L2579) | A custom style object to be added to the root element. | -| `targetCollection?` | [`SdkCollectionId`](./api/SdkCollectionId) | The collection to save the question to. This will hide the collection picker from the save modal. Only applicable to interactive questions. | -| `title?` | [`SdkQuestionTitleProps`](./api/SdkQuestionTitleProps) | Determines whether the question title is displayed, and allows a custom title to be displayed instead of the default question title. Shown by default. | -| `width?` | `Width`\<`string` \| `number`\> | A number or string specifying a CSS size value that specifies the width of the component | -| `withAlerts?` | `boolean` | Enables the ability to set up alerts on the question. | -| `withChartTypeSelector?` | `boolean` | Determines whether the chart type selector and corresponding settings button are shown. Only relevant when using the default layout. | -| `withDownloads?` | `boolean` | Enables the ability to download results in the question. | +| Property | Type | Description | +| :---------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `className?` | `string` | A custom class name to be added to the root element. | +| `dataPicker?` | [`EmbeddingDataPicker`](./api/EmbeddingDataPicker) | Controls the menu for selecting data sources in questions. You can opt for the full data picker by setting `dataPicker = "staged"`. | +| `entityTypes?` | [`EmbeddingEntityType`](./api/EmbeddingEntityType)[] | An array that specifies which entity types are available in the data picker | +| `height?` | `Height`\<`string` \| `number`\> | A number or string specifying a CSS size value that specifies the height of the component | +| `hiddenParameters?` | `string`[] | A list of parameters to hide. | +| `initialCollection?` | [`SdkCollectionId`](./api/SdkCollectionId) | The collection to preselect in the save modal's collection picker. Unlike `targetCollection`, the picker remains visible and the user can choose a different collection. Ignored when `targetCollection` is set. | +| `initialSqlParameters?` | [`SqlParameterValues`](./api/SqlParameterValues) | Initial values for SQL parameters, slug-keyed. Applied once on mount; user widget edits afterwards are not reflected back to the host.
    For each parameter:
    - set to a value: that value is applied.
    - set to `null`: strictly cleared, ignoring the parameter's default.
    - omitted (or set to `undefined`): falls back to the parameter's default (or `null` if it has no default). | +| `isSaveEnabled?` | `boolean` | Whether to show the save button. | +| `onBeforeSave?` | (`question`: [`MetabaseQuestion`](./api/MetabaseQuestion) \| `undefined`, `context`: \{ `isNewQuestion`: `boolean`; \}) => [`Promise`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise)\<`void`\> | A callback function that triggers before saving. Only relevant when `isSaveEnabled = true` | +| `onNavigateBack?` | () => `void` | A callback function that triggers when a user clicks the back button. | +| `onRun?` | (`question`: [`MetabaseQuestion`](./api/MetabaseQuestion) \| `undefined`) => `void` | A callback function that triggers when a question is updated, including when a user clicks the `Visualize` button in the question editor | +| `onSave?` | (`question`: [`MetabaseQuestion`](./api/MetabaseQuestion), `context`: \{ `dashboardTabId?`: `number`; `isNewQuestion`: `boolean`; \}) => `void` | A callback function that triggers when a user saves the question. Only relevant when `isSaveEnabled = true` | +| `onSqlParametersChange?` | (`payload`: [`SqlParameterChangePayload`](./api/SqlParameterChangePayload)) => `void` | Fires on SQL parameters change. The payload's `source` distinguishes the initial state on load (`'initial-state'`), user edits in the UI (`'manual-change'`), and auto-updates (`'auto-change'`). | +| `onVisualizationChange?` | (`display`: \| `"object"` \| `"table"` \| `"bar"` \| `"line"` \| `"pie"` \| `"scalar"` \| `"row"` \| `"area"` \| `"combo"` \| `"pivot"` \| `"smartscalar"` \| `"gauge"` \| `"progress"` \| `"funnel"` \| `"map"` \| `"scatter"` \| `"boxplot"` \| `"waterfall"` \| `"sankey"` \| `"list"`) => `void` | A callback function that triggers when the visualization type changes. | +| `plugins?` | [`MetabasePluginsConfig`](./api/MetabasePluginsConfig) | - | +| `sqlParameters?` | [`SqlParameterValues`](./api/SqlParameterValues) | Controlled SQL parameter values, slug-keyed. On every render, this object replaces the question's parameter values:
    - a parameter set to a value uses that value.
    - a parameter set to `null` is cleared, even if it has a default.
    - a parameter omitted from the object (or set to `undefined`) uses its default (or `null` if it has no default).

    Pair with `onSqlParametersChange` to stay in sync with user edits. | +| `style?` | [`CSSProperties`](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/0b728411cd1dfb4bd26992bb35a73cf8edaa22e7/types/react/index.d.ts#L2579) | A custom style object to be added to the root element. | +| `targetCollection?` | [`SdkCollectionId`](./api/SdkCollectionId) | The collection to save the question to. This will hide the collection picker from the save modal. Only applicable to interactive questions. | +| `title?` | [`SdkQuestionTitleProps`](./api/SdkQuestionTitleProps) | Determines whether the question title is displayed, and allows a custom title to be displayed instead of the default question title. Shown by default. | +| `width?` | `Width`\<`string` \| `number`\> | A number or string specifying a CSS size value that specifies the width of the component | +| `withAlerts?` | `boolean` | Enables the ability to set up alerts on the question. | +| `withChartTypeSelector?` | `boolean` | Determines whether the chart type selector and corresponding settings button are shown. Only relevant when using the default layout. | +| `withDownloads?` | `boolean` | Enables the ability to download results in the question. | +| `withEditorButton?` | `boolean` | Determines whether the editor button is shown. Only relevant when using the default layout. | diff --git a/_docs/master/embedding/sdk/api/snippets/DrillThroughQuestionProps.md b/_docs/master/embedding/sdk/api/snippets/DrillThroughQuestionProps.md index 5451482d1b..7615ac5d24 100644 --- a/_docs/master/embedding/sdk/api/snippets/DrillThroughQuestionProps.md +++ b/_docs/master/embedding/sdk/api/snippets/DrillThroughQuestionProps.md @@ -17,25 +17,27 @@ Props for the drill-through question -| Property | Type | Description | -| :---------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------- | -| `children?` | [`ReactNode`](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/0b728411cd1dfb4bd26992bb35a73cf8edaa22e7/types/react/index.d.ts#L478) | The children of the component | -| `className?` | `string` | A custom class name to be added to the root element. | -| `dataPicker?` | [`EmbeddingDataPicker`](./api/EmbeddingDataPicker) | Controls the menu for selecting data sources in questions. You can opt for the full data picker by setting `dataPicker = "staged"`. | -| `entityTypes?` | [`EmbeddingEntityType`](./api/EmbeddingEntityType)[] | An array that specifies which entity types are available in the data picker | -| `height?` | `Height`\<`string` \| `number`\> | A number or string specifying a CSS size value that specifies the height of the component | -| `initialSqlParameters?` | [`SqlParameterValues`](./api/SqlParameterValues) | Initial values for the SQL parameters. | -| `isSaveEnabled?` | `boolean` | Whether to show the save button. | -| `onBeforeSave?` | (`question`: [`MetabaseQuestion`](./api/MetabaseQuestion) \| `undefined`, `context`: \{ `isNewQuestion`: `boolean`; \}) => [`Promise`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise)\<`void`\> | A callback function that triggers before saving. Only relevant when `isSaveEnabled = true` | -| `onRun?` | (`question`: [`MetabaseQuestion`](./api/MetabaseQuestion) \| `undefined`) => `void` | A callback function that triggers when a question is updated, including when a user clicks the `Visualize` button in the question editor | -| `onSave?` | (`question`: [`MetabaseQuestion`](./api/MetabaseQuestion), `context`: \{ `dashboardTabId?`: `number`; `isNewQuestion`: `boolean`; \}) => `void` | A callback function that triggers when a user saves the question. Only relevant when `isSaveEnabled = true` | -| `plugins?` | [`MetabasePluginsConfig`](./api/MetabasePluginsConfig) | - | -| `style?` | [`CSSProperties`](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/0b728411cd1dfb4bd26992bb35a73cf8edaa22e7/types/react/index.d.ts#L2579) | A custom style object to be added to the root element. | -| `targetCollection?` | [`SdkCollectionId`](./api/SdkCollectionId) | The collection to save the question to. This will hide the collection picker from the save modal. Only applicable to interactive questions. | -| `title?` | [`SdkQuestionTitleProps`](./api/SdkQuestionTitleProps) | Determines whether the question title is displayed, and allows a custom title to be displayed instead of the default question title. Shown by default. | -| `width?` | `Width`\<`string` \| `number`\> | A number or string specifying a CSS size value that specifies the width of the component | -| `withAlerts?` | `boolean` | Enables the ability to set up alerts on the question. | -| `withChartTypeSelector?` | `boolean` | Determines whether the chart type selector and corresponding settings button are shown. Only relevant when using the default layout. | -| `withDownloads?` | `boolean` | Enables the ability to download results in the question. | +| Property | Type | Description | +| :---------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `children?` | [`ReactNode`](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/0b728411cd1dfb4bd26992bb35a73cf8edaa22e7/types/react/index.d.ts#L478) | The children of the component | +| `className?` | `string` | A custom class name to be added to the root element. | +| `dataPicker?` | [`EmbeddingDataPicker`](./api/EmbeddingDataPicker) | Controls the menu for selecting data sources in questions. You can opt for the full data picker by setting `dataPicker = "staged"`. | +| `entityTypes?` | [`EmbeddingEntityType`](./api/EmbeddingEntityType)[] | An array that specifies which entity types are available in the data picker | +| `height?` | `Height`\<`string` \| `number`\> | A number or string specifying a CSS size value that specifies the height of the component | +| `initialCollection?` | [`SdkCollectionId`](./api/SdkCollectionId) | The collection to preselect in the save modal's collection picker. Unlike `targetCollection`, the picker remains visible and the user can choose a different collection. Ignored when `targetCollection` is set. | +| `initialSqlParameters?` | [`SqlParameterValues`](./api/SqlParameterValues) | Initial values for SQL parameters, slug-keyed. Applied once on mount; user widget edits afterwards are not reflected back to the host.
    For each parameter:
    - set to a value: that value is applied.
    - set to `null`: strictly cleared, ignoring the parameter's default.
    - omitted (or set to `undefined`): falls back to the parameter's default (or `null` if it has no default). | +| `isSaveEnabled?` | `boolean` | Whether to show the save button. | +| `onBeforeSave?` | (`question`: [`MetabaseQuestion`](./api/MetabaseQuestion) \| `undefined`, `context`: \{ `isNewQuestion`: `boolean`; \}) => [`Promise`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise)\<`void`\> | A callback function that triggers before saving. Only relevant when `isSaveEnabled = true` | +| `onRun?` | (`question`: [`MetabaseQuestion`](./api/MetabaseQuestion) \| `undefined`) => `void` | A callback function that triggers when a question is updated, including when a user clicks the `Visualize` button in the question editor | +| `onSave?` | (`question`: [`MetabaseQuestion`](./api/MetabaseQuestion), `context`: \{ `dashboardTabId?`: `number`; `isNewQuestion`: `boolean`; \}) => `void` | A callback function that triggers when a user saves the question. Only relevant when `isSaveEnabled = true` | +| `plugins?` | [`MetabasePluginsConfig`](./api/MetabasePluginsConfig) | - | +| `style?` | [`CSSProperties`](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/0b728411cd1dfb4bd26992bb35a73cf8edaa22e7/types/react/index.d.ts#L2579) | A custom style object to be added to the root element. | +| `targetCollection?` | [`SdkCollectionId`](./api/SdkCollectionId) | The collection to save the question to. This will hide the collection picker from the save modal. Only applicable to interactive questions. | +| `title?` | [`SdkQuestionTitleProps`](./api/SdkQuestionTitleProps) | Determines whether the question title is displayed, and allows a custom title to be displayed instead of the default question title. Shown by default. | +| `width?` | `Width`\<`string` \| `number`\> | A number or string specifying a CSS size value that specifies the width of the component | +| `withAlerts?` | `boolean` | Enables the ability to set up alerts on the question. | +| `withChartTypeSelector?` | `boolean` | Determines whether the chart type selector and corresponding settings button are shown. Only relevant when using the default layout. | +| `withDownloads?` | `boolean` | Enables the ability to download results in the question. | +| `withEditorButton?` | `boolean` | Determines whether the editor button is shown. Only relevant when using the default layout. | diff --git a/_docs/master/embedding/sdk/api/snippets/EditableDashboardProps.md b/_docs/master/embedding/sdk/api/snippets/EditableDashboardProps.md index 441c108109..02204ed1fe 100644 --- a/_docs/master/embedding/sdk/api/snippets/EditableDashboardProps.md +++ b/_docs/master/embedding/sdk/api/snippets/EditableDashboardProps.md @@ -15,27 +15,29 @@ layout: new-docs -| Property | Type | Description | -| :-------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `autoRefreshInterval?` | `number` | The interval between auto refreshes on the dashboard, in seconds. | -| `className?` | `string` | A custom class name to be added to the root element. | -| `dashboardId` | `string` \| `number` | The ID of the dashboard.
    This is either:
    - the numerical ID when accessing a dashboard link, i.e. `http://localhost:3000/dashboard/1-my-dashboard` where the ID is `1`
    - the string ID found in the `entity_id` key of the dashboard object when using the API directly or using the SDK Collection Browser to return data | -| `dataPickerProps?` | [`Pick`](https://www.typescriptlang.org/docs/handbook/utility-types.html#picktype-keys)\<[`SdkQuestionProps`](./api/SdkQuestionProps), `"entityTypes"`\> | Additional props to pass to the query builder rendered by `InteractiveQuestion` when creating a new dashboard question. | -| `drillThroughQuestionHeight?` | `Height`\<`string` \| `number`\> | Height of a question component when drilled from the dashboard to a question level. | -| `drillThroughQuestionProps?` | [`DrillThroughQuestionProps`](./api/DrillThroughQuestionProps) | Props of a question component when drilled from the dashboard to a question level. | -| `enableEntityNavigation?` | `boolean` | When true, internal click behaviors (links to dashboards/questions) are preserved. When false (default for SDK), these click behaviors are filtered out. | -| `hiddenParameters?` | `string`[] | A list of [parameters to hide](/docs/master/embedding/public-links#appearance-parameters).
    - Combining [initialParameters](./api/InteractiveDashboardProps#initialparameters) and [hiddenParameters](./api/InteractiveDashboardProps#hiddenparameters) to filter data on the frontend is a [security risk](/docs/master/embedding/sdk/authentication#security-warning-each-end-user-must-have-their-own-metabase-account).
    - Combining [initialParameters](./api/InteractiveDashboardProps#initialparameters) and [hiddenParameters](./api/InteractiveDashboardProps#hiddenparameters) to declutter the user interface is fine. | -| `initialParameters?` | [`ParameterValues`](./api/ParameterValues) | Query parameters for the dashboard. For a single option, use a `string` value, and use a list of strings for multiple options.
    - Combining [initialParameters](./api/InteractiveDashboardProps#initialparameters) and [hiddenParameters](./api/InteractiveDashboardProps#hiddenparameters) to filter data on the frontend is a [security risk](/docs/master/embedding/sdk/authentication#security-warning-each-end-user-must-have-their-own-metabase-account).
    - Combining [initialParameters](./api/InteractiveDashboardProps#initialparameters) and [hiddenParameters](./api/InteractiveDashboardProps#hiddenparameters) to declutter the user interface is fine. | -| `onLoad?` | (`dashboard`: [`MetabaseDashboard`](./api/MetabaseDashboard) \| `null`) => `void` | Callback that is called when the dashboard is loaded. | -| `onLoadWithoutCards?` | (`dashboard`: [`MetabaseDashboard`](./api/MetabaseDashboard) \| `null`) => `void` | Callback that is called when the dashboard is loaded without cards. | -| `onVisualizationChange?` | (`visualization`: \| `"object"` \| `"table"` \| `"bar"` \| `"line"` \| `"pie"` \| `"scalar"` \| `"row"` \| `"area"` \| `"combo"` \| `"pivot"` \| `"smartscalar"` \| `"gauge"` \| `"progress"` \| `"funnel"` \| `"map"` \| `"scatter"` \| `"boxplot"` \| `"waterfall"` \| `"sankey"` \| `"list"`) => `void` | A callback function that triggers when a question is opened from a dashboard card or when the user changes the visualization type of a question. | -| `plugins?` | [`MetabasePluginsConfig`](./api/MetabasePluginsConfig) | Additional mapper function to override or add drill-down menu. See the implementing custom actions section for more details. | -| `renderDrillThroughQuestion?` | () => [`ReactNode`](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/0b728411cd1dfb4bd26992bb35a73cf8edaa22e7/types/react/index.d.ts#L478) | A custom React component to render the question layout. Use namespaced InteractiveQuestion components to build the layout. | -| `style?` | [`CSSProperties`](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/0b728411cd1dfb4bd26992bb35a73cf8edaa22e7/types/react/index.d.ts#L2579) | A custom style object to be added to the root element. | -| `token?` | `string` \| `null` | - | -| `withCardTitle?` | `boolean` | Whether the dashboard cards should display a title. | -| `withDownloads?` | `boolean` | Whether to hide the download button. | -| `withSubscriptions?` | `boolean` | Whether to show the subscriptions button. | -| `withTitle?` | `boolean` | Whether the dashboard should display a title. | +| Property | Type | Description | +| :-------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `autoRefreshInterval?` | `number` | The interval between auto refreshes on the dashboard, in seconds. | +| `className?` | `string` | A custom class name to be added to the root element. | +| `dashboardId` | `string` \| `number` | The ID of the dashboard.
    This is either:
    - the numerical ID when accessing a dashboard link, i.e. `http://localhost:3000/dashboard/1-my-dashboard` where the ID is `1`
    - the string ID found in the `entity_id` key of the dashboard object when using the API directly or using the SDK Collection Browser to return data | +| `dataPickerProps?` | [`Pick`](https://www.typescriptlang.org/docs/handbook/utility-types.html#picktype-keys)\<[`SdkQuestionProps`](./api/SdkQuestionProps), `"entityTypes"`\> | Additional props to pass to the query builder rendered by `InteractiveQuestion` when creating a new dashboard question. | +| `drillThroughQuestionHeight?` | `Height`\<`string` \| `number`\> | Height of a question component when drilled from the dashboard to a question level. | +| `drillThroughQuestionProps?` | [`DrillThroughQuestionProps`](./api/DrillThroughQuestionProps) | Props of a question component when drilled from the dashboard to a question level. | +| `enableEntityNavigation?` | `boolean` | When true, internal click behaviors (links to dashboards/questions) are preserved. When false (default for SDK), these click behaviors are filtered out. | +| `hiddenParameters?` | `string`[] | A list of [parameters to hide](/docs/master/embedding/public-links#appearance-parameters).
    - Combining [initialParameters](./api/InteractiveDashboardProps#initialparameters) and [hiddenParameters](./api/InteractiveDashboardProps#hiddenparameters) to filter data on the frontend is a [security risk](/docs/master/embedding/sdk/authentication#security-warning-each-end-user-must-have-their-own-metabase-account).
    - Combining [initialParameters](./api/InteractiveDashboardProps#initialparameters) and [hiddenParameters](./api/InteractiveDashboardProps#hiddenparameters) to declutter the user interface is fine. | +| `initialParameters?` | [`ParameterValues`](./api/ParameterValues) | Initial values for query parameters, slug-keyed. Applied once on mount; user widget edits afterwards are not reflected back to the host.
    For each parameter:
    - set to a value (string for a single option, array of strings for multiple): that value is applied.
    - set to `null`: strictly cleared, ignoring the parameter's default.
    - omitted (or set to `undefined`): falls back to the parameter's default (or `null` if it has no default).

    - Combining [initialParameters](./api/InteractiveDashboardProps#initialparameters) and [hiddenParameters](./api/InteractiveDashboardProps#hiddenparameters) to filter data on the frontend is a [security risk](/docs/master/embedding/sdk/authentication#security-warning-each-end-user-must-have-their-own-metabase-account).
    - Combining [initialParameters](./api/InteractiveDashboardProps#initialparameters) and [hiddenParameters](./api/InteractiveDashboardProps#hiddenparameters) to declutter the user interface is fine. | +| `onLoad?` | (`dashboard`: [`MetabaseDashboard`](./api/MetabaseDashboard) \| `null`) => `void` | Callback that is called when the dashboard is loaded. | +| `onLoadWithoutCards?` | (`dashboard`: [`MetabaseDashboard`](./api/MetabaseDashboard) \| `null`) => `void` | Callback that is called when the dashboard is loaded without cards. | +| `onParametersChange?` | (`payload`: [`ParameterChangePayload`](./api/ParameterChangePayload)) => `void` | Fires on parameters change. The payload's `source` distinguishes the initial state on load (`'initial-state'`), user edits in the UI (`'manual-change'`), and auto-updates (`'auto-change'`). | +| `onVisualizationChange?` | (`visualization`: \| `"object"` \| `"table"` \| `"bar"` \| `"line"` \| `"pie"` \| `"scalar"` \| `"row"` \| `"area"` \| `"combo"` \| `"pivot"` \| `"smartscalar"` \| `"gauge"` \| `"progress"` \| `"funnel"` \| `"map"` \| `"scatter"` \| `"boxplot"` \| `"waterfall"` \| `"sankey"` \| `"list"`) => `void` | A callback function that triggers when a question is opened from a dashboard card or when the user changes the visualization type of a question. | +| `parameters?` | [`ParameterValues`](./api/ParameterValues) | Controlled parameter values, slug-keyed. On every render, this object replaces the dashboard's parameter values:
    - a parameter set to a value uses that value.
    - a parameter set to `null` is cleared, even if it has a default.
    - a parameter omitted from the object (or set to `undefined`) uses its default (or `null` if it has no default).

    Pair with [onParametersChange](./api/InteractiveDashboardProps#onparameterschange) to stay in sync with user edits.
    - Combining [parameters](./api/InteractiveDashboardProps#parameters) and [hiddenParameters](./api/InteractiveDashboardProps#hiddenparameters) to filter data on the frontend is a [security risk](/docs/master/embedding/sdk/authentication#security-warning-each-end-user-must-have-their-own-metabase-account).
    - Combining [parameters](./api/InteractiveDashboardProps#parameters) and [hiddenParameters](./api/InteractiveDashboardProps#hiddenparameters) to declutter the user interface is fine. | +| `plugins?` | [`MetabasePluginsConfig`](./api/MetabasePluginsConfig) | Additional mapper function to override or add drill-down menu. See the implementing custom actions section for more details. | +| `renderDrillThroughQuestion?` | () => [`ReactNode`](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/0b728411cd1dfb4bd26992bb35a73cf8edaa22e7/types/react/index.d.ts#L478) | A custom React component to render the question layout. Use namespaced InteractiveQuestion components to build the layout. | +| `style?` | [`CSSProperties`](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/0b728411cd1dfb4bd26992bb35a73cf8edaa22e7/types/react/index.d.ts#L2579) | A custom style object to be added to the root element. | +| `token?` | `string` \| `null` | - | +| `withCardTitle?` | `boolean` | Whether the dashboard cards should display a title. | +| `withDownloads?` | `boolean` | Whether to hide the download button. | +| `withSubscriptions?` | `boolean` | Whether to show the subscriptions button. | +| `withTitle?` | `boolean` | Whether the dashboard should display a title. | diff --git a/_docs/master/embedding/sdk/api/snippets/IconName.md b/_docs/master/embedding/sdk/api/snippets/IconName.md index 969ba90cf7..4899b8ca68 100644 --- a/_docs/master/embedding/sdk/api/snippets/IconName.md +++ b/_docs/master/embedding/sdk/api/snippets/IconName.md @@ -181,6 +181,7 @@ type IconName = | "lock_filled" | "mail" | "mail_filled" + | "mcp" | "medallion" | "message_circle" | "metabot" @@ -248,6 +249,7 @@ type IconName = | "segment" | "shield" | "shield_outline" + | "shield_stroke" | "sidebar_closed" | "sidebar_open" | "slack" diff --git a/_docs/master/embedding/sdk/api/snippets/InteractiveDashboard.md b/_docs/master/embedding/sdk/api/snippets/InteractiveDashboard.md index 5a2b6806b0..4e513a43ef 100644 --- a/_docs/master/embedding/sdk/api/snippets/InteractiveDashboard.md +++ b/_docs/master/embedding/sdk/api/snippets/InteractiveDashboard.md @@ -17,6 +17,8 @@ function InteractiveDashboard( drillThroughQuestionHeight?: Height; drillThroughQuestionProps?: DrillThroughQuestionProps; initialParameters?: ParameterValues; + onParametersChange?: (payload: ParameterChangePayload) => void; + parameters?: ParameterValues; plugins?: MetabasePluginsConfig; renderDrillThroughQuestion?: () => ReactNode; } & { @@ -71,9 +73,9 @@ A dashboard component with drill downs, click behaviors, and the ability to view -| Parameter | Type | Description | -| :-------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :---------- | -| `props` | \{ `autoRefreshInterval?`: `number`; `dashboardId`: [`SdkDashboardId`](./api/SdkDashboardId); `drillThroughQuestionHeight?`: `Height`\<`string` \| `number`\>; `drillThroughQuestionProps?`: [`DrillThroughQuestionProps`](./api/DrillThroughQuestionProps); `initialParameters?`: [`ParameterValues`](./api/ParameterValues); `plugins?`: [`MetabasePluginsConfig`](./api/MetabasePluginsConfig); `renderDrillThroughQuestion?`: () => [`ReactNode`](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/0b728411cd1dfb4bd26992bb35a73cf8edaa22e7/types/react/index.d.ts#L478); \} & \{ `dashboardId?`: [`SdkDashboardId`](./api/SdkDashboardId) \| `null`; `token?`: `string` \| `null`; \} & \{ `enableEntityNavigation?`: `boolean`; `hiddenParameters?`: `string`[]; `initialParameters?`: [`ParameterValues`](./api/ParameterValues); `withCardTitle?`: `boolean`; `withDownloads?`: `boolean`; `withSubscriptions?`: `boolean`; `withTitle?`: `boolean`; \} & \{ `className?`: `string`; `style?`: [`CSSProperties`](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/0b728411cd1dfb4bd26992bb35a73cf8edaa22e7/types/react/index.d.ts#L2579); \} & \{ `onLoad?`: (`dashboard`: [`MetabaseDashboard`](./api/MetabaseDashboard) \| `null`) => `void`; `onLoadWithoutCards?`: (`dashboard`: [`MetabaseDashboard`](./api/MetabaseDashboard) \| `null`) => `void`; `onVisualizationChange?`: (`visualization`: \| `"object"` \| `"table"` \| `"bar"` \| `"line"` \| `"pie"` \| `"scalar"` \| `"row"` \| `"area"` \| `"combo"` \| `"pivot"` \| `"smartscalar"` \| `"gauge"` \| `"progress"` \| `"funnel"` \| `"map"` \| `"scatter"` \| `"boxplot"` \| `"waterfall"` \| `"sankey"` \| `"list"`) => `void`; \} & \{ `dataPickerProps?`: [`Pick`](https://www.typescriptlang.org/docs/handbook/utility-types.html#picktype-keys)\<[`SdkQuestionProps`](./api/SdkQuestionProps), `"entityTypes"`\>; \} & \{ \} | | +| Parameter | Type | Description | +| :-------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :---------- | +| `props` | \{ `autoRefreshInterval?`: `number`; `dashboardId`: [`SdkDashboardId`](./api/SdkDashboardId); `drillThroughQuestionHeight?`: `Height`\<`string` \| `number`\>; `drillThroughQuestionProps?`: [`DrillThroughQuestionProps`](./api/DrillThroughQuestionProps); `initialParameters?`: [`ParameterValues`](./api/ParameterValues); `onParametersChange?`: (`payload`: [`ParameterChangePayload`](./api/ParameterChangePayload)) => `void`; `parameters?`: [`ParameterValues`](./api/ParameterValues); `plugins?`: [`MetabasePluginsConfig`](./api/MetabasePluginsConfig); `renderDrillThroughQuestion?`: () => [`ReactNode`](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/0b728411cd1dfb4bd26992bb35a73cf8edaa22e7/types/react/index.d.ts#L478); \} & \{ `dashboardId?`: [`SdkDashboardId`](./api/SdkDashboardId) \| `null`; `token?`: `string` \| `null`; \} & \{ `enableEntityNavigation?`: `boolean`; `hiddenParameters?`: `string`[]; `initialParameters?`: [`ParameterValues`](./api/ParameterValues); `withCardTitle?`: `boolean`; `withDownloads?`: `boolean`; `withSubscriptions?`: `boolean`; `withTitle?`: `boolean`; \} & \{ `className?`: `string`; `style?`: [`CSSProperties`](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/0b728411cd1dfb4bd26992bb35a73cf8edaa22e7/types/react/index.d.ts#L2579); \} & \{ `onLoad?`: (`dashboard`: [`MetabaseDashboard`](./api/MetabaseDashboard) \| `null`) => `void`; `onLoadWithoutCards?`: (`dashboard`: [`MetabaseDashboard`](./api/MetabaseDashboard) \| `null`) => `void`; `onVisualizationChange?`: (`visualization`: \| `"object"` \| `"table"` \| `"bar"` \| `"line"` \| `"pie"` \| `"scalar"` \| `"row"` \| `"area"` \| `"combo"` \| `"pivot"` \| `"smartscalar"` \| `"gauge"` \| `"progress"` \| `"funnel"` \| `"map"` \| `"scatter"` \| `"boxplot"` \| `"waterfall"` \| `"sankey"` \| `"list"`) => `void`; \} & \{ `dataPickerProps?`: [`Pick`](https://www.typescriptlang.org/docs/handbook/utility-types.html#picktype-keys)\<[`SdkQuestionProps`](./api/SdkQuestionProps), `"entityTypes"`\>; \} & \{ \} | | diff --git a/_docs/master/embedding/sdk/api/snippets/InteractiveDashboardProps.md b/_docs/master/embedding/sdk/api/snippets/InteractiveDashboardProps.md index 7ef47d46a9..6f4d207aa3 100644 --- a/_docs/master/embedding/sdk/api/snippets/InteractiveDashboardProps.md +++ b/_docs/master/embedding/sdk/api/snippets/InteractiveDashboardProps.md @@ -15,27 +15,29 @@ layout: new-docs -| Property | Type | Description | -| :-------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `autoRefreshInterval?` | `number` | The interval between auto refreshes on the dashboard, in seconds. | -| `className?` | `string` | A custom class name to be added to the root element. | -| `dashboardId` | `string` \| `number` | The ID of the dashboard.
    This is either:
    - the numerical ID when accessing a dashboard link, i.e. `http://localhost:3000/dashboard/1-my-dashboard` where the ID is `1`
    - the string ID found in the `entity_id` key of the dashboard object when using the API directly or using the SDK Collection Browser to return data | -| `dataPickerProps?` | [`Pick`](https://www.typescriptlang.org/docs/handbook/utility-types.html#picktype-keys)\<[`SdkQuestionProps`](./api/SdkQuestionProps), `"entityTypes"`\> | Additional props to pass to the query builder rendered by `InteractiveQuestion` when creating a new dashboard question. | -| `drillThroughQuestionHeight?` | `Height`\<`string` \| `number`\> | Height of a question component when drilled from the dashboard to a question level. | -| `drillThroughQuestionProps?` | [`DrillThroughQuestionProps`](./api/DrillThroughQuestionProps) | Props of a question component when drilled from the dashboard to a question level. | -| `enableEntityNavigation?` | `boolean` | When true, internal click behaviors (links to dashboards/questions) are preserved. When false (default for SDK), these click behaviors are filtered out. | -| `hiddenParameters?` | `string`[] | A list of [parameters to hide](/docs/master/embedding/public-links#appearance-parameters).
    - Combining [initialParameters](./api/InteractiveDashboardProps#initialparameters) and [hiddenParameters](./api/InteractiveDashboardProps#hiddenparameters) to filter data on the frontend is a [security risk](/docs/master/embedding/sdk/authentication#security-warning-each-end-user-must-have-their-own-metabase-account).
    - Combining [initialParameters](./api/InteractiveDashboardProps#initialparameters) and [hiddenParameters](./api/InteractiveDashboardProps#hiddenparameters) to declutter the user interface is fine. | -| `initialParameters?` | [`ParameterValues`](./api/ParameterValues) | Query parameters for the dashboard. For a single option, use a `string` value, and use a list of strings for multiple options.
    - Combining [initialParameters](./api/InteractiveDashboardProps#initialparameters) and [hiddenParameters](./api/InteractiveDashboardProps#hiddenparameters) to filter data on the frontend is a [security risk](/docs/master/embedding/sdk/authentication#security-warning-each-end-user-must-have-their-own-metabase-account).
    - Combining [initialParameters](./api/InteractiveDashboardProps#initialparameters) and [hiddenParameters](./api/InteractiveDashboardProps#hiddenparameters) to declutter the user interface is fine. | -| `onLoad?` | (`dashboard`: [`MetabaseDashboard`](./api/MetabaseDashboard) \| `null`) => `void` | Callback that is called when the dashboard is loaded. | -| `onLoadWithoutCards?` | (`dashboard`: [`MetabaseDashboard`](./api/MetabaseDashboard) \| `null`) => `void` | Callback that is called when the dashboard is loaded without cards. | -| `onVisualizationChange?` | (`visualization`: \| `"object"` \| `"table"` \| `"bar"` \| `"line"` \| `"pie"` \| `"scalar"` \| `"row"` \| `"area"` \| `"combo"` \| `"pivot"` \| `"smartscalar"` \| `"gauge"` \| `"progress"` \| `"funnel"` \| `"map"` \| `"scatter"` \| `"boxplot"` \| `"waterfall"` \| `"sankey"` \| `"list"`) => `void` | A callback function that triggers when a question is opened from a dashboard card or when the user changes the visualization type of a question. | -| `plugins?` | [`MetabasePluginsConfig`](./api/MetabasePluginsConfig) | Additional mapper function to override or add drill-down menu. See the implementing custom actions section for more details. | -| `renderDrillThroughQuestion?` | () => [`ReactNode`](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/0b728411cd1dfb4bd26992bb35a73cf8edaa22e7/types/react/index.d.ts#L478) | A custom React component to render the question layout. Use namespaced InteractiveQuestion components to build the layout. | -| `style?` | [`CSSProperties`](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/0b728411cd1dfb4bd26992bb35a73cf8edaa22e7/types/react/index.d.ts#L2579) | A custom style object to be added to the root element. | -| `token?` | `string` \| `null` | - | -| `withCardTitle?` | `boolean` | Whether the dashboard cards should display a title. | -| `withDownloads?` | `boolean` | Whether to hide the download button. | -| `withSubscriptions?` | `boolean` | Whether to show the subscriptions button. | -| `withTitle?` | `boolean` | Whether the dashboard should display a title. | +| Property | Type | Description | +| :-------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `autoRefreshInterval?` | `number` | The interval between auto refreshes on the dashboard, in seconds. | +| `className?` | `string` | A custom class name to be added to the root element. | +| `dashboardId` | `string` \| `number` | The ID of the dashboard.
    This is either:
    - the numerical ID when accessing a dashboard link, i.e. `http://localhost:3000/dashboard/1-my-dashboard` where the ID is `1`
    - the string ID found in the `entity_id` key of the dashboard object when using the API directly or using the SDK Collection Browser to return data | +| `dataPickerProps?` | [`Pick`](https://www.typescriptlang.org/docs/handbook/utility-types.html#picktype-keys)\<[`SdkQuestionProps`](./api/SdkQuestionProps), `"entityTypes"`\> | Additional props to pass to the query builder rendered by `InteractiveQuestion` when creating a new dashboard question. | +| `drillThroughQuestionHeight?` | `Height`\<`string` \| `number`\> | Height of a question component when drilled from the dashboard to a question level. | +| `drillThroughQuestionProps?` | [`DrillThroughQuestionProps`](./api/DrillThroughQuestionProps) | Props of a question component when drilled from the dashboard to a question level. | +| `enableEntityNavigation?` | `boolean` | When true, internal click behaviors (links to dashboards/questions) are preserved. When false (default for SDK), these click behaviors are filtered out. | +| `hiddenParameters?` | `string`[] | A list of [parameters to hide](/docs/master/embedding/public-links#appearance-parameters).
    - Combining [initialParameters](./api/InteractiveDashboardProps#initialparameters) and [hiddenParameters](./api/InteractiveDashboardProps#hiddenparameters) to filter data on the frontend is a [security risk](/docs/master/embedding/sdk/authentication#security-warning-each-end-user-must-have-their-own-metabase-account).
    - Combining [initialParameters](./api/InteractiveDashboardProps#initialparameters) and [hiddenParameters](./api/InteractiveDashboardProps#hiddenparameters) to declutter the user interface is fine. | +| `initialParameters?` | [`ParameterValues`](./api/ParameterValues) | Initial values for query parameters, slug-keyed. Applied once on mount; user widget edits afterwards are not reflected back to the host.
    For each parameter:
    - set to a value (string for a single option, array of strings for multiple): that value is applied.
    - set to `null`: strictly cleared, ignoring the parameter's default.
    - omitted (or set to `undefined`): falls back to the parameter's default (or `null` if it has no default).

    - Combining [initialParameters](./api/InteractiveDashboardProps#initialparameters) and [hiddenParameters](./api/InteractiveDashboardProps#hiddenparameters) to filter data on the frontend is a [security risk](/docs/master/embedding/sdk/authentication#security-warning-each-end-user-must-have-their-own-metabase-account).
    - Combining [initialParameters](./api/InteractiveDashboardProps#initialparameters) and [hiddenParameters](./api/InteractiveDashboardProps#hiddenparameters) to declutter the user interface is fine. | +| `onLoad?` | (`dashboard`: [`MetabaseDashboard`](./api/MetabaseDashboard) \| `null`) => `void` | Callback that is called when the dashboard is loaded. | +| `onLoadWithoutCards?` | (`dashboard`: [`MetabaseDashboard`](./api/MetabaseDashboard) \| `null`) => `void` | Callback that is called when the dashboard is loaded without cards. | +| `onParametersChange?` | (`payload`: [`ParameterChangePayload`](./api/ParameterChangePayload)) => `void` | Fires on parameters change. The payload's `source` distinguishes the initial state on load (`'initial-state'`), user edits in the UI (`'manual-change'`), and auto-updates (`'auto-change'`). | +| `onVisualizationChange?` | (`visualization`: \| `"object"` \| `"table"` \| `"bar"` \| `"line"` \| `"pie"` \| `"scalar"` \| `"row"` \| `"area"` \| `"combo"` \| `"pivot"` \| `"smartscalar"` \| `"gauge"` \| `"progress"` \| `"funnel"` \| `"map"` \| `"scatter"` \| `"boxplot"` \| `"waterfall"` \| `"sankey"` \| `"list"`) => `void` | A callback function that triggers when a question is opened from a dashboard card or when the user changes the visualization type of a question. | +| `parameters?` | [`ParameterValues`](./api/ParameterValues) | Controlled parameter values, slug-keyed. On every render, this object replaces the dashboard's parameter values:
    - a parameter set to a value uses that value.
    - a parameter set to `null` is cleared, even if it has a default.
    - a parameter omitted from the object (or set to `undefined`) uses its default (or `null` if it has no default).

    Pair with [onParametersChange](./api/InteractiveDashboardProps#onparameterschange) to stay in sync with user edits.
    - Combining [parameters](./api/InteractiveDashboardProps#parameters) and [hiddenParameters](./api/InteractiveDashboardProps#hiddenparameters) to filter data on the frontend is a [security risk](/docs/master/embedding/sdk/authentication#security-warning-each-end-user-must-have-their-own-metabase-account).
    - Combining [parameters](./api/InteractiveDashboardProps#parameters) and [hiddenParameters](./api/InteractiveDashboardProps#hiddenparameters) to declutter the user interface is fine. | +| `plugins?` | [`MetabasePluginsConfig`](./api/MetabasePluginsConfig) | Additional mapper function to override or add drill-down menu. See the implementing custom actions section for more details. | +| `renderDrillThroughQuestion?` | () => [`ReactNode`](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/0b728411cd1dfb4bd26992bb35a73cf8edaa22e7/types/react/index.d.ts#L478) | A custom React component to render the question layout. Use namespaced InteractiveQuestion components to build the layout. | +| `style?` | [`CSSProperties`](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/0b728411cd1dfb4bd26992bb35a73cf8edaa22e7/types/react/index.d.ts#L2579) | A custom style object to be added to the root element. | +| `token?` | `string` \| `null` | - | +| `withCardTitle?` | `boolean` | Whether the dashboard cards should display a title. | +| `withDownloads?` | `boolean` | Whether to hide the download button. | +| `withSubscriptions?` | `boolean` | Whether to show the subscriptions button. | +| `withTitle?` | `boolean` | Whether the dashboard should display a title. | diff --git a/_docs/master/embedding/sdk/api/snippets/InteractiveQuestionProps.md b/_docs/master/embedding/sdk/api/snippets/InteractiveQuestionProps.md index a78e1d7774..4573a02c81 100644 --- a/_docs/master/embedding/sdk/api/snippets/InteractiveQuestionProps.md +++ b/_docs/master/embedding/sdk/api/snippets/InteractiveQuestionProps.md @@ -15,28 +15,34 @@ layout: new-docs -| Property | Type | Description | -| :---------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------- | -| `className?` | `string` | A custom class name to be added to the root element. | -| `dataPicker?` | [`EmbeddingDataPicker`](./api/EmbeddingDataPicker) | Controls the menu for selecting data sources in questions. You can opt for the full data picker by setting `dataPicker = "staged"`. | -| `entityTypes?` | [`EmbeddingEntityType`](./api/EmbeddingEntityType)[] | An array that specifies which entity types are available in the data picker | -| `height?` | `Height`\<`string` \| `number`\> | A number or string specifying a CSS size value that specifies the height of the component | -| `hiddenParameters?` | `string`[] | A list of parameters to hide. | -| `initialSqlParameters?` | [`SqlParameterValues`](./api/SqlParameterValues) | Initial values for the SQL parameters. | -| `isSaveEnabled?` | `boolean` | Whether to show the save button. | -| `onBeforeSave?` | (`question`: [`MetabaseQuestion`](./api/MetabaseQuestion) \| `undefined`, `context`: \{ `isNewQuestion`: `boolean`; \}) => [`Promise`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise)\<`void`\> | A callback function that triggers before saving. Only relevant when `isSaveEnabled = true` | -| `onNavigateBack?` | () => `void` | A callback function that triggers when a user clicks the back button. | -| `onRun?` | (`question`: [`MetabaseQuestion`](./api/MetabaseQuestion) \| `undefined`) => `void` | A callback function that triggers when a question is updated, including when a user clicks the `Visualize` button in the question editor | -| `onSave?` | (`question`: [`MetabaseQuestion`](./api/MetabaseQuestion), `context`: \{ `dashboardTabId?`: `number`; `isNewQuestion`: `boolean`; \}) => `void` | A callback function that triggers when a user saves the question. Only relevant when `isSaveEnabled = true` | -| `onVisualizationChange?` | (`display`: \| `"object"` \| `"table"` \| `"bar"` \| `"line"` \| `"pie"` \| `"scalar"` \| `"row"` \| `"area"` \| `"combo"` \| `"pivot"` \| `"smartscalar"` \| `"gauge"` \| `"progress"` \| `"funnel"` \| `"map"` \| `"scatter"` \| `"boxplot"` \| `"waterfall"` \| `"sankey"` \| `"list"`) => `void` | A callback function that triggers when the visualization type changes. | -| `plugins?` | [`MetabasePluginsConfig`](./api/MetabasePluginsConfig) | - | -| `questionId?` | [`SdkQuestionId`](./api/SdkQuestionId) \| `null` | - | -| `style?` | [`CSSProperties`](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/0b728411cd1dfb4bd26992bb35a73cf8edaa22e7/types/react/index.d.ts#L2579) | A custom style object to be added to the root element. | -| `targetCollection?` | [`SdkCollectionId`](./api/SdkCollectionId) | The collection to save the question to. This will hide the collection picker from the save modal. Only applicable to interactive questions. | -| `title?` | [`SdkQuestionTitleProps`](./api/SdkQuestionTitleProps) | Determines whether the question title is displayed, and allows a custom title to be displayed instead of the default question title. Shown by default. | -| `width?` | `Width`\<`string` \| `number`\> | A number or string specifying a CSS size value that specifies the width of the component | -| `withAlerts?` | `boolean` | Enables the ability to set up alerts on the question. | -| `withChartTypeSelector?` | `boolean` | Determines whether the chart type selector and corresponding settings button are shown. Only relevant when using the default layout. | -| `withDownloads?` | `boolean` | Enables the ability to download results in the question. | +| Property | Type | Description | +| :---------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `className?` | `string` | A custom class name to be added to the root element. | +| `dataPicker?` | [`EmbeddingDataPicker`](./api/EmbeddingDataPicker) | Controls the menu for selecting data sources in questions. You can opt for the full data picker by setting `dataPicker = "staged"`. | +| `entityTypes?` | [`EmbeddingEntityType`](./api/EmbeddingEntityType)[] | An array that specifies which entity types are available in the data picker | +| `height?` | `Height`\<`string` \| `number`\> | A number or string specifying a CSS size value that specifies the height of the component | +| `hiddenParameters?` | `string`[] | A list of parameters to hide. | +| `initialCollection?` | [`SdkCollectionId`](./api/SdkCollectionId) | The collection to preselect in the save modal's collection picker. Unlike `targetCollection`, the picker remains visible and the user can choose a different collection. Ignored when `targetCollection` is set. | +| `initialSqlParameters?` | [`SqlParameterValues`](./api/SqlParameterValues) | Initial values for SQL parameters, slug-keyed. Applied once on mount; user widget edits afterwards are not reflected back to the host.
    For each parameter:
    - set to a value: that value is applied.
    - set to `null`: strictly cleared, ignoring the parameter's default.
    - omitted (or set to `undefined`): falls back to the parameter's default (or `null` if it has no default). | +| `isSaveEnabled?` | `boolean` | Whether to show the save button. | +| `onBeforeSave?` | (`question`: [`MetabaseQuestion`](./api/MetabaseQuestion) \| `undefined`, `context`: \{ `isNewQuestion`: `boolean`; \}) => [`Promise`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise)\<`void`\> | A callback function that triggers before saving. Only relevant when `isSaveEnabled = true` | +| `onNavigateBack?` | () => `void` | A callback function that triggers when a user clicks the back button. | +| `onRun?` | (`question`: [`MetabaseQuestion`](./api/MetabaseQuestion) \| `undefined`) => `void` | A callback function that triggers when a question is updated, including when a user clicks the `Visualize` button in the question editor | +| `onSave?` | (`question`: [`MetabaseQuestion`](./api/MetabaseQuestion), `context`: \{ `dashboardTabId?`: `number`; `isNewQuestion`: `boolean`; \}) => `void` | A callback function that triggers when a user saves the question. Only relevant when `isSaveEnabled = true` | +| `onSqlParametersChange?` | (`payload`: [`SqlParameterChangePayload`](./api/SqlParameterChangePayload)) => `void` | Fires on SQL parameters change. The payload's `source` distinguishes the initial state on load (`'initial-state'`), user edits in the UI (`'manual-change'`), and auto-updates (`'auto-change'`). | +| `onVisualizationChange?` | (`display`: \| `"object"` \| `"table"` \| `"bar"` \| `"line"` \| `"pie"` \| `"scalar"` \| `"row"` \| `"area"` \| `"combo"` \| `"pivot"` \| `"smartscalar"` \| `"gauge"` \| `"progress"` \| `"funnel"` \| `"map"` \| `"scatter"` \| `"boxplot"` \| `"waterfall"` \| `"sankey"` \| `"list"`) => `void` | A callback function that triggers when the visualization type changes. | +| `plugins?` | [`MetabasePluginsConfig`](./api/MetabasePluginsConfig) | - | +| `query?` | `undefined` | - | +| `questionId?` | [`SdkQuestionId`](./api/SdkQuestionId) \| `null` | The ID of the question.
    This is either:
    - the numerical ID when accessing a question link, i.e. `http://localhost:3000/question/1-my-question` where the ID is `1`
    - the string ID found in the `entity_id` key of the question object when using the API directly or using the SDK Collection Browser to return data
    - `new` to show the notebook editor for creating new questions
    - `new-native` to show the SQL editor for creating new native questions | +| `sqlParameters?` | [`SqlParameterValues`](./api/SqlParameterValues) | Controlled SQL parameter values, slug-keyed. On every render, this object replaces the question's parameter values:
    - a parameter set to a value uses that value.
    - a parameter set to `null` is cleared, even if it has a default.
    - a parameter omitted from the object (or set to `undefined`) uses its default (or `null` if it has no default).

    Pair with `onSqlParametersChange` to stay in sync with user edits. | +| `style?` | [`CSSProperties`](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/0b728411cd1dfb4bd26992bb35a73cf8edaa22e7/types/react/index.d.ts#L2579) | A custom style object to be added to the root element. | +| `targetCollection?` | [`SdkCollectionId`](./api/SdkCollectionId) | The collection to save the question to. This will hide the collection picker from the save modal. Only applicable to interactive questions. | +| `title?` | [`SdkQuestionTitleProps`](./api/SdkQuestionTitleProps) | Determines whether the question title is displayed, and allows a custom title to be displayed instead of the default question title. Shown by default. | +| `token?` | `string` \| `null` | A valid JWT token for the guest embed. | +| `width?` | `Width`\<`string` \| `number`\> | A number or string specifying a CSS size value that specifies the width of the component | +| `withAlerts?` | `boolean` | Enables the ability to set up alerts on the question. | +| `withChartTypeSelector?` | `boolean` | Determines whether the chart type selector and corresponding settings button are shown. Only relevant when using the default layout. | +| `withDownloads?` | `boolean` | Enables the ability to download results in the question. | +| `withEditorButton?` | `boolean` | Determines whether the editor button is shown. Only relevant when using the default layout. | diff --git a/_docs/master/embedding/sdk/api/snippets/MetabaseColorKey.md b/_docs/master/embedding/sdk/api/snippets/MetabaseColorKey.md index 742f9e5658..65290bdcf5 100644 --- a/_docs/master/embedding/sdk/api/snippets/MetabaseColorKey.md +++ b/_docs/master/embedding/sdk/api/snippets/MetabaseColorKey.md @@ -55,9 +55,11 @@ type MetabaseColorKey = | "background-secondary-inverse" | "background-selected" | "background-success" + | "background-success-secondary" | "background-tertiary" | "background-tertiary-inverse" | "background-warning" + | "background-warning-secondary" | "border" | "border-brand" | "border-filter" diff --git a/_docs/master/embedding/sdk/api/snippets/MetabaseEmbeddingColorKeyV2.md b/_docs/master/embedding/sdk/api/snippets/MetabaseEmbeddingColorKeyV2.md index 3846ab3bd6..de3e019d7f 100644 --- a/_docs/master/embedding/sdk/api/snippets/MetabaseEmbeddingColorKeyV2.md +++ b/_docs/master/embedding/sdk/api/snippets/MetabaseEmbeddingColorKeyV2.md @@ -67,9 +67,11 @@ type MetabaseEmbeddingColorKeyV2 = Exclude< | "background-secondary-inverse" | "background-selected" | "background-success" + | "background-success-secondary" | "background-tertiary" | "background-tertiary-inverse" | "background-warning" + | "background-warning-secondary" | "border" | "border-brand" | "border-filter" diff --git a/_docs/master/embedding/sdk/api/snippets/MetabaseEmbeddingThemeV2.md b/_docs/master/embedding/sdk/api/snippets/MetabaseEmbeddingThemeV2.md index 4cf3ceef7b..b0d3cccb06 100644 --- a/_docs/master/embedding/sdk/api/snippets/MetabaseEmbeddingThemeV2.md +++ b/_docs/master/embedding/sdk/api/snippets/MetabaseEmbeddingThemeV2.md @@ -15,10 +15,10 @@ Version 2 theme configuration for embedded Metabase components. -| Property | Type | Description | -| :-------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------ | -| `chartColors?` | [`ChartColorV2`](./api/ChartColorV2)[] | Chart colors overrides. Each color can be a string or an object with base/tint/shade. | -| `colors?` | [`Partial`](https://www.typescriptlang.org/docs/handbook/utility-types.html#partialtype)\<[`Record`](https://www.typescriptlang.org/docs/handbook/utility-types.html#recordkeys-type)\< \| `"filter"` \| `"info"` \| `"warning"` \| `"success"` \| `"error"` \| `"shadow"` \| `"accent0-light"` \| `"accent0-dark"` \| `"accent1-light"` \| `"accent1-dark"` \| `"accent2-light"` \| `"accent2-dark"` \| `"accent3-light"` \| `"accent3-dark"` \| `"accent4-light"` \| `"accent4-dark"` \| `"accent5-light"` \| `"accent5-dark"` \| `"accent6-light"` \| `"accent6-dark"` \| `"accent7-light"` \| `"accent7-dark"` \| `"accent-gray"` \| `"accent-gray-light"` \| `"accent-gray-dark"` \| `"background-brand"` \| `"background-filter"` \| `"background-disabled"` \| `"background-disabled-inverse"` \| `"background-error"` \| `"background-error-secondary"` \| `"background-highlight"` \| `"background-hover"` \| `"background-info"` \| `"background-primary"` \| `"background-primary-inverse"` \| `"background-secondary"` \| `"background-secondary-inverse"` \| `"background-selected"` \| `"background-success"` \| `"background-tertiary"` \| `"background-tertiary-inverse"` \| `"background-warning"` \| `"border"` \| `"border-brand"` \| `"border-filter"` \| `"border-strong"` \| `"border-stronger"` \| `"border-subtle"` \| `"brand"` \| `"brand-hover"` \| `"bronze"` \| `"copper"` \| `"danger"` \| `"focus"` \| `"gold"` \| `"icon-brand"` \| `"icon-disabled"` \| `"icon-primary"` \| `"icon-secondary"` \| `"illustration-brand-secondary"` \| `"illustration-brand-tertiary"` \| `"overlay"` \| `"saturated-blue"` \| `"saturated-green"` \| `"saturated-purple"` \| `"saturated-red"` \| `"saturated-yellow"` \| `"silver"` \| `"success-secondary"` \| `"summarize"` \| `"switch-off"` \| `"syntax-parameters"` \| `"syntax-parameters-active"` \| `"text-brand"` \| `"text-filter"` \| `"text-hover"` \| `"text-primary"` \| `"text-primary-inverse"` \| `"text-secondary"` \| `"text-secondary-inverse"` \| `"text-secondary-opaque"` \| `"text-selected"` \| `"text-tertiary"` \| `"text-tertiary-inverse"` \| `"tooltip-background"` \| `"tooltip-background-focused"` \| `"tooltip-text"` \| `"tooltip-text-secondary"` \| `"white"`, `string`\>\> | Color overrides. | -| `version` | `2` | Theme version must be 2 for version 2 themes. | +| Property | Type | Description | +| :-------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------ | +| `chartColors?` | [`ChartColorV2`](./api/ChartColorV2)[] | Chart colors overrides. Each color can be a string or an object with base/tint/shade. | +| `colors?` | [`Partial`](https://www.typescriptlang.org/docs/handbook/utility-types.html#partialtype)\<[`Record`](https://www.typescriptlang.org/docs/handbook/utility-types.html#recordkeys-type)\< \| `"filter"` \| `"info"` \| `"warning"` \| `"success"` \| `"error"` \| `"shadow"` \| `"accent0-light"` \| `"accent0-dark"` \| `"accent1-light"` \| `"accent1-dark"` \| `"accent2-light"` \| `"accent2-dark"` \| `"accent3-light"` \| `"accent3-dark"` \| `"accent4-light"` \| `"accent4-dark"` \| `"accent5-light"` \| `"accent5-dark"` \| `"accent6-light"` \| `"accent6-dark"` \| `"accent7-light"` \| `"accent7-dark"` \| `"accent-gray"` \| `"accent-gray-light"` \| `"accent-gray-dark"` \| `"background-brand"` \| `"background-filter"` \| `"background-disabled"` \| `"background-disabled-inverse"` \| `"background-error"` \| `"background-error-secondary"` \| `"background-highlight"` \| `"background-hover"` \| `"background-info"` \| `"background-primary"` \| `"background-primary-inverse"` \| `"background-secondary"` \| `"background-secondary-inverse"` \| `"background-selected"` \| `"background-success"` \| `"background-success-secondary"` \| `"background-tertiary"` \| `"background-tertiary-inverse"` \| `"background-warning"` \| `"background-warning-secondary"` \| `"border"` \| `"border-brand"` \| `"border-filter"` \| `"border-strong"` \| `"border-stronger"` \| `"border-subtle"` \| `"brand"` \| `"brand-hover"` \| `"bronze"` \| `"copper"` \| `"danger"` \| `"focus"` \| `"gold"` \| `"icon-brand"` \| `"icon-disabled"` \| `"icon-primary"` \| `"icon-secondary"` \| `"illustration-brand-secondary"` \| `"illustration-brand-tertiary"` \| `"overlay"` \| `"saturated-blue"` \| `"saturated-green"` \| `"saturated-purple"` \| `"saturated-red"` \| `"saturated-yellow"` \| `"silver"` \| `"success-secondary"` \| `"summarize"` \| `"switch-off"` \| `"syntax-parameters"` \| `"syntax-parameters-active"` \| `"text-brand"` \| `"text-filter"` \| `"text-hover"` \| `"text-primary"` \| `"text-primary-inverse"` \| `"text-secondary"` \| `"text-secondary-inverse"` \| `"text-secondary-opaque"` \| `"text-selected"` \| `"text-tertiary"` \| `"text-tertiary-inverse"` \| `"tooltip-background"` \| `"tooltip-background-focused"` \| `"tooltip-text"` \| `"tooltip-text-secondary"` \| `"white"`, `string`\>\> | Color overrides. | +| `version` | `2` | Theme version must be 2 for version 2 themes. | diff --git a/_docs/master/embedding/sdk/api/snippets/MetabaseFontFamily.md b/_docs/master/embedding/sdk/api/snippets/MetabaseFontFamily.md index e7498aee8d..472e992d78 100644 --- a/_docs/master/embedding/sdk/api/snippets/MetabaseFontFamily.md +++ b/_docs/master/embedding/sdk/api/snippets/MetabaseFontFamily.md @@ -15,6 +15,7 @@ type MetabaseFontFamily = | "Merriweather" | "Open Sans" | "Lato" + | "Inter" | "Noto Sans" | "Roboto Slab" | "Source Sans Pro" diff --git a/_docs/master/embedding/sdk/api/snippets/MetabotAgentChartMessage.md b/_docs/master/embedding/sdk/api/snippets/MetabotAgentChartMessage.md new file mode 100644 index 0000000000..049237edd3 --- /dev/null +++ b/_docs/master/embedding/sdk/api/snippets/MetabotAgentChartMessage.md @@ -0,0 +1,34 @@ +--- +version: master +has_magic_breadcrumbs: true +show_category_breadcrumb: true +show_title_breadcrumb: true +category: Embedding +title: MetabotAgentChartMessage +source_url: 'https://github.com/metabase/metabase/blob/master/docs/embedding/sdk/api/snippets/MetabotAgentChartMessage.md' +layout: new-docs +--- + +```ts +type MetabotAgentChartMessage = { + Chart: React_2.ComponentType; + id: string; + questionPath: string; + role: "agent"; + type: "chart"; +}; +``` + +## Properties + + + +| Property | Type | Description | +| :--------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------- | +| `Chart` | [`React_2.ComponentType`](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/0b728411cd1dfb4bd26992bb35a73cf8edaa22e7/types/react/index.d.ts#L104)\<[`MetabotChartProps`](./api/MetabotChartProps)\> | A pre-wired React component that renders the chart. | +| `id` | `string` | - | +| `questionPath` | `string` | URL path to the question, e.g. `/question#` | +| `role` | `"agent"` | - | +| `type` | `"chart"` | - | + + diff --git a/_docs/master/embedding/sdk/api/snippets/MetabotAgentMessage.md b/_docs/master/embedding/sdk/api/snippets/MetabotAgentMessage.md new file mode 100644 index 0000000000..3bb164f97e --- /dev/null +++ b/_docs/master/embedding/sdk/api/snippets/MetabotAgentMessage.md @@ -0,0 +1,14 @@ +--- +version: master +has_magic_breadcrumbs: true +show_category_breadcrumb: true +show_title_breadcrumb: true +category: Embedding +title: MetabotAgentMessage +source_url: 'https://github.com/metabase/metabase/blob/master/docs/embedding/sdk/api/snippets/MetabotAgentMessage.md' +layout: new-docs +--- + +```ts +type MetabotAgentMessage = MetabotAgentTextMessage | MetabotAgentChartMessage; +``` diff --git a/_docs/master/embedding/sdk/api/snippets/MetabotAgentTextMessage.md b/_docs/master/embedding/sdk/api/snippets/MetabotAgentTextMessage.md new file mode 100644 index 0000000000..3e9e2a340c --- /dev/null +++ b/_docs/master/embedding/sdk/api/snippets/MetabotAgentTextMessage.md @@ -0,0 +1,32 @@ +--- +version: master +has_magic_breadcrumbs: true +show_category_breadcrumb: true +show_title_breadcrumb: true +category: Embedding +title: MetabotAgentTextMessage +source_url: 'https://github.com/metabase/metabase/blob/master/docs/embedding/sdk/api/snippets/MetabotAgentTextMessage.md' +layout: new-docs +--- + +```ts +type MetabotAgentTextMessage = { + id: string; + message: string; + role: "agent"; + type: "text"; +}; +``` + +## Properties + + + +| Property | Type | +| :----------------------------- | :-------- | +| `id` | `string` | +| `message` | `string` | +| `role` | `"agent"` | +| `type` | `"text"` | + + diff --git a/_docs/master/embedding/sdk/api/snippets/MetabotChartProps.md b/_docs/master/embedding/sdk/api/snippets/MetabotChartProps.md new file mode 100644 index 0000000000..ba0ec0d28f --- /dev/null +++ b/_docs/master/embedding/sdk/api/snippets/MetabotChartProps.md @@ -0,0 +1,20 @@ +--- +version: master +has_magic_breadcrumbs: true +show_category_breadcrumb: true +show_title_breadcrumb: true +category: Embedding +title: MetabotChartProps +source_url: 'https://github.com/metabase/metabase/blob/master/docs/embedding/sdk/api/snippets/MetabotChartProps.md' +layout: new-docs +--- + +```ts +type MetabotChartProps = + | (Omit & { + drills?: false; + }) + | (Omit & { + drills: true; + }); +``` diff --git a/_docs/master/embedding/sdk/api/snippets/MetabotErrorMessage.md b/_docs/master/embedding/sdk/api/snippets/MetabotErrorMessage.md new file mode 100644 index 0000000000..57b8b91992 --- /dev/null +++ b/_docs/master/embedding/sdk/api/snippets/MetabotErrorMessage.md @@ -0,0 +1,28 @@ +--- +version: master +has_magic_breadcrumbs: true +show_category_breadcrumb: true +show_title_breadcrumb: true +category: Embedding +title: MetabotErrorMessage +source_url: 'https://github.com/metabase/metabase/blob/master/docs/embedding/sdk/api/snippets/MetabotErrorMessage.md' +layout: new-docs +--- + +```ts +type MetabotErrorMessage = { + message: string; + type: "message" | "alert" | "locked"; +}; +``` + +## Properties + + + +| Property | Type | Description | +| :----------------------------- | :------------------------------------- | :---------------------------------------------------------------------------------------- | +| `message` | `string` | - | +| `type` | `"message"` \| `"alert"` \| `"locked"` | `"alert"` renders with a warning icon and error color; `"message"` renders as plain text. | + + diff --git a/_docs/master/embedding/sdk/api/snippets/MetabotMessage.md b/_docs/master/embedding/sdk/api/snippets/MetabotMessage.md new file mode 100644 index 0000000000..47ca0728e4 --- /dev/null +++ b/_docs/master/embedding/sdk/api/snippets/MetabotMessage.md @@ -0,0 +1,14 @@ +--- +version: master +has_magic_breadcrumbs: true +show_category_breadcrumb: true +show_title_breadcrumb: true +category: Embedding +title: MetabotMessage +source_url: 'https://github.com/metabase/metabase/blob/master/docs/embedding/sdk/api/snippets/MetabotMessage.md' +layout: new-docs +--- + +```ts +type MetabotMessage = MetabotUserTextMessage | MetabotAgentMessage; +``` diff --git a/_docs/master/embedding/sdk/api/snippets/MetabotUserTextMessage.md b/_docs/master/embedding/sdk/api/snippets/MetabotUserTextMessage.md new file mode 100644 index 0000000000..75f8013426 --- /dev/null +++ b/_docs/master/embedding/sdk/api/snippets/MetabotUserTextMessage.md @@ -0,0 +1,32 @@ +--- +version: master +has_magic_breadcrumbs: true +show_category_breadcrumb: true +show_title_breadcrumb: true +category: Embedding +title: MetabotUserTextMessage +source_url: 'https://github.com/metabase/metabase/blob/master/docs/embedding/sdk/api/snippets/MetabotUserTextMessage.md' +layout: new-docs +--- + +```ts +type MetabotUserTextMessage = { + id: string; + message: string; + role: "user"; + type: "text"; +}; +``` + +## Properties + + + +| Property | Type | +| :----------------------------- | :------- | +| `id` | `string` | +| `message` | `string` | +| `role` | `"user"` | +| `type` | `"text"` | + + diff --git a/_docs/master/embedding/sdk/api/snippets/ParameterChangePayload.md b/_docs/master/embedding/sdk/api/snippets/ParameterChangePayload.md new file mode 100644 index 0000000000..5cb891fb7c --- /dev/null +++ b/_docs/master/embedding/sdk/api/snippets/ParameterChangePayload.md @@ -0,0 +1,34 @@ +--- +version: master +has_magic_breadcrumbs: true +show_category_breadcrumb: true +show_title_breadcrumb: true +category: Embedding +title: ParameterChangePayload +source_url: 'https://github.com/metabase/metabase/blob/master/docs/embedding/sdk/api/snippets/ParameterChangePayload.md' +layout: new-docs +--- + +```ts +type ParameterChangePayload = { + defaultParameters: ParameterValues; + lastUsedParameters: ParameterValues; + parameters: ParameterValues; + source: ParameterChangeSource; +}; +``` + +Payload passed to `onParametersChange` callback + +## Properties + + + +| Property | Type | +| :--------------------------------------------------- | :-------------------------------------------------------- | +| `defaultParameters` | [`ParameterValues`](./api/ParameterValues) | +| `lastUsedParameters` | [`ParameterValues`](./api/ParameterValues) | +| `parameters` | [`ParameterValues`](./api/ParameterValues) | +| `source` | [`ParameterChangeSource`](./api/ParameterChangeSource) | + + diff --git a/_docs/master/embedding/sdk/api/snippets/ParameterChangeSource.md b/_docs/master/embedding/sdk/api/snippets/ParameterChangeSource.md new file mode 100644 index 0000000000..9ea57095a4 --- /dev/null +++ b/_docs/master/embedding/sdk/api/snippets/ParameterChangeSource.md @@ -0,0 +1,20 @@ +--- +version: master +has_magic_breadcrumbs: true +show_category_breadcrumb: true +show_title_breadcrumb: true +category: Embedding +title: ParameterChangeSource +source_url: 'https://github.com/metabase/metabase/blob/master/docs/embedding/sdk/api/snippets/ParameterChangeSource.md' +layout: new-docs +--- + +```ts +type ParameterChangeSource = "initial-state" | "manual-change" | "auto-change"; +``` + +Source of a parameter-change event: + +- `initial-state` - first applied snapshot, fired once per dashboard load. +- `manual-change` - user edited parameters in UI. +- `auto-change` - in the case of auto-updates, e.g. to pass normalized values back to parent. diff --git a/_docs/master/embedding/sdk/api/snippets/SdkQuestionEntityPublicProps.md b/_docs/master/embedding/sdk/api/snippets/SdkQuestionEntityPublicProps.md index 403fcdb4bf..73c6d7d664 100644 --- a/_docs/master/embedding/sdk/api/snippets/SdkQuestionEntityPublicProps.md +++ b/_docs/master/embedding/sdk/api/snippets/SdkQuestionEntityPublicProps.md @@ -12,10 +12,12 @@ layout: new-docs ```ts type SdkQuestionEntityPublicProps = | { + query?: never; questionId: SdkQuestionId | null; token?: never; } | { + query?: never; questionId?: never; token: SdkEntityToken | null; }; @@ -27,6 +29,7 @@ type SdkQuestionEntityPublicProps = ```ts { + query?: never; questionId: SdkQuestionId | null; token?: never; } @@ -34,11 +37,13 @@ type SdkQuestionEntityPublicProps = | Name | Type | Description | | :----------- | :-------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `query?` | `never` | - | | `questionId` | [`SdkQuestionId`](./api/SdkQuestionId) \| `null` | The ID of the question.
    This is either:
    - the numerical ID when accessing a question link, i.e. `http://localhost:3000/question/1-my-question` where the ID is `1`
    - the string ID found in the `entity_id` key of the question object when using the API directly or using the SDK Collection Browser to return data
    - `new` to show the notebook editor for creating new questions
    - `new-native` to show the SQL editor for creating new native questions | | `token?` | `never` | - | ```ts { + query?: never; questionId?: never; token: SdkEntityToken | null; } @@ -46,6 +51,7 @@ type SdkQuestionEntityPublicProps = | Name | Type | Description | | :------------ | :---------------------------------------------------- | :------------------------------------- | +| `query?` | `never` | - | | `questionId?` | `never` | - | | `token` | [`SdkEntityToken`](./api/SdkEntityToken) \| `null` | A valid JWT token for the guest embed. | diff --git a/_docs/master/embedding/sdk/api/snippets/SdkQuestionProps.md b/_docs/master/embedding/sdk/api/snippets/SdkQuestionProps.md index 1c6782ea6f..3cad3dc0a3 100644 --- a/_docs/master/embedding/sdk/api/snippets/SdkQuestionProps.md +++ b/_docs/master/embedding/sdk/api/snippets/SdkQuestionProps.md @@ -15,29 +15,33 @@ layout: new-docs -| Property | Type | Description | -| :---------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------- | -| `className?` | `string` | A custom class name to be added to the root element. | -| `dataPicker?` | [`EmbeddingDataPicker`](./api/EmbeddingDataPicker) | Controls the menu for selecting data sources in questions. You can opt for the full data picker by setting `dataPicker = "staged"`. | -| `entityTypes?` | [`EmbeddingEntityType`](./api/EmbeddingEntityType)[] | An array that specifies which entity types are available in the data picker | -| `height?` | `Height`\<`string` \| `number`\> | A number or string specifying a CSS size value that specifies the height of the component | -| `hiddenParameters?` | `string`[] | A list of parameters to hide. | -| `initialSqlParameters?` | [`SqlParameterValues`](./api/SqlParameterValues) | Initial values for the SQL parameters. | -| `isSaveEnabled?` | `boolean` | Whether to show the save button. | -| `onBeforeSave?` | (`question`: [`MetabaseQuestion`](./api/MetabaseQuestion) \| `undefined`, `context`: \{ `isNewQuestion`: `boolean`; \}) => [`Promise`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise)\<`void`\> | A callback function that triggers before saving. Only relevant when `isSaveEnabled = true` | -| `onNavigateBack?` | () => `void` | A callback function that triggers when a user clicks the back button. | -| `onRun?` | (`question`: [`MetabaseQuestion`](./api/MetabaseQuestion) \| `undefined`) => `void` | A callback function that triggers when a question is updated, including when a user clicks the `Visualize` button in the question editor | -| `onSave?` | (`question`: [`MetabaseQuestion`](./api/MetabaseQuestion), `context`: \{ `dashboardTabId?`: `number`; `isNewQuestion`: `boolean`; \}) => `void` | A callback function that triggers when a user saves the question. Only relevant when `isSaveEnabled = true` | -| `onVisualizationChange?` | (`display`: \| `"object"` \| `"table"` \| `"bar"` \| `"line"` \| `"pie"` \| `"scalar"` \| `"row"` \| `"area"` \| `"combo"` \| `"pivot"` \| `"smartscalar"` \| `"gauge"` \| `"progress"` \| `"funnel"` \| `"map"` \| `"scatter"` \| `"boxplot"` \| `"waterfall"` \| `"sankey"` \| `"list"`) => `void` | A callback function that triggers when the visualization type changes. | -| `plugins?` | [`MetabasePluginsConfig`](./api/MetabasePluginsConfig) | - | -| `questionId?` | [`SdkQuestionId`](./api/SdkQuestionId) \| `null` | - | -| `style?` | [`CSSProperties`](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/0b728411cd1dfb4bd26992bb35a73cf8edaa22e7/types/react/index.d.ts#L2579) | A custom style object to be added to the root element. | -| `targetCollection?` | [`SdkCollectionId`](./api/SdkCollectionId) | The collection to save the question to. This will hide the collection picker from the save modal. Only applicable to interactive questions. | -| `title?` | [`SdkQuestionTitleProps`](./api/SdkQuestionTitleProps) | Determines whether the question title is displayed, and allows a custom title to be displayed instead of the default question title. Shown by default. | -| `token?` | `string` \| `null` | - | -| `width?` | `Width`\<`string` \| `number`\> | A number or string specifying a CSS size value that specifies the width of the component | -| `withAlerts?` | `boolean` | Enables the ability to set up alerts on the question. | -| `withChartTypeSelector?` | `boolean` | Determines whether the chart type selector and corresponding settings button are shown. Only relevant when using the default layout. | -| `withDownloads?` | `boolean` | Enables the ability to download results in the question. | +| Property | Type | Description | +| :---------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `className?` | `string` | A custom class name to be added to the root element. | +| `dataPicker?` | [`EmbeddingDataPicker`](./api/EmbeddingDataPicker) | Controls the menu for selecting data sources in questions. You can opt for the full data picker by setting `dataPicker = "staged"`. | +| `entityTypes?` | [`EmbeddingEntityType`](./api/EmbeddingEntityType)[] | An array that specifies which entity types are available in the data picker | +| `height?` | `Height`\<`string` \| `number`\> | A number or string specifying a CSS size value that specifies the height of the component | +| `hiddenParameters?` | `string`[] | A list of parameters to hide. | +| `initialCollection?` | [`SdkCollectionId`](./api/SdkCollectionId) | The collection to preselect in the save modal's collection picker. Unlike `targetCollection`, the picker remains visible and the user can choose a different collection. Ignored when `targetCollection` is set. | +| `initialSqlParameters?` | [`SqlParameterValues`](./api/SqlParameterValues) | Initial values for SQL parameters, slug-keyed. Applied once on mount; user widget edits afterwards are not reflected back to the host.
    For each parameter:
    - set to a value: that value is applied.
    - set to `null`: strictly cleared, ignoring the parameter's default.
    - omitted (or set to `undefined`): falls back to the parameter's default (or `null` if it has no default). | +| `isSaveEnabled?` | `boolean` | Whether to show the save button. | +| `onBeforeSave?` | (`question`: [`MetabaseQuestion`](./api/MetabaseQuestion) \| `undefined`, `context`: \{ `isNewQuestion`: `boolean`; \}) => [`Promise`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise)\<`void`\> | A callback function that triggers before saving. Only relevant when `isSaveEnabled = true` | +| `onNavigateBack?` | () => `void` | A callback function that triggers when a user clicks the back button. | +| `onRun?` | (`question`: [`MetabaseQuestion`](./api/MetabaseQuestion) \| `undefined`) => `void` | A callback function that triggers when a question is updated, including when a user clicks the `Visualize` button in the question editor | +| `onSave?` | (`question`: [`MetabaseQuestion`](./api/MetabaseQuestion), `context`: \{ `dashboardTabId?`: `number`; `isNewQuestion`: `boolean`; \}) => `void` | A callback function that triggers when a user saves the question. Only relevant when `isSaveEnabled = true` | +| `onSqlParametersChange?` | (`payload`: [`SqlParameterChangePayload`](./api/SqlParameterChangePayload)) => `void` | Fires on SQL parameters change. The payload's `source` distinguishes the initial state on load (`'initial-state'`), user edits in the UI (`'manual-change'`), and auto-updates (`'auto-change'`). | +| `onVisualizationChange?` | (`display`: \| `"object"` \| `"table"` \| `"bar"` \| `"line"` \| `"pie"` \| `"scalar"` \| `"row"` \| `"area"` \| `"combo"` \| `"pivot"` \| `"smartscalar"` \| `"gauge"` \| `"progress"` \| `"funnel"` \| `"map"` \| `"scatter"` \| `"boxplot"` \| `"waterfall"` \| `"sankey"` \| `"list"`) => `void` | A callback function that triggers when the visualization type changes. | +| `plugins?` | [`MetabasePluginsConfig`](./api/MetabasePluginsConfig) | - | +| `questionId?` | [`SdkQuestionId`](./api/SdkQuestionId) \| `null` | - | +| `sqlParameters?` | [`SqlParameterValues`](./api/SqlParameterValues) | Controlled SQL parameter values, slug-keyed. On every render, this object replaces the question's parameter values:
    - a parameter set to a value uses that value.
    - a parameter set to `null` is cleared, even if it has a default.
    - a parameter omitted from the object (or set to `undefined`) uses its default (or `null` if it has no default).

    Pair with `onSqlParametersChange` to stay in sync with user edits. | +| `style?` | [`CSSProperties`](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/0b728411cd1dfb4bd26992bb35a73cf8edaa22e7/types/react/index.d.ts#L2579) | A custom style object to be added to the root element. | +| `targetCollection?` | [`SdkCollectionId`](./api/SdkCollectionId) | The collection to save the question to. This will hide the collection picker from the save modal. Only applicable to interactive questions. | +| `title?` | [`SdkQuestionTitleProps`](./api/SdkQuestionTitleProps) | Determines whether the question title is displayed, and allows a custom title to be displayed instead of the default question title. Shown by default. | +| `token?` | `string` \| `null` | - | +| `width?` | `Width`\<`string` \| `number`\> | A number or string specifying a CSS size value that specifies the width of the component | +| `withAlerts?` | `boolean` | Enables the ability to set up alerts on the question. | +| `withChartTypeSelector?` | `boolean` | Determines whether the chart type selector and corresponding settings button are shown. Only relevant when using the default layout. | +| `withDownloads?` | `boolean` | Enables the ability to download results in the question. | +| `withEditorButton?` | `boolean` | Determines whether the editor button is shown. Only relevant when using the default layout. | diff --git a/_docs/master/embedding/sdk/api/snippets/SqlParameterChangePayload.md b/_docs/master/embedding/sdk/api/snippets/SqlParameterChangePayload.md new file mode 100644 index 0000000000..f9dcc397e9 --- /dev/null +++ b/_docs/master/embedding/sdk/api/snippets/SqlParameterChangePayload.md @@ -0,0 +1,32 @@ +--- +version: master +has_magic_breadcrumbs: true +show_category_breadcrumb: true +show_title_breadcrumb: true +category: Embedding +title: SqlParameterChangePayload +source_url: 'https://github.com/metabase/metabase/blob/master/docs/embedding/sdk/api/snippets/SqlParameterChangePayload.md' +layout: new-docs +--- + +```ts +type SqlParameterChangePayload = { + defaultParameters: ParameterValues; + parameters: ParameterValues; + source: SqlParameterChangeSource; +}; +``` + +Payload passed to `onSqlParametersChange` callback + +## Properties + + + +| Property | Type | +| :------------------------------------------------- | :-------------------------------------------------------------- | +| `defaultParameters` | [`ParameterValues`](./api/ParameterValues) | +| `parameters` | [`ParameterValues`](./api/ParameterValues) | +| `source` | [`SqlParameterChangeSource`](./api/SqlParameterChangeSource) | + + diff --git a/_docs/master/embedding/sdk/api/snippets/SqlParameterChangeSource.md b/_docs/master/embedding/sdk/api/snippets/SqlParameterChangeSource.md new file mode 100644 index 0000000000..1beba32d29 --- /dev/null +++ b/_docs/master/embedding/sdk/api/snippets/SqlParameterChangeSource.md @@ -0,0 +1,23 @@ +--- +version: master +has_magic_breadcrumbs: true +show_category_breadcrumb: true +show_title_breadcrumb: true +category: Embedding +title: SqlParameterChangeSource +source_url: 'https://github.com/metabase/metabase/blob/master/docs/embedding/sdk/api/snippets/SqlParameterChangeSource.md' +layout: new-docs +--- + +```ts +type SqlParameterChangeSource = + | "initial-state" + | "manual-change" + | "auto-change"; +``` + +Source of a sql-parameter-change event: + +- `initial-state` - first applied state, fired once per question load. +- `manual-change` - user edited parameters in UI. +- `auto-change` - in the case of auto-updates, e.g. to pass normalized values back to parent. diff --git a/_docs/master/embedding/sdk/api/snippets/StaticDashboardProps.md b/_docs/master/embedding/sdk/api/snippets/StaticDashboardProps.md index 36a6c8ecbf..a601a2cf97 100644 --- a/_docs/master/embedding/sdk/api/snippets/StaticDashboardProps.md +++ b/_docs/master/embedding/sdk/api/snippets/StaticDashboardProps.md @@ -15,23 +15,25 @@ layout: new-docs -| Property | Type | Description | -| :---------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `autoRefreshInterval?` | `number` | The interval between auto refreshes on the dashboard, in seconds. | -| `className?` | `string` | A custom class name to be added to the root element. | -| `dashboardId?` | [`SdkDashboardId`](./api/SdkDashboardId) \| `null` | The ID of the dashboard.
    This is either:
    - the numerical ID when accessing a dashboard link, i.e. `http://localhost:3000/dashboard/1-my-dashboard` where the ID is `1`
    - the string ID found in the `entity_id` key of the dashboard object when using the API directly or using the SDK Collection Browser to return data | -| `dataPickerProps?` | [`Pick`](https://www.typescriptlang.org/docs/handbook/utility-types.html#picktype-keys)\<[`SdkQuestionProps`](./api/SdkQuestionProps), `"entityTypes"`\> | Additional props to pass to the query builder rendered by `InteractiveQuestion` when creating a new dashboard question. | -| `hiddenParameters?` | `string`[] | A list of [parameters to hide](/docs/master/embedding/public-links#appearance-parameters).
    - Combining [initialParameters](./api/InteractiveDashboardProps#initialparameters) and [hiddenParameters](./api/InteractiveDashboardProps#hiddenparameters) to filter data on the frontend is a [security risk](/docs/master/embedding/sdk/authentication#security-warning-each-end-user-must-have-their-own-metabase-account).
    - Combining [initialParameters](./api/InteractiveDashboardProps#initialparameters) and [hiddenParameters](./api/InteractiveDashboardProps#hiddenparameters) to declutter the user interface is fine. | -| `initialParameters?` | [`ParameterValues`](./api/ParameterValues) | Query parameters for the dashboard. For a single option, use a `string` value, and use a list of strings for multiple options.
    - Combining [initialParameters](./api/InteractiveDashboardProps#initialparameters) and [hiddenParameters](./api/InteractiveDashboardProps#hiddenparameters) to filter data on the frontend is a [security risk](/docs/master/embedding/sdk/authentication#security-warning-each-end-user-must-have-their-own-metabase-account).
    - Combining [initialParameters](./api/InteractiveDashboardProps#initialparameters) and [hiddenParameters](./api/InteractiveDashboardProps#hiddenparameters) to declutter the user interface is fine. | -| `onLoad?` | (`dashboard`: [`MetabaseDashboard`](./api/MetabaseDashboard) \| `null`) => `void` | Callback that is called when the dashboard is loaded. | -| `onLoadWithoutCards?` | (`dashboard`: [`MetabaseDashboard`](./api/MetabaseDashboard) \| `null`) => `void` | Callback that is called when the dashboard is loaded without cards. | -| `onVisualizationChange?` | (`visualization`: \| `"object"` \| `"table"` \| `"bar"` \| `"line"` \| `"pie"` \| `"scalar"` \| `"row"` \| `"area"` \| `"combo"` \| `"pivot"` \| `"smartscalar"` \| `"gauge"` \| `"progress"` \| `"funnel"` \| `"map"` \| `"scatter"` \| `"boxplot"` \| `"waterfall"` \| `"sankey"` \| `"list"`) => `void` | A callback function that triggers when a question is opened from a dashboard card or when the user changes the visualization type of a question. | -| `plugins?` | [`MetabasePluginsConfig`](./api/MetabasePluginsConfig) | Additional mapper function to override or add drill-down menu. See the implementing custom actions section for more details. | -| `style?` | [`CSSProperties`](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/0b728411cd1dfb4bd26992bb35a73cf8edaa22e7/types/react/index.d.ts#L2579) | A custom style object to be added to the root element. | -| `token?` | `string` \| `null` | A valid JWT token for the guest embed. | -| `withCardTitle?` | `boolean` | Whether the dashboard cards should display a title. | -| `withDownloads?` | `boolean` | Whether to hide the download button. | -| `withSubscriptions?` | `boolean` | Whether to show the subscriptions button. | -| `withTitle?` | `boolean` | Whether the dashboard should display a title. | +| Property | Type | Description | +| :---------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `autoRefreshInterval?` | `number` | The interval between auto refreshes on the dashboard, in seconds. | +| `className?` | `string` | A custom class name to be added to the root element. | +| `dashboardId?` | [`SdkDashboardId`](./api/SdkDashboardId) \| `null` | The ID of the dashboard.
    This is either:
    - the numerical ID when accessing a dashboard link, i.e. `http://localhost:3000/dashboard/1-my-dashboard` where the ID is `1`
    - the string ID found in the `entity_id` key of the dashboard object when using the API directly or using the SDK Collection Browser to return data | +| `dataPickerProps?` | [`Pick`](https://www.typescriptlang.org/docs/handbook/utility-types.html#picktype-keys)\<[`SdkQuestionProps`](./api/SdkQuestionProps), `"entityTypes"`\> | Additional props to pass to the query builder rendered by `InteractiveQuestion` when creating a new dashboard question. | +| `hiddenParameters?` | `string`[] | A list of [parameters to hide](/docs/master/embedding/public-links#appearance-parameters).
    - Combining [initialParameters](./api/InteractiveDashboardProps#initialparameters) and [hiddenParameters](./api/InteractiveDashboardProps#hiddenparameters) to filter data on the frontend is a [security risk](/docs/master/embedding/sdk/authentication#security-warning-each-end-user-must-have-their-own-metabase-account).
    - Combining [initialParameters](./api/InteractiveDashboardProps#initialparameters) and [hiddenParameters](./api/InteractiveDashboardProps#hiddenparameters) to declutter the user interface is fine. | +| `initialParameters?` | [`ParameterValues`](./api/ParameterValues) | Initial values for query parameters, slug-keyed. Applied once on mount; user widget edits afterwards are not reflected back to the host.
    For each parameter:
    - set to a value (string for a single option, array of strings for multiple): that value is applied.
    - set to `null`: strictly cleared, ignoring the parameter's default.
    - omitted (or set to `undefined`): falls back to the parameter's default (or `null` if it has no default).

    - Combining [initialParameters](./api/InteractiveDashboardProps#initialparameters) and [hiddenParameters](./api/InteractiveDashboardProps#hiddenparameters) to filter data on the frontend is a [security risk](/docs/master/embedding/sdk/authentication#security-warning-each-end-user-must-have-their-own-metabase-account).
    - Combining [initialParameters](./api/InteractiveDashboardProps#initialparameters) and [hiddenParameters](./api/InteractiveDashboardProps#hiddenparameters) to declutter the user interface is fine. | +| `onLoad?` | (`dashboard`: [`MetabaseDashboard`](./api/MetabaseDashboard) \| `null`) => `void` | Callback that is called when the dashboard is loaded. | +| `onLoadWithoutCards?` | (`dashboard`: [`MetabaseDashboard`](./api/MetabaseDashboard) \| `null`) => `void` | Callback that is called when the dashboard is loaded without cards. | +| `onParametersChange?` | (`payload`: [`ParameterChangePayload`](./api/ParameterChangePayload)) => `void` | Fires on parameters change. The payload's `source` distinguishes the initial state on load (`'initial-state'`), user edits in the UI (`'manual-change'`), and auto-updates (`'auto-change'`). | +| `onVisualizationChange?` | (`visualization`: \| `"object"` \| `"table"` \| `"bar"` \| `"line"` \| `"pie"` \| `"scalar"` \| `"row"` \| `"area"` \| `"combo"` \| `"pivot"` \| `"smartscalar"` \| `"gauge"` \| `"progress"` \| `"funnel"` \| `"map"` \| `"scatter"` \| `"boxplot"` \| `"waterfall"` \| `"sankey"` \| `"list"`) => `void` | A callback function that triggers when a question is opened from a dashboard card or when the user changes the visualization type of a question. | +| `parameters?` | [`ParameterValues`](./api/ParameterValues) | Controlled parameter values, slug-keyed. On every render, this object replaces the dashboard's parameter values:
    - a parameter set to a value uses that value.
    - a parameter set to `null` is cleared, even if it has a default.
    - a parameter omitted from the object (or set to `undefined`) uses its default (or `null` if it has no default).

    Pair with [onParametersChange](./api/InteractiveDashboardProps#onparameterschange) to stay in sync with user edits.
    - Combining [parameters](./api/InteractiveDashboardProps#parameters) and [hiddenParameters](./api/InteractiveDashboardProps#hiddenparameters) to filter data on the frontend is a [security risk](/docs/master/embedding/sdk/authentication#security-warning-each-end-user-must-have-their-own-metabase-account).
    - Combining [parameters](./api/InteractiveDashboardProps#parameters) and [hiddenParameters](./api/InteractiveDashboardProps#hiddenparameters) to declutter the user interface is fine. | +| `plugins?` | [`MetabasePluginsConfig`](./api/MetabasePluginsConfig) | Additional mapper function to override or add drill-down menu. See the implementing custom actions section for more details. | +| `style?` | [`CSSProperties`](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/0b728411cd1dfb4bd26992bb35a73cf8edaa22e7/types/react/index.d.ts#L2579) | A custom style object to be added to the root element. | +| `token?` | `string` \| `null` | A valid JWT token for the guest embed. | +| `withCardTitle?` | `boolean` | Whether the dashboard cards should display a title. | +| `withDownloads?` | `boolean` | Whether to hide the download button. | +| `withSubscriptions?` | `boolean` | Whether to show the subscriptions button. | +| `withTitle?` | `boolean` | Whether the dashboard should display a title. | diff --git a/_docs/master/embedding/sdk/api/snippets/StaticQuestionProps.md b/_docs/master/embedding/sdk/api/snippets/StaticQuestionProps.md index 6b9d0506ab..864cc1f7da 100644 --- a/_docs/master/embedding/sdk/api/snippets/StaticQuestionProps.md +++ b/_docs/master/embedding/sdk/api/snippets/StaticQuestionProps.md @@ -20,8 +20,11 @@ layout: new-docs | `className?` | `string` | A custom class name to be added to the root element. | | `height?` | `Height`\<`string` \| `number`\> | A number or string specifying a CSS size value that specifies the height of the component | | `hiddenParameters?` | `string`[] | A list of parameters to hide. | -| `initialSqlParameters?` | [`SqlParameterValues`](./api/SqlParameterValues) | Initial values for the SQL parameters. | +| `initialSqlParameters?` | [`SqlParameterValues`](./api/SqlParameterValues) | Initial values for SQL parameters, slug-keyed. Applied once on mount; user widget edits afterwards are not reflected back to the host.
    For each parameter:
    - set to a value: that value is applied.
    - set to `null`: strictly cleared, ignoring the parameter's default.
    - omitted (or set to `undefined`): falls back to the parameter's default (or `null` if it has no default). | +| `onSqlParametersChange?` | (`payload`: [`SqlParameterChangePayload`](./api/SqlParameterChangePayload)) => `void` | Fires on SQL parameters change. The payload's `source` distinguishes the initial state on load (`'initial-state'`), user edits in the UI (`'manual-change'`), and auto-updates (`'auto-change'`). | +| `query?` | `undefined` | - | | `questionId?` | [`SdkQuestionId`](./api/SdkQuestionId) \| `null` | The ID of the question.
    This is either:
    - the numerical ID when accessing a question link, i.e. `http://localhost:3000/question/1-my-question` where the ID is `1`
    - the string ID found in the `entity_id` key of the question object when using the API directly or using the SDK Collection Browser to return data
    - `new` to show the notebook editor for creating new questions
    - `new-native` to show the SQL editor for creating new native questions | +| `sqlParameters?` | [`SqlParameterValues`](./api/SqlParameterValues) | Controlled SQL parameter values, slug-keyed. On every render, this object replaces the question's parameter values:
    - a parameter set to a value uses that value.
    - a parameter set to `null` is cleared, even if it has a default.
    - a parameter omitted from the object (or set to `undefined`) uses its default (or `null` if it has no default).

    Pair with `onSqlParametersChange` to stay in sync with user edits. | | `style?` | [`CSSProperties`](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/0b728411cd1dfb4bd26992bb35a73cf8edaa22e7/types/react/index.d.ts#L2579) | A custom style object to be added to the root element. | | `title?` | [`SdkQuestionTitleProps`](./api/SdkQuestionTitleProps) | Determines whether the question title is displayed, and allows a custom title to be displayed instead of the default question title. Shown by default. | | `token?` | `string` \| `null` | A valid JWT token for the guest embed. | diff --git a/_docs/master/embedding/sdk/api/snippets/UseMetabotResult.md b/_docs/master/embedding/sdk/api/snippets/UseMetabotResult.md new file mode 100644 index 0000000000..4affe4d5bf --- /dev/null +++ b/_docs/master/embedding/sdk/api/snippets/UseMetabotResult.md @@ -0,0 +1,40 @@ +--- +version: master +has_magic_breadcrumbs: true +show_category_breadcrumb: true +show_title_breadcrumb: true +category: Embedding +title: UseMetabotResult +source_url: 'https://github.com/metabase/metabase/blob/master/docs/embedding/sdk/api/snippets/UseMetabotResult.md' +layout: new-docs +--- + +```ts +type UseMetabotResult = { + cancelRequest: () => void; + CurrentChart: React_2.ComponentType | null; + errorMessages: MetabotErrorMessage[]; + isProcessing: boolean; + messages: MetabotMessage[]; + resetConversation: () => void; + retryMessage: (messageId: string) => Promise; + submitMessage: (message: string) => Promise; +}; +``` + +## Properties + + + +| Property | Type | Description | +| :------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `cancelRequest` | () => `void` | Cancel the current in-flight request. | +| `CurrentChart` | \| [`React_2.ComponentType`](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/0b728411cd1dfb4bd26992bb35a73cf8edaa22e7/types/react/index.d.ts#L104)\<[`MetabotChartProps`](./api/MetabotChartProps)\> \| `null` | A pre-wired component bound to the latest `navigate_to` path. `null` until the agent sends a chart — lets consumers detect presence and render a placeholder or swap panel content only when set. **Example** `{CurrentChart ? : }` | +| `errorMessages` | [`MetabotErrorMessage`](./api/MetabotErrorMessage)[] | Errors are conversation-level, not attached to individual messages. | +| `isProcessing` | `boolean` | `true` from the moment a message is submitted until the response completes — including success, error, or cancellation. | +| `messages` | [`MetabotMessage`](./api/MetabotMessage)[] | All messages in the conversation. Chart messages include a `Chart` property. | +| `resetConversation` | () => `void` | Clear all messages and start fresh. | +| `retryMessage` | (`messageId`: `string`) => [`Promise`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise)\<`void`\> | Rewinds the conversation to the user message preceding `messageId` and re-submits that prompt. The agent message at `messageId` and anything after it is dropped. | +| `submitMessage` | (`message`: `string`) => [`Promise`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise)\<`void`\> | Submit a new message to the conversation. | + + diff --git a/_docs/master/embedding/sdk/api/snippets/index.md b/_docs/master/embedding/sdk/api/snippets/index.md index 8b8b6a6aab..1159116310 100644 --- a/_docs/master/embedding/sdk/api/snippets/index.md +++ b/_docs/master/embedding/sdk/api/snippets/index.md @@ -32,41 +32,45 @@ layout: new-docs ## Dashboard -| Name | Description | -| :-------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| [EditableDashboard](./api/EditableDashboard) | A dashboard component with the features available in the `InteractiveDashboard` component, as well as the ability to add and update questions, layout, and content within your dashboard. | -| [InteractiveDashboard](./api/InteractiveDashboard) | A dashboard component with drill downs, click behaviors, and the ability to view and click into questions. | -| [StaticDashboard](./api/StaticDashboard) | A lightweight dashboard component. | -| [EditableDashboardProps](./api/EditableDashboardProps) | - | -| [InteractiveDashboardProps](./api/InteractiveDashboardProps) | - | -| [StaticDashboardProps](./api/StaticDashboardProps) | - | +| Name | Description | +| :-------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [EditableDashboard](./api/EditableDashboard) | A dashboard component with the features available in the `InteractiveDashboard` component, as well as the ability to add and update questions, layout, and content within your dashboard. | +| [InteractiveDashboard](./api/InteractiveDashboard) | A dashboard component with drill downs, click behaviors, and the ability to view and click into questions. | +| [StaticDashboard](./api/StaticDashboard) | A lightweight dashboard component. | +| [EditableDashboardProps](./api/EditableDashboardProps) | - | +| [InteractiveDashboardProps](./api/InteractiveDashboardProps) | - | +| [StaticDashboardProps](./api/StaticDashboardProps) | - | +| [ParameterChangePayload](./api/ParameterChangePayload) | Payload passed to `onParametersChange` callback | +| [ParameterChangeSource](./api/ParameterChangeSource) | Source of a parameter-change event: - `initial-state` - first applied snapshot, fired once per dashboard load. - `manual-change` - user edited parameters in UI. - `auto-change` - in the case of auto-updates, e.g. to pass normalized values back to parent. | ## InteractiveQuestion -| Name | Description | -| :------------------------------------------------------------------------------------------------------------ | :------------------------------------------------ | -| [InteractiveQuestion](./api/InteractiveQuestion) | A component that renders an interactive question. | -| [DrillThroughQuestionProps](./api/DrillThroughQuestionProps) | Props for the drill-through question | -| [InteractiveQuestionChartTypeDropdownProps](./api/InteractiveQuestionChartTypeDropdownProps) | - | -| [InteractiveQuestionEditorButtonProps](./api/InteractiveQuestionEditorButtonProps) | - | -| [InteractiveQuestionEditorProps](./api/InteractiveQuestionEditorProps) | - | -| [InteractiveQuestionProps](./api/InteractiveQuestionProps) | - | -| [InteractiveQuestionQuestionSettingsDropdownProps](./api/InteractiveQuestionQuestionSettingsDropdownProps) | - | -| [InteractiveQuestionQuestionVisualizationProps](./api/InteractiveQuestionQuestionVisualizationProps) | - | -| [InteractiveQuestionResetButtonProps](./api/InteractiveQuestionResetButtonProps) | - | -| [InteractiveQuestionSaveQuestionFormProps](./api/InteractiveQuestionSaveQuestionFormProps) | - | -| [InteractiveQuestionTitleProps](./api/InteractiveQuestionTitleProps) | - | -| [SdkQuestionProps](./api/SdkQuestionProps) | - | -| [InteractiveQuestionBackButtonProps](./api/InteractiveQuestionBackButtonProps) | - | -| [InteractiveQuestionBreakoutDropdownProps](./api/InteractiveQuestionBreakoutDropdownProps) | - | -| [InteractiveQuestionChartTypeSelectorProps](./api/InteractiveQuestionChartTypeSelectorProps) | - | -| [InteractiveQuestionDownloadWidgetDropdownProps](./api/InteractiveQuestionDownloadWidgetDropdownProps) | - | -| [InteractiveQuestionDownloadWidgetProps](./api/InteractiveQuestionDownloadWidgetProps) | - | -| [InteractiveQuestionFilterDropdownProps](./api/InteractiveQuestionFilterDropdownProps) | - | -| [InteractiveQuestionFilterProps](./api/InteractiveQuestionFilterProps) | - | -| [InteractiveQuestionQuestionSettingsProps](./api/InteractiveQuestionQuestionSettingsProps) | - | -| [InteractiveQuestionSaveButtonProps](./api/InteractiveQuestionSaveButtonProps) | - | -| [InteractiveQuestionSummarizeDropdownProps](./api/InteractiveQuestionSummarizeDropdownProps) | - | +| Name | Description | +| :------------------------------------------------------------------------------------------------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [InteractiveQuestion](./api/InteractiveQuestion) | A component that renders an interactive question. | +| [DrillThroughQuestionProps](./api/DrillThroughQuestionProps) | Props for the drill-through question | +| [InteractiveQuestionChartTypeDropdownProps](./api/InteractiveQuestionChartTypeDropdownProps) | - | +| [InteractiveQuestionEditorButtonProps](./api/InteractiveQuestionEditorButtonProps) | - | +| [InteractiveQuestionEditorProps](./api/InteractiveQuestionEditorProps) | - | +| [InteractiveQuestionProps](./api/InteractiveQuestionProps) | - | +| [InteractiveQuestionQuestionSettingsDropdownProps](./api/InteractiveQuestionQuestionSettingsDropdownProps) | - | +| [InteractiveQuestionQuestionVisualizationProps](./api/InteractiveQuestionQuestionVisualizationProps) | - | +| [InteractiveQuestionResetButtonProps](./api/InteractiveQuestionResetButtonProps) | - | +| [InteractiveQuestionSaveQuestionFormProps](./api/InteractiveQuestionSaveQuestionFormProps) | - | +| [InteractiveQuestionTitleProps](./api/InteractiveQuestionTitleProps) | - | +| [SdkQuestionProps](./api/SdkQuestionProps) | - | +| [InteractiveQuestionBackButtonProps](./api/InteractiveQuestionBackButtonProps) | - | +| [InteractiveQuestionBreakoutDropdownProps](./api/InteractiveQuestionBreakoutDropdownProps) | - | +| [InteractiveQuestionChartTypeSelectorProps](./api/InteractiveQuestionChartTypeSelectorProps) | - | +| [InteractiveQuestionDownloadWidgetDropdownProps](./api/InteractiveQuestionDownloadWidgetDropdownProps) | - | +| [InteractiveQuestionDownloadWidgetProps](./api/InteractiveQuestionDownloadWidgetProps) | - | +| [InteractiveQuestionFilterDropdownProps](./api/InteractiveQuestionFilterDropdownProps) | - | +| [InteractiveQuestionFilterProps](./api/InteractiveQuestionFilterProps) | - | +| [InteractiveQuestionQuestionSettingsProps](./api/InteractiveQuestionQuestionSettingsProps) | - | +| [InteractiveQuestionSaveButtonProps](./api/InteractiveQuestionSaveButtonProps) | - | +| [InteractiveQuestionSummarizeDropdownProps](./api/InteractiveQuestionSummarizeDropdownProps) | - | +| [SqlParameterChangePayload](./api/SqlParameterChangePayload) | Payload passed to `onSqlParametersChange` callback | +| [SqlParameterChangeSource](./api/SqlParameterChangeSource) | Source of a sql-parameter-change event: - `initial-state` - first applied state, fired once per question load. - `manual-change` - user edited parameters in UI. - `auto-change` - in the case of auto-updates, e.g. to pass normalized values back to parent. | ## MetabaseProvider @@ -142,6 +146,10 @@ layout: new-docs | [MetabasePluginsConfig](./api/MetabasePluginsConfig) | - | | [MetabaseThemePreset](./api/MetabaseThemePreset) | - | | [MetabaseUser](./api/MetabaseUser) | The User entity | +| [MetabotAgentChartMessage](./api/MetabotAgentChartMessage) | - | +| [MetabotAgentMessage](./api/MetabotAgentMessage) | - | +| [MetabotAgentTextMessage](./api/MetabotAgentTextMessage) | - | +| [MetabotUserTextMessage](./api/MetabotUserTextMessage) | - | | [ParameterValues](./api/ParameterValues) | - | | [ProtectedColorKey](./api/ProtectedColorKey) | Color keys that are protected and should not be exposed to embedding. | | [SdkCollectionId](./api/SdkCollectionId) | - | @@ -190,3 +198,13 @@ layout: new-docs | Function | Description | | :------------------------------------------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------- | | [useMetabaseAuthStatus](./api/useMetabaseAuthStatus) | Returns the authentication status of the current user in the Metabase embedding SDK. Returns `null` until the SDK is fully loaded and initialized. | + +## useMetabot + +| Name | Description | +| :-------------------------------------------------- | :------------------------------------ | +| [useMetabot](./api/useMetabot) | Returns the Metabot conversation API. | +| [MetabotChartProps](./api/MetabotChartProps) | - | +| [MetabotErrorMessage](./api/MetabotErrorMessage) | - | +| [MetabotMessage](./api/MetabotMessage) | - | +| [UseMetabotResult](./api/UseMetabotResult) | - | diff --git a/_docs/master/embedding/sdk/api/snippets/useMetabot.md b/_docs/master/embedding/sdk/api/snippets/useMetabot.md new file mode 100644 index 0000000000..349ec2ae06 --- /dev/null +++ b/_docs/master/embedding/sdk/api/snippets/useMetabot.md @@ -0,0 +1,43 @@ +--- +version: master +has_magic_breadcrumbs: true +show_category_breadcrumb: true +show_title_breadcrumb: true +category: Embedding +title: useMetabot +source_url: 'https://github.com/metabase/metabase/blob/master/docs/embedding/sdk/api/snippets/useMetabot.md' +layout: new-docs +--- + +```ts +function useMetabot(): UseMetabotResult | null; +``` + +Returns the Metabot conversation API. + +Returns `null` until the SDK bundle has loaded and `` +has mounted its internal subscriber. Guard before use: + +## Returns + + + +[`UseMetabotResult`](./api/UseMetabotResult) \| `null` + + + +## Example + + + +```ts +const metabot = useMetabot(); +if (!metabot) { + return ; +} +metabot.submitMessage("Show me orders"); + +@function +``` + + diff --git a/_docs/master/embedding/sdk/api/useMetabot.html b/_docs/master/embedding/sdk/api/useMetabot.html new file mode 100644 index 0000000000..5dd7642c98 --- /dev/null +++ b/_docs/master/embedding/sdk/api/useMetabot.html @@ -0,0 +1,18 @@ +--- +version: master +has_magic_breadcrumbs: true +show_category_breadcrumb: true +show_title_breadcrumb: true +category: Embedding +title: useMetabot +source_url: 'https://github.com/metabase/metabase/blob/master/docs/embedding/sdk/api/useMetabot.html' +layout: docs-api +--- + +useMetabot | Embedded analytics SDK API{% include docs/embedded-analytics-sdk-metadata.html %}

    Function useMetabot

    • Returns the Metabot conversation API.

      +

      Returns null until the SDK bundle has loaded and <MetabaseProvider> +has mounted its internal subscriber. Guard before use:

      +

      Returns UseMetabotResult | null

      const metabot = useMetabot();
      if (!metabot) {
      return <Spinner />;
      }
      metabot.submitMessage("Show me orders");

      @function +
      + +

    diff --git a/_docs/master/embedding/sdk/config.md b/_docs/master/embedding/sdk/config.md index 377140e151..52d798d05a 100644 --- a/_docs/master/embedding/sdk/config.md +++ b/_docs/master/embedding/sdk/config.md @@ -22,6 +22,8 @@ To use the SDK in your app, you need to import the `MetabaseProvider` component A component that configures the SDK and provides the Metabase SDK's context and theme. +To pass a theme, use `defineMetabaseTheme`. See [Reuse a saved theme in the SDK](../appearance#reuse-a-saved-theme-in-the-sdk). + #### API Reference - [Component](./api/MetabaseProvider) diff --git a/_docs/master/embedding/sdk/dashboards.md b/_docs/master/embedding/sdk/dashboards.md index 7a478494d2..9fd480e4d1 100644 --- a/_docs/master/embedding/sdk/dashboards.md +++ b/_docs/master/embedding/sdk/dashboards.md @@ -67,6 +67,10 @@ A dashboard component with the features available in the `InteractiveDashboard` {% include_file "{{ dirname }}/snippets/dashboards/interactive-dashboard.tsx" %} ``` +## Pass parameter values to a dashboard + +See [Modular embedding parameters](../parameters#pass-parameter-values-to-a-dashboard). + ## Customizing dashboard height By default, dashboard components take full page height (100vh). You can override this with custom styles passed via `style` or `className` props. diff --git a/_docs/master/embedding/sdk/introduction.md b/_docs/master/embedding/sdk/introduction.md index c234c2d690..e9febbdba9 100644 --- a/_docs/master/embedding/sdk/introduction.md +++ b/_docs/master/embedding/sdk/introduction.md @@ -57,18 +57,22 @@ To use the SDK, you'll need to enable the SDK in Metabase, and install the SDK i ### Install the SDK in your React application -You can install the modular embedding SDK for React via npm. Make sure to use the dist-tag that corresponds to your Metabase version, example: 56-stable for Metabase 56: +Install the SDK Package matching your Metabase major with the `@{major}-stable` dist-tag, so the package's TypeScript types and exported components stay in sync with your instance's SDK Bundle: ```bash -npm install @metabase/embedding-sdk-react@56-stable +npm install @metabase/embedding-sdk-react@60-stable ``` or with Yarn: ```bash -yarn add @metabase/embedding-sdk-react@56-stable +yarn add @metabase/embedding-sdk-react@60-stable ``` +On **Metabase 56 or earlier**, the SDK major _must_ match your Metabase major. On **Metabase 57 and later**, you can also install without a dist-tag to track the latest published SDK major. + +See [SDK versions](./version) for more on compatibility. + ### Resolving `@types/react` version mismatches In rare scenarios, the modular embedding SDK and your application may use different major versions of `@types/react`, causing TypeScript conflicts. @@ -100,7 +104,7 @@ To enforce a single `@types/react` version across all dependencies, add an `over Starting with Metabase 57, the SDK consists of two parts: - **SDK Package** – The `@metabase/embedding-sdk-react` npm package is a lightweight bootstrapper library. Its primary purpose is to load and run the main SDK Bundle code. -- **SDK Bundle** – The full SDK code, served directly from your self-hosted Metabase instance or Metabase Cloud, and it's the part of the Metabase. This ensures that the main SDK code is always compatible with its corresponding Metabase instance. +- **SDK Bundle** – The full SDK code, served directly from your self-hosted Metabase instance or Metabase Cloud, and it's a part of Metabase. This ensures that the main SDK code is always compatible with its corresponding Metabase instance. ## Developing with the modular embedding SDK diff --git a/_docs/master/embedding/sdk/questions.md b/_docs/master/embedding/sdk/questions.md index 4b5659b286..a12522840a 100644 --- a/_docs/master/embedding/sdk/questions.md +++ b/_docs/master/embedding/sdk/questions.md @@ -67,15 +67,9 @@ Use this component when you want to allow people to explore their data and custo {% include_file "{{ dirname }}/api/snippets/InteractiveQuestionProps.md" snippet="properties" %} -## Pass SQL parameters to SQL questions with `initialSqlParameters` +## Pass parameters to SQL questions -You can pass parameter values to questions defined with SQL via the `initialSqlParameters` prop, in the format of `{parameter_name: parameter_value}`. Learn more about [SQL parameters](../../questions/native-editor/sql-parameters). - -```typescript -{% include_file "{{ dirname }}/snippets/questions/initial-sql-parameters.tsx" snippet="example" %} -``` - -`initialSqlParameters` can't be used with questions built using the query builder. +See [Modular embedding parameters](../parameters#pass-parameters-to-sql-questions). ## Enable alerts on embedded questions diff --git a/_docs/master/embedding/sdk/quickstart-with-sample-app.md b/_docs/master/embedding/sdk/quickstart-with-sample-app.md index 035bd52a76..d69f54ca65 100644 --- a/_docs/master/embedding/sdk/quickstart-with-sample-app.md +++ b/_docs/master/embedding/sdk/quickstart-with-sample-app.md @@ -36,7 +36,7 @@ git clone git@github.com:metabase/metabase-nodejs-react-sdk-embedding-sample.git 2. Check out the branch in the [metabase-nodejs-react-sdk-embedding-sample](https://github.com/metabase/metabase-nodejs-react-sdk-embedding-sample/tree/{{page.version | remove: "v0."}}-stable) repo that corresponds to your Metabase version. ```bash -git checkout {{page.version}}-stable +git checkout {{page.version | remove: "v0."}}-stable ``` E.g., if you're running Metabase 1.57 make sure the sample app repo is on the `57-stable` branch. You can find your Metabase version in the Metabase UI by clicking the **grid icon** in the upper right, selecting **Help**, then choosing **About Metabase**. diff --git a/_docs/master/embedding/sdk/quickstart.md b/_docs/master/embedding/sdk/quickstart.md index 763b417b01..5b37142ea5 100644 --- a/_docs/master/embedding/sdk/quickstart.md +++ b/_docs/master/embedding/sdk/quickstart.md @@ -54,20 +54,22 @@ Still in the Admin console, go to **Settings > Authentication** and click on the ## 3. Install the SDK in your app -When installing the npm package, it's critical to use the npm dist-tag that corresponds to the major version of your Metabase. For example, if your Metabase is version 1.56.x, you'd run `56-stable`. See [SDK versioning](./version). +Install the `@{major}-stable` dist-tag matching your Metabase major, so the package's types and exported components in your client match your SDK bundle served from your Metabase. For Metabase 60: Via npm: ``` -npm install @metabase/embedding-sdk-react@53-stable +npm install @metabase/embedding-sdk-react@60-stable ``` Via Yarn: ``` -yarn add @metabase/embedding-sdk-react@53-stable +yarn add @metabase/embedding-sdk-react@60-stable ``` +See [SDK versions](./version) for other install options. + ## 4. Embed SDK components in your app In your app, import the SDK components, like so: diff --git a/_docs/master/embedding/sdk/snippets/questions/use-metabot-dedicated-chart.tsx b/_docs/master/embedding/sdk/snippets/questions/use-metabot-dedicated-chart.tsx new file mode 100644 index 0000000000..843d5dd8a9 --- /dev/null +++ b/_docs/master/embedding/sdk/snippets/questions/use-metabot-dedicated-chart.tsx @@ -0,0 +1,113 @@ +import React, { useState } from "react"; +import { + MetabaseProvider, + defineMetabaseAuthConfig, + useMetabot, +} from "@metabase/embedding-sdk-react"; + +const authConfig = defineMetabaseAuthConfig({ + metabaseInstanceUrl: "https://your-metabase.example.com", +}); + +function MetabotChat() { + const metabot = useMetabot(); + const [prompt, setPrompt] = useState(""); + + // useMetabot returns null until the SDK bundle has loaded + // and has mounted. Always guard before use. + if (!metabot) { + return
    Loading…
    ; + } + + const handleSubmit = (event: React.FormEvent) => { + event.preventDefault(); + if (!prompt.trim()) { + return; + } + metabot.submitMessage(prompt); + setPrompt(""); + }; + + const { CurrentChart } = metabot; + + return ( +
    +
    + {CurrentChart ? ( + + ) : ( +
    + Ask Metabot to generate a chart +
    + )} +
    + +
    +
    + {metabot.messages.map((message) => { + // Chart messages render in the dedicated panel on the left, + // so you should filter them out in the chat transcript + // so they don't render twice. + if (message.role === "agent" && message.type === "chart") { + return null; + } + // Agent text (message.role === "agent") is markdown: links, + // bold, lists, code, etc. Wrap in a markdown renderer (react-markdown, + // markdown-to-jsx, etc.). Rendered as plain + // text here for brevity. User text (message.role === "user") is + // raw, so no markdown rendering needed. + return ( +
    + {message.message} +
    + ); + })} +
    + +
    + setPrompt(event.target.value)} + placeholder="Ask Metabot…" + disabled={metabot.isProcessing} + style={{ flex: 1 }} + /> + + +
    +
    + ); +} + +export default function App() { + return ( + + + + ); +} diff --git a/_docs/master/embedding/sdk/snippets/questions/use-metabot-inline-charts.tsx b/_docs/master/embedding/sdk/snippets/questions/use-metabot-inline-charts.tsx new file mode 100644 index 0000000000..daafb0dc23 --- /dev/null +++ b/_docs/master/embedding/sdk/snippets/questions/use-metabot-inline-charts.tsx @@ -0,0 +1,80 @@ +import React, { useState } from "react"; +import { + MetabaseProvider, + defineMetabaseAuthConfig, + useMetabot, +} from "@metabase/embedding-sdk-react"; + +const authConfig = defineMetabaseAuthConfig({ + metabaseInstanceUrl: "https://your-metabase.example.com", +}); + +function MetabotChat() { + const metabot = useMetabot(); + const [prompt, setPrompt] = useState(""); + + // useMetabot returns null until the SDK bundle has loaded + // and has mounted. Always guard before use. + if (!metabot) { + return
    Loading…
    ; + } + + const handleSubmit = (event: React.FormEvent) => { + event.preventDefault(); + if (!prompt.trim()) { + return; + } + metabot.submitMessage(prompt); + setPrompt(""); + }; + + return ( +
    +
    + {metabot.messages.map((message) => { + if (message.role === "user") { + return ( +
    + {message.message} +
    + ); + } + if (message.type === "text") { + // message.message is markdown: links, bold, lists, code. + // Wrap in a markdown renderer (react-markdown, markdown-to-jsx, + // etc.) for production use; rendered as plain text here for brevity. + return
    {message.message}
    ; + } + // Agent chart message — render its bound Chart inline. + const { Chart } = message; + return ( +
    + +
    + ); + })} +
    + +
    + setPrompt(event.target.value)} + placeholder="Ask Metabot…" + disabled={metabot.isProcessing} + style={{ flex: 1 }} + /> + + +
    + ); +} + +export default function App() { + return ( + + + + ); +} diff --git a/_docs/master/embedding/sdk/upgrade.md b/_docs/master/embedding/sdk/upgrade.md index 4c740114d1..70f547ef6b 100644 --- a/_docs/master/embedding/sdk/upgrade.md +++ b/_docs/master/embedding/sdk/upgrade.md @@ -26,8 +26,6 @@ Check for any relevant changes, especially deprecations or breaking changes that ## 2. Test the upgrade -When upgrading to a new major version, you'll want to upgrade both Metabase and the SDK version in parallel, as having Metabase and the SDK major versions out of sync can cause errors. - ### Spin up the new version of Metabase for testing You can do this locally or in a dev instance. If your testing setup involves a lot of test user accounts, getting a [development instance](../../installation-and-operation/development-instance) could be more cost-effective. @@ -38,31 +36,25 @@ See [upgrading Metabase](../../installation-and-operation/upgrading-metabase). You'll want to test the changes locally first, as there may be breaking changes that require you to upgrade your application code. -Check out a new branch in your application and install the next stable version, either with npm or Yarn: - -Via npm: +Check out a new branch in your application and install the SDK that matches your Metabase major version. For Metabase 60.x: ```bash -npm install @metabase/embedding-sdk-react@{next-major-version-number}-stable +npm install @metabase/embedding-sdk-react@60-stable ``` -For example, if you were upgrading to version 56 of the SDK: +or with Yarn: ```bash -npm install @metabase/embedding-sdk-react@56-stable +yarn add @metabase/embedding-sdk-react@60-stable ``` -If you're using Yarn: - -```bash -yarn add @metabase/embedding-sdk-react@{next-major-version-number}-stable -``` +To track the latest published SDK major instead, install without a dist-tag (`npm install @metabase/embedding-sdk-react`). See more on [SDK versions](./version). ### If there are deprecations or breaking changes, make the necessary changes to your application code -Deprecations or breaking changes are rare, but if you do need to make changes, we'll mention it in the release notes for the new major version and have docs that walk you through the changes. +Deprecations or breaking changes are rare, but if you do need to make changes to your application code, we'll mention it in the [release notes](/releases) for the new major version and have docs that walk you through the changes. Update or add tests for any application code changes that you make. @@ -79,8 +71,6 @@ If all goes well with your local tests, deploy to your staging environment. Chec If everything is working in staging, you're ready to deploy to production. -Be sure to deploy your application changes and upgrade your Metabase in parallel so that the SDK version and the Metabase version stay in sync. - ### Caching may delay the upgrade by up to a minute This is intentional. After upgrading, Metabase may still serve the previous, cached version of the SDK Bundle for up to 60 seconds (`Cache-Control: public, max-age=60`). This short cache window helps ensure fast performance while still allowing updates to propagate quickly. diff --git a/_docs/master/embedding/sdk/version.md b/_docs/master/embedding/sdk/version.md index 1aeaf93e72..f2ccd380dc 100644 --- a/_docs/master/embedding/sdk/version.md +++ b/_docs/master/embedding/sdk/version.md @@ -14,17 +14,27 @@ summary: 'Learn about Modular embedding SDK versioning and compatibility with Me {% include plans-blockquote.html feature="Modular embedding SDK" sdk=true %} -The SDK stable version tracks with the Metabase version. +## Metabase 57 and later -So, for example, if you're on Metabase 56 (`0.56.x`, `1.56.x`), _any_ version 0.56.x of the @metabase/embedding-sdk-react npm package will be compatible. +Starting with Metabase 57, the `@metabase/embedding-sdk-react` npm package loads the SDK Bundle from your Metabase. -To simplify things, we publish dist-tags for each stable Metabase version. For example, to install the latest version of the SDK compatible with Metabase 56, run: +Install the SDK Package matching your Metabase major with the `@{major}-stable` dist-tag, so the package's TypeScript types and exported components stay in sync with your instance's SDK Bundle: ```sh -npm install @metabase/embedding-sdk-react@56-stable +npm install @metabase/embedding-sdk-react@60-stable ``` -To grab the latest version of the SDK that works with Metabase nightly builds, use the `canary` dist-tag. +Installing without a dist-tag (`npm install @metabase/embedding-sdk-react`) still works. The bundle loads from your Metabase, but the package's types and exports will track the latest published SDK major, which may drift from your Metabase version. + +## Metabase 56 and earlier + +For Metabase 56 and earlier, the SDK major version must match the Metabase major version. Use the matching `@{major}-stable` dist-tag. For example, for Metabase 55: + +```sh +npm install @metabase/embedding-sdk-react@55-stable +``` + +On Metabase 55 (`0.55.x`, `1.55.x`), _any_ 0.55.x release of `@metabase/embedding-sdk-react` will be compatible. ## Minimum SDK version @@ -32,7 +42,9 @@ Version 52 is the minimum version supported for the Modular embedding SDK. ## You can pin instances to a version on Metabase Cloud -Metabase Cloud upgrades your instance automatically as new versions roll out. But if you're using the SDK with Metabase Cloud, you may want to pin your version so you can upgrade manually. This way you can make sure that your embeds don't break when you upgrade both your Metabase and your SDK version. +Metabase Cloud upgrades your instance automatically as new versions roll out. If you're using the SDK with Metabase Cloud, you may want to pin your version so you can upgrade manually. + +On Metabase 56 or earlier, pinning also keeps the SDK Package and Metabase majors in lockstep. ### Manually pinning your instance version on Metabase Cloud diff --git a/_docs/master/embedding/securing-embeds.md b/_docs/master/embedding/securing-embeds.md index d8e03d3847..748312d08f 100644 --- a/_docs/master/embedding/securing-embeds.md +++ b/_docs/master/embedding/securing-embeds.md @@ -74,10 +74,12 @@ Guest embedding uses a [JWT authorization flow](#guest-embedding-with-jwt-author ### Guest embeds don't have user sessions -Guest embeds don't authenticate people's identities on the Metabase side, so people can view a guest embed without creating a Metabase account. However, without a Metabase account, Metabase won't have a way to remember a user or their session, which means: +Guest embeds don't authenticate people's identities on the Metabase side, so people can view a guest embed without creating a Metabase account. + +Without a Metabase account, however, Metabase won't have a way to remember a user or their session, which means: - Metabase [permissions](../permissions/introduction) and [row and column security](../permissions/row-and-column-security) won't work --- if you need to lock down sensitive data, you must set up [locked parameters](#example-securing-data-with-locked-parameters-on-a-guest-embed) for _each_ of your guest embeds. -- Any filter selections in a guest embed will reset once the signed JWT expires. +- Any filter selections in a guest embed will reset once the signed JWT expires, _unless_ you configure [JWT refresh](./guest-embedding#refreshing-or-initializing-the-jwt-from-your-server) so the embed swaps in a fresh token without reloading. - All guest embed usage will show up in [usage analytics](../usage-and-performance-tools/usage-analytics) under "External user". ## Security in guest embedding vs. modular and full app embedding @@ -98,6 +100,7 @@ This diagram illustrates how an embed gets secured by a signed JWT: 2. **Signed request**: your backend generates a Metabase embedding URL with a [signed JWT](./guest-embedding#how-guest-embedding-works). The signed JWT should encode any query [parameters](./static-embedding-parameters) you're using to filter your data. 3. **Response**: your Metabase backend returns data based on the query parameters encoded in the signed JWT. 4. **Success**: your frontend displays the embedded Metabase page with the correct data. +5. **(Optional) Refresh / Initialize**: if you've configured a [`guestEmbedProviderUri`](./guest-embedding#refreshing-or-initializing-the-jwt-from-your-server), the embed will call that endpoint you've set up for a fresh token the next time the embed needs to make a data request after the current token has expired (like when someone changes the filter value). The embed won't automatically fetch a new token. The endpoint can also serve the first token on load, so you can use the endpoint to revoke access by refusing to issue a new token. ### Example: securing data with locked parameters on a guest embed diff --git a/_docs/master/embedding/snippets/parameters/dashboards/controlled-parameters.tsx b/_docs/master/embedding/snippets/parameters/dashboards/controlled-parameters.tsx new file mode 100644 index 0000000000..3f65498c41 --- /dev/null +++ b/_docs/master/embedding/snippets/parameters/dashboards/controlled-parameters.tsx @@ -0,0 +1,52 @@ +import { + InteractiveDashboard, + type ParameterChangePayload, + type ParameterValues, +} from "@metabase/embedding-sdk-react"; +import { useState } from "react"; + +const dashboardId = 1; + +const ExampleControlled = () => { + // [] + const [parameters, setParameters] = useState({ + state: "NY", + }); + + const handleParametersChange = (payload: ParameterChangePayload) => { + // Sync your local state on every applied change. `payload.source` is one of: + // "initial-state" — post-load snapshot, fired once per dashboard load + // "manual-change" — user edited a parameter widget + // "auto-change" — your push was normalized; re-sync from `payload.parameters` + setParameters(payload.parameters); + }; + + return ( + + ); + // [] +}; + +const ExampleClearOne = () => ( + // [] + // Setting a parameter to `null` clears it (ignores the parameter's default). + // Missing slugs fall back to `parameter.default ?? null`. + + // [] +); + +const ExampleClearAll = () => ( + // [] + // Pass an empty object to clear every parameter. + + // [] +); + +export { ExampleControlled, ExampleClearOne, ExampleClearAll }; diff --git a/_docs/master/embedding/snippets/parameters/dashboards/initial-parameters.tsx b/_docs/master/embedding/snippets/parameters/dashboards/initial-parameters.tsx new file mode 100644 index 0000000000..df8e56bda1 --- /dev/null +++ b/_docs/master/embedding/snippets/parameters/dashboards/initial-parameters.tsx @@ -0,0 +1,14 @@ +import { InteractiveDashboard } from "@metabase/embedding-sdk-react"; + +const dashboardId = 1; + +const Example = () => ( + // [] + + // [] +); + +export { Example }; diff --git a/_docs/master/embedding/snippets/parameters/questions/controlled-sql-parameters.tsx b/_docs/master/embedding/snippets/parameters/questions/controlled-sql-parameters.tsx new file mode 100644 index 0000000000..761ed732cc --- /dev/null +++ b/_docs/master/embedding/snippets/parameters/questions/controlled-sql-parameters.tsx @@ -0,0 +1,44 @@ +import { + InteractiveQuestion, + type SqlParameterChangePayload, + type SqlParameterValues, +} from "@metabase/embedding-sdk-react"; +import { useState } from "react"; + +const questionId = 1; + +const ExampleControlled = () => { + // [] + const [sqlParameters, setSqlParameters] = useState({ + state: "NY", + }); + + const handleSqlParametersChange = (payload: SqlParameterChangePayload) => { + // Sync your local state on every applied change. `payload.source` is one of: + // "initial-state" — post-load snapshot, fired once per question load + // "manual-change" — user edited a parameter widget + // "auto-change" — your push was normalized; re-sync from `payload.parameters` + setSqlParameters(payload.parameters); + }; + + return ( + + ); + // [] +}; + +const ExampleClear = () => ( + // [] + // Setting a SQL parameter to `null` clears it (ignores the parameter's default). + + // [] +); + +export { ExampleControlled, ExampleClear }; diff --git a/_docs/master/embedding/sdk/snippets/questions/initial-sql-parameters.tsx b/_docs/master/embedding/snippets/parameters/questions/initial-sql-parameters.tsx similarity index 100% rename from _docs/master/embedding/sdk/snippets/questions/initial-sql-parameters.tsx rename to _docs/master/embedding/snippets/parameters/questions/initial-sql-parameters.tsx diff --git a/_docs/master/embedding/static-embedding-parameters.md b/_docs/master/embedding/static-embedding-parameters.md index d4789ab161..b256f42394 100644 --- a/_docs/master/embedding/static-embedding-parameters.md +++ b/_docs/master/embedding/static-embedding-parameters.md @@ -18,8 +18,6 @@ Also known as: parameters for signed embeds, or standalone embeds. Parameters are pieces of information that are passed between Metabase and your website via the [embedding URL](./static-embedding#adding-the-embedding-url-to-your-website). You can use parameters to specify how Metabase items should look and behave inside the iframe on your website. -{% include shared/in-page-promo-embedding-workshop.html %} - ## Types of parameters Parameters can be signed or unsigned. diff --git a/_docs/master/embedding/static-embedding.md b/_docs/master/embedding/static-embedding.md index 54db62a83e..c1fd52a675 100644 --- a/_docs/master/embedding/static-embedding.md +++ b/_docs/master/embedding/static-embedding.md @@ -15,8 +15,6 @@ redirect_from: > We recommend you use the new [Guest embedding](./guest-embedding) approach instead of static embedding. -{% include shared/in-page-promo-embedding-workshop.html %} - In general, embedding works by displaying a Metabase URL inside an iframe in your website. A **static embed** (or signed embed) is an iframe that's loading a Metabase URL secured with a signed JSON Web Token (JWT). Metabase will only load the URL if the request supplies a JWT signed with the secret shared between your app and your Metabase. The JWT also includes a reference to the resource to load, e.g., the dashboard ID, and any values for locked parameters. You can't use static embeds with [row and column security](../permissions/row-and-column-security), [drill-through](/learn/metabase-basics/querying-and-dashboards/questions/drill-through), and user-specific data isn't captured in [usage analytics](../usage-and-performance-tools/usage-analytics) because signed JWTs don't create user sessions (server-side sessions). For those features, check out [Modular embedding](./modular-embedding). diff --git a/_docs/master/installation-and-operation/configuring-application-database.md b/_docs/master/installation-and-operation/configuring-application-database.md index 05efa76ecc..2c6569d36b 100644 --- a/_docs/master/installation-and-operation/configuring-application-database.md +++ b/_docs/master/installation-and-operation/configuring-application-database.md @@ -52,7 +52,7 @@ export MB_DB_CONNECTION_URI="jdbc:postgresql://localhost:5432/metabase?user= Skip this step if you're using a [local repo](#local-file-repositories). + Create a personal access token with read and write repository access. Copy the token immediately; you won't be able to see the token again. - **GitHub**: Create a [fine-grained personal access token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens) with **Contents: Read and write** and **Metadata: Read-only** permissions. - **GitLab**: In **User Settings** > **Personal access tokens**, [create a token](https://docs.gitlab.com/user/profile/personal_access_tokens/) with **read_repository** and **write_repository** scopes. Tokens have an expiration date (your admin may set a maximum lifetime). -- **Bitbucket**: In your [Atlassian account settings](https://id.atlassian.com/manage-profile/security) under **Security**, click **Create API token with scopes**. Select Bitbucket, search for "repos", and grant `read:repository:bitbucket` and `write:repository:bitbucket` (write does not include read). Tokens expire and can't be modified after creation. +- **Bitbucket**: In your Bitbucket repository, go to **Repository settings** > **Security** > **Access tokens** and click **Create access token**. Give it a name and, under **Scopes**, select: + + - **Repositories**: **Read** and **Write** + - **Pull requests**: **Read** and **Write** + + Click **Create** and copy the token immediately, you can't view the token again after closing the dialog. + + The created token must have these scopes (visible in the **View access token** dialog after creation): + + - `repository` + - `repository:write` + - `pullrequest` + - `pullrequest:write` ### 3. Connect your development Metabase to your repository @@ -156,7 +171,17 @@ Create a personal access token with read-only repository access. Copy the token - **GitHub**: Create a [fine-grained personal access token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens) with **Contents: Read-only** and **Metadata: Read-only** permissions. - **GitLab**: In **User Settings** > **Personal access tokens**, [create a token](https://docs.gitlab.com/user/profile/personal_access_tokens/) with **read_repository** scope only. -- **Bitbucket**: In your [Atlassian account settings](https://id.atlassian.com/manage-profile/security) under **Security**, click **Create API token with scopes**. Select Bitbucket and grant `read:repository:bitbucket` only. +- **Bitbucket**: In your Bitbucket repository, go to **Repository settings** > **Security** > **Access tokens** and click **Create access token**. Under **Scopes**, select: + + - **Repositories**: **Read** + - **Pull requests**: **Read** + + Leave Write and all other scope groups unchecked. Click **Create** and copy the token immediately. + + The created token must have these scopes (visible in the **View access token** dialog after creation): + + - `repository` + - `pullrequest` ### 7. Connect your production Metabase to your repository @@ -196,9 +221,53 @@ To version your data transformation logic, you can sync your [Transforms](../dat - **Transform syncing is all or nothing**: Metabase will sync your entire transforms namespace. You can't selectively sync specific transform folders. - **This setting only determines whether Metabase pushes transforms from Read-write mode.** When you _pull_ from a repository, all content present in the repo is loaded—including any transforms—regardless of this setting. Think of it like pulling a repo that has a new collection you hadn't previously synced: the setting doesn't filter what comes in, only what goes out. --**You can't edit transforms in read-only mode.**, even if you haven't explicitly turned on transform syncing. Keeping transforms read-only prevents unintended overwrites on subsequent pulls. +- **You can't edit transforms in read-only mode**, even if you haven't explicitly turned on transform syncing. Keeping transforms read-only prevents unintended overwrites on subsequent pulls. - **Use different databases for dev and production**. If you use transforms with Remote Sync, your development and production Metabases should connect to separate databases that share _identical_ schemas. If you use the same database for both, dev transforms would also change production data. +## Local file repositories + +Remote Sync can point at a bare git repo on the same filesystem as your Metabase process, via a `file://` URL. Local repos come in handy for local development, especially alongside the [file-based agent workflow](../ai/file-based-development). + +Create a bare git repo on the same filesystem as your Metabase process: + +```sh +git init --bare /path/to/your-repo.git +``` + +A bare repo is required because Remote Sync pushes into it the same way it would push to a hosted remote. Non-bare repos refuse pushes to a checked-out branch. + +### Point Metabase to your local repo + +Use the `file://` scheme with an absolute path: + +``` +file:///absolute/path/to/your-repo +``` + +Note the three slashes: `file://` plus the leading `/` of the absolute path. + +Leave the access token field blank. Local `file://` repositories don't need one. + +If Metabase runs in Docker, you'll need to mount the directory as a volume and the **`file://` URL must use the container's path**, not the host path. Metabase's process runs inside the container and can only see paths visible from inside it. + +With `docker-compose.yml`: + +```yaml +services: + metabase: + image: metabase/metabase + ports: + - "3000:3000" + volumes: + - /Users/you/local-repo:/Users/you/local-repo +``` + +Then in Metabase, you'd enter: + +``` +file:///Users/you/local-repo +``` + ## An example dev-to-production workflow Let's say your team wants to build a new analytics dashboard. Here's a workflow that ensures all production content goes through a review process. diff --git a/_docs/master/installation-and-operation/running-metabase-on-azure.md b/_docs/master/installation-and-operation/running-metabase-on-azure.md index 24bd313f81..ad1f5b1c04 100644 --- a/_docs/master/installation-and-operation/running-metabase-on-azure.md +++ b/_docs/master/installation-and-operation/running-metabase-on-azure.md @@ -126,7 +126,7 @@ Now click on the huge plus sign next to **Add VNET** and select the VNET that yo Return to the application configuration page and click on **Settings** -> **Configuration** on the left side of the page. You should see a few Application Settings already configured. -You'll need to add the [environment Variables](../configuring-metabase/environment-variables) for connecting Metabase to its [PostgreSQL Application Database](../installation-and-operation/configuring-application-database#postgresql). Make sure that you use the full **MB_DB_CONNECTION_URI**. +You'll need to add the [environment variables](../configuring-metabase/environment-variables) for connecting Metabase to its [PostgreSQL Application Database](../installation-and-operation/configuring-application-database#postgresql). Make sure that you use the full [`MB_DB_CONNECTION_URI`](../configuring-metabase/environment-variables#mb_db_connection_uri). Also, consider that the username in Azure PostgreSQL is `user@name_of_your_database_engine` so in this case the entire connection uri would be as follows: diff --git a/_docs/master/installation-and-operation/running-metabase-on-docker.md b/_docs/master/installation-and-operation/running-metabase-on-docker.md index b3d9fb9814..80710bd424 100644 --- a/_docs/master/installation-and-operation/running-metabase-on-docker.md +++ b/_docs/master/installation-and-operation/running-metabase-on-docker.md @@ -344,13 +344,13 @@ secrets: We currently support the following [environment variables](../configuring-metabase/environment-variables) to be used as secrets: -- `MB_DB_USER` -- `MB_DB_PASS` -- `MB_DB_CONNECTION_URI` -- `MB_EMAIL_SMTP_PASSWORD` -- `MB_EMAIL_SMTP_USERNAME` -- `MB_LDAP_PASSWORD` -- `MB_LDAP_BIND_DN` +- [`MB_DB_USER`](../configuring-metabase/environment-variables#mb_db_user) +- [`MB_DB_PASS`](../configuring-metabase/environment-variables#mb_db_pass) +- [`MB_DB_CONNECTION_URI`](../configuring-metabase/environment-variables#mb_db_connection_uri) +- [`MB_EMAIL_SMTP_PASSWORD`](../configuring-metabase/environment-variables#mb_email_smtp_password) +- [`MB_EMAIL_SMTP_USERNAME`](../configuring-metabase/environment-variables#mb_email_smtp_username) +- [`MB_LDAP_PASSWORD`](../configuring-metabase/environment-variables#mb_ldap_password) +- [`MB_LDAP_BIND_DN`](../configuring-metabase/environment-variables#mb_ldap_bind_dn) In order for the Metabase container to read the files and use the contents as a secret, the environment variable name needs to be appended with a "\_FILE" as explained above. diff --git a/_docs/master/installation-and-operation/running-the-metabase-jar-file.md b/_docs/master/installation-and-operation/running-the-metabase-jar-file.md index 193fd52a37..7a62666c1a 100644 --- a/_docs/master/installation-and-operation/running-the-metabase-jar-file.md +++ b/_docs/master/installation-and-operation/running-the-metabase-jar-file.md @@ -110,7 +110,7 @@ Metabase will start using the default settings. You should see some log entries At this point you're ready to go! You can access your new Metabase server on port 3000, most likely at `http://localhost:3000`. -You can use another port than 3000 by setting the `MB_JETTY_PORT` [environment variable](../configuring-metabase/environment-variables) before running the jar. +You can use another port than 3000 by setting the `MB_JETTY_PORT` [environment variable](../configuring-metabase/environment-variables#mb_jetty_port) before running the jar. If you are using a Pro or Enterprise version of Metabase, be sure to [activate your license](../installation-and-operation/activating-the-enterprise-edition). diff --git a/_docs/master/installation-and-operation/security-center.md b/_docs/master/installation-and-operation/security-center.md new file mode 100644 index 0000000000..865c59191b --- /dev/null +++ b/_docs/master/installation-and-operation/security-center.md @@ -0,0 +1,72 @@ +--- +version: master +has_magic_breadcrumbs: true +show_category_breadcrumb: true +show_title_breadcrumb: true +category: 'Installation and Operation' +title: 'Security center' +source_url: 'https://github.com/metabase/metabase/blob/master/docs/installation-and-operation/security-center.md' +layout: new-docs +summary: 'See all security advisories published by Metabase and subscribe to notifications.' +--- + +# Security center + +{% include plans-blockquote.html feature="Security center" self-hosted-only="true" %} + +_Admin > Security_ + +The Security Center is the main way we (Metabase the company) let people who are self-hosting Metabase know about important security patches. You can configure Metabase to send notifications to specific email addresses or a Slack channel whenever a new security advisory is published. + +![Security center](./images/security-center.png) + +Security center is available for (and relevant to) self-hosted Metabases on Pro/Enterprise plans. Metabase Cloud instances are automatically patched as soon as issues are discovered and resolved. Air-gapped Metabases will not get the security center (regardless of the plan) because security center needs to check Metabases's security registry for updates, which would violate air-gapping. + +## See security issues affecting your instance + +Security center in **Admin > Security** will display _all_ security advisories published by Metabase, regardless of whether they're affecting your instance. + +You can opt in to get email or Slack notifications when new issues affect your instance. + +![Security center](./images/security-center.png) + +To check whether your instance is affected by a security issue, Metabase analyzes the instance's configuration: version, settings, databases connected, features used, etc. For example, if an advisory involving impersonation on PostgreSQL is posted, Metabase will check whether your instance has a PostgreSQL database connected, and whether it has impersonation enabled. If Metabase finds an issue that impacts your Metabase, it will highlight the issue in the security center and send you a notification (if you've set up notifications, which you should do). + +Metabase checks for new security advisories periodically, but you can also force the check by clicking **Check now** in the security center. + +You can dismiss security issues by clicking **Dismiss** on an issue. Keep in mind that you can't un-dismiss the issue, so only dismiss an issue once you've gone through remediation steps. + +## Remedy security issues + +Every security issue posted in **Admin > Security** will come with remediation steps. These steps will usually just involve upgrading your Metabase. + +See [Upgrading a self-hosted Metabase](upgrading-metabase#upgrading-a-self-hosted-metabase). + +If you have questions or need help, you can always [reach out to us](/help-premium) and we'll get you sorted. + +## Get notified about security issues + +_Admin > Security_ + +To get notified about security issues affecting your instance, you must set up at least one notification channel for your Metabase. See [Set up email](../configuring-metabase/email) or [Set up Slack](../configuring-metabase/slack). + +Once you set up a notification channel for your Metabase: + +1. Go to **Admin > Security**. +2. At the top of security center, click **Notification settings**. +3. Select Email and/or Slack: + + - **Email**: you can choose whether to send emails to all admins of your Metabase, and add any additional emails, including non-Metabase users. For example, you can add people from the security team at your org. + - **Slack**: pick a channel or a user to send notifications to. + + ![Security notification](./images/security-notify.png) + +4. (Optional, but you should do this) Click **Send the test notification** to make sure the messages actually arrive. +5. Save. + +You'll only get notifications about new issues _affecting your instance_. New issues that don't affect your instance will be visible in the security center, but you won't get notified about them. + +## Further reading + +- [Security](/security) +- [Upgrading Metabase](upgrading-metabase) diff --git a/_docs/master/people-and-groups/authenticating-with-jwt.md b/_docs/master/people-and-groups/authenticating-with-jwt.md index 5d7daef4e1..8a51270f63 100644 --- a/_docs/master/people-and-groups/authenticating-with-jwt.md +++ b/_docs/master/people-and-groups/authenticating-with-jwt.md @@ -29,6 +29,8 @@ Assuming your site is localhost serving on port 3000: 5. In the event of a successful sign-in, your authentication app should issue a GET request to your Metabase endpoint with the token and the "return to" URI: `http://localhost:3000/auth/sso?jwt=TOKEN_GOES_HERE&return_to=/question/1-superb-question`. 6. Metabase verifies the JSON Web Token, logs the person in, then redirects the person to their original destination, `/question/1-superb-question`. +As an alternative to putting the JWT in the URL query string (which some environments log or cache), you can send the same token in the body of a `POST` request to `/auth/sso` with `Content-Type: application/json` and a JSON body like `{"jwt": "TOKEN_GOES_HERE"}`. You can still pass `return_to` as a query parameter on that URL (for example `POST /auth/sso?return_to=/question/1-superb-question`). The login behavior is otherwise the same as the GET flow. + ## Set up JWT authentication Navigate to the **Admin**>**Settings** section of the Admin area, then click on the **Authentication > JWT** tab. diff --git a/_docs/master/permissions/collections.md b/_docs/master/permissions/collections.md index d4c271e5ed..96d26c43a8 100644 --- a/_docs/master/permissions/collections.md +++ b/_docs/master/permissions/collections.md @@ -43,7 +43,7 @@ The group can view, edit, move, delete, and pin items saved in this collection, ### View access -The group can see all the questions, dashboards, and models in the collection, as well as [events and timelines](../exploration-and-organization/events-and-timelines). +The group can see all the questions, dashboards, and models in the collection, as well as [events and timelines](../exploration-and-organization/events-and-timelines). Note: Curate access includes View access. ### No access @@ -77,7 +77,15 @@ Just like with data access permissions, collection permissions are _additive_, m ## Permissions and sub-collections -A group can be given access to a collection located somewhere within one or more sub-collections _without_ having to have access to every collection "above" it. For example, if a group had access to the "Super Secret Collection" that's saved several layers deep within a "Marketing" collection that the group lacks access to, the "Super Secret Collection" would show up at the top-most level that the group _does_ have access to. +- Changing access to a collection doesn't automatically change access to _existing_ subcollections, but all _new_ subcollections will inherit the access level. + + For example, let's say you have a `Campaigns` collection with a `2025 reports` subcollection, and you change the "Data team" group's access to `Campaigns` from "View" to "Curate". Then by default, Data team will get Curate access to `Campaigns` but will retain only "View" access to `2025 reports`. However, if after these permissions are configured, someone adds a new subcollection `2026 reports`, then Data team will get Curate access to "2026 reports" because new subcollections inherit permissions from the parent collection. + +- To change access for existing subcollections as well, toggle **Also change sub-collections** when changing collection access. + +- A group can be given access to a collection located somewhere within one or more sub-collections _without_ having to have access to every collection "above" it. + + For example, if a group had access to the "Super Secret Collection" that's saved several layers deep within a "Marketing" collection that the group lacks access to, the "Super Secret Collection" would show up at the top-most level that the group _does_ have access to. ## Deleting collections diff --git a/_docs/master/questions/alerts.md b/_docs/master/questions/alerts.md index 1036eeff4c..b0b74b83d6 100644 --- a/_docs/master/questions/alerts.md +++ b/_docs/master/questions/alerts.md @@ -149,7 +149,7 @@ Alerts will continue to work _even if the person who set up the alert no longer {% include plans-blockquote.html feature="Usage analytics" %} -Admins can view a list of all alerts and dashboard subscriptions that people have set up in your Metabase in the **Usage analytics** collection. See [Usage analytics](../usage-and-performance-tools/usage-analytics#alerts-model). +Admins can view a list of all alerts and dashboard subscriptions that people have set up in your Metabase in the **Usage analytics** collection. See the [Alerts model](../usage-and-performance-tools/usage-analytics-reference#alerts) in the Usage analytics reference. ## How permissions work with alerts diff --git a/_docs/master/questions/exporting-results.md b/_docs/master/questions/exporting-results.md index 441291a616..926ac79283 100644 --- a/_docs/master/questions/exporting-results.md +++ b/_docs/master/questions/exporting-results.md @@ -70,7 +70,7 @@ The reason Metabase doesn't try to export results as a native Excel PivotTable i By default, Metabase will export first 1048575 rows of results. -- For CSV exports, you can increase this limit with an environment variable: [`MB_DOWNLOAD_ROW_LIMIT`](../configuring-metabase/environment-variables). Increasing this limit, however, may impact your Metabase's performance. +- For CSV exports, you can increase this limit with an environment variable: [`MB_DOWNLOAD_ROW_LIMIT`](../configuring-metabase/environment-variables#mb_download_row_limit). Increasing this limit, however, may impact your Metabase's performance. - XLSX exports will always be limited to Excel's maximum of 1048575 rows (plus the header row). ### Cell character limit in Excel exports diff --git a/_docs/master/questions/images/break-out-metric.png b/_docs/master/questions/images/break-out-metric.png index effc2c2528..ac430f4edc 100644 Binary files a/_docs/master/questions/images/break-out-metric.png and b/_docs/master/questions/images/break-out-metric.png differ diff --git a/_docs/master/questions/images/breakout-chart-explorer.png b/_docs/master/questions/images/breakout-chart-explorer.png index 45afe8f402..0d7cdc26ab 100644 Binary files a/_docs/master/questions/images/breakout-chart-explorer.png and b/_docs/master/questions/images/breakout-chart-explorer.png differ diff --git a/_docs/master/questions/images/bubble-chart-colored-series-example.png b/_docs/master/questions/images/bubble-chart-colored-series-example.png new file mode 100644 index 0000000000..59a06484d2 Binary files /dev/null and b/_docs/master/questions/images/bubble-chart-colored-series-example.png differ diff --git a/_docs/master/questions/images/bubble-chart-example.png b/_docs/master/questions/images/bubble-chart-example.png new file mode 100644 index 0000000000..51bbcf4975 Binary files /dev/null and b/_docs/master/questions/images/bubble-chart-example.png differ diff --git a/_docs/master/questions/images/compare-metrics.png b/_docs/master/questions/images/compare-metrics.png index 795b12c3f8..5d0aec1266 100644 Binary files a/_docs/master/questions/images/compare-metrics.png and b/_docs/master/questions/images/compare-metrics.png differ diff --git a/_docs/master/questions/images/math-with-metrics.png b/_docs/master/questions/images/math-with-metrics.png new file mode 100644 index 0000000000..9dedfcd5cd Binary files /dev/null and b/_docs/master/questions/images/math-with-metrics.png differ diff --git a/_docs/master/questions/images/metrics-explorer.png b/_docs/master/questions/images/metrics-explorer.png index ff6361bc17..077c7f8cc7 100644 Binary files a/_docs/master/questions/images/metrics-explorer.png and b/_docs/master/questions/images/metrics-explorer.png differ diff --git a/_docs/master/questions/images/scatterplot-example.png b/_docs/master/questions/images/scatterplot-example.png new file mode 100644 index 0000000000..34bd275ea0 Binary files /dev/null and b/_docs/master/questions/images/scatterplot-example.png differ diff --git a/_docs/master/questions/images/two-metrics.png b/_docs/master/questions/images/two-metrics.png index b067e6d9b4..9cfb1ec5c5 100644 Binary files a/_docs/master/questions/images/two-metrics.png and b/_docs/master/questions/images/two-metrics.png differ diff --git a/_docs/master/questions/images/waterfall-chart.png b/_docs/master/questions/images/waterfall-chart.png index 60cbdafba4..40e3592ede 100644 Binary files a/_docs/master/questions/images/waterfall-chart.png and b/_docs/master/questions/images/waterfall-chart.png differ diff --git a/_docs/master/questions/metrics-explorer.md b/_docs/master/questions/metrics-explorer.md index e0bda24e86..5dd9cb0bac 100644 --- a/_docs/master/questions/metrics-explorer.md +++ b/_docs/master/questions/metrics-explorer.md @@ -12,7 +12,7 @@ summary: 'Explore metrics and measures across dimensions and compare them side b # Metrics explorer -The metrics Explorer is a space for ad-hoc analysis of [metrics](../data-modeling/metrics) and [measures](../data-studio/measures) +The metrics explorer is a space for ad-hoc analysis of [metrics](../data-modeling/metrics) and [measures](../data-studio/measures) ![Metrics explorer](../questions/images/metrics-explorer.png) @@ -22,6 +22,7 @@ You can: - [Explore metrics and measures along their dimensions](#explore-a-metric-or-a-measure) - [Compare multiple metrics and measures](#compare-metrics-and-measures) +- [Do math with metrics](#calculations-with-metrics-and-measures) - [Break out by additional dimensions](#break-out-by-dimensions) - [Filter each metric or measure](#filter-metrics-and-measures) - Zoom into time periods @@ -32,25 +33,42 @@ To share your metric explorations with people in your organization, you can copy ## Explore a metric or a measure +In the metrics explorer, you can explore how a measure or metric varies across dimensions. + To open a **metric** in the Metrics Explorer: 1. Navigate to the metric's home page. To get to the metric's home page, you can click on a metric from its collection, from the [metrics browser](../data-modeling/metrics#see-all-metrics), or from search. -2. Click **Explore** in the top right corner to open the metrics explorer +2. To view the metric in the explorer, click **Explore** in the top right corner. + +To return to the metric's home page, click the metric card in the search bar and select **Go to metric home page**. + +To open a **measure** in the metrics explorer: -To get back to the metric's page from metrics explorer, right-click the metric card in the search bar and select **Go to metric home page**. +1. Navigate to the measure in **Data studio > Tables > [Your table] > Measures**. +2. Select your measure. +3. On the measure's page, click **three dots** next to the measure's name and select **Explore**. -To open a **measure** in the metrics explorer, go directly to `[your metabase URL]/explore` and type the measure's name in the search bar. To get back to the measure definition from metrics explorer, right-click the measure card in the search bar and select **Edit in Data Studio**. +Once you open a measure or metric in the metrics explorer, Metabase will create tabs plotting the metric/measure along the most appropriate dimensions, as well as the **Totals** tab with the total result of the metric, without any dimensions applied. + +You can also [break out](#break-out-by-dimensions) a metric/measure by additional dimensions or [filter the metric/measure](#filter-metrics-and-measures). ## Compare metrics and measures -To compare multiple metrics or measures, search for measure or metric you want to add in the search bar. +To compare multiple metrics or measures: + +1. [Open one of the metrics/measures in the metrics explorer](#explore-a-metric-or-a-measure). +2. Click the top search bar and search for another measure or metric you want to add. -![Compare metrics](./images/compare-metrics.png) +3. Press **Enter** or click **Run** in the search bar. -You'll see the dimensions of the first metric/measure below the search bar. You can pick a dimension to break out the metrics/measures (for example, if you want to see how both Number of Orders and Revenue change by date, state, or product category). + ![Compare metrics](./images/compare-metrics.png) + +You can add the same metric/measure multiple times. This is useful if you want to [break out](#break-out-by-dimensions) or [filter](#filter-metrics-and-measures) the metric, while keeping the total trend visibile. For example, you might want to compare the trend of total revenue to the revenue of a single product category. + +Once you pick the metrics, you'll see the dimensions of the first metric/measure below the search bar. You can pick a dimension to compare metrics/measures (for example, if you want to see how both Number of Orders and Revenue change by date, state, or product category). ![Compare metrics](./images/two-metrics.png) @@ -68,20 +86,22 @@ If your metrics/measures don't have shared dimensions, you'll need to select a d When your metrics/measures don't have shared dimensions, Metabase has no way of knowing how the dimensions relate to each other, so it's on you to make sure the dimensions you pick make sense to compare! +You can [filter](#filter-metrics-and-measures) or [break out](#break-out-by-dimensions) each metric/measure separately, or [do simple calculations with metrics/measures](#calculations-with-metrics-and-measures). + ## Break out by dimensions You can also break out each metric by additional dimensions. For example, you might want to compare overall revenue to the number of orders for each product category. +![Break out](./images/breakout-chart-explorer.png) + To break out a metric or measure by additional dimensions: -1. Right-click on the metric's card in the search bar. +1. Click on the metric's card in the search bar. 2. Select **Break out** ![Break out by](./images/break-out-metric.png) 3. Choose the breakout dimension. -![Break out](./images/breakout-chart-explorer.png) - -To remove the breakout, right-click on the measure/metric card again and select **Remove breakout** +To remove the breakout, click on the measure/metric card in the search bar again and select **Remove breakout**. ## Filter metrics and measures @@ -96,3 +116,17 @@ To add a filter to a metric or measure: You'll see the filter added below the metric or measure's card in the search bar. To remove the filter, click the **X** on the filter's card. ![Filtered metric](./images/filtered-metric.png) + +## Calculations with metrics and measures + +You can use the four basic math operations (`+`,`-`,`*`,`/`) on metrics/measures in the metrics explorer. For example, you can explore how revenue per user, `Revenue / Active users`, changes with time. + +The metrics explorer is especially useful when metrics and measures are associated with different data sources, likeif you have a "Revenue" metric on the `Subscriptions` table and an "Active users" metric on the `Events` table. If you were to compare these metrics in the query builder, you'd have to wrangle their tables with joins, but the metrics explorer lets you compare these metrics by just typing out a formula. + +![Math with metrics](./images/math-with-metrics.png) + +To write an expression with metrics/measures, just start entering the formula into the search bar. You can use `+`,`-`,`*`,`/`, parentheses, numbers, or other metrics (including using the same metric multiple times). To visualize the results, just press Enter. + +To edit the expression, click on the expression's card in the search bar and click **Edit**. + +You can also rename your expressions. For example, you might want to rename your formula `Revenue / Active users` as `Per user revenue`. To rename the expression, click the expression's card in the search bar, click **Rename**, and type the new name. diff --git a/_docs/master/questions/visualizations/scatterplot-or-bubble-chart.md b/_docs/master/questions/visualizations/scatterplot-or-bubble-chart.md index 4fda007c9f..a98d72cb40 100644 --- a/_docs/master/questions/visualizations/scatterplot-or-bubble-chart.md +++ b/_docs/master/questions/visualizations/scatterplot-or-bubble-chart.md @@ -13,10 +13,151 @@ redirect_from: # Scatterplots and bubble charts -**Scatterplots** are useful for visualizing the correlation between two variables, like comparing the age of your users vs. how many dollars they've spent on your products. To use a scatterplot, you'll need to ask a question that results in two numeric columns, like `Count of Orders grouped by Customer Age`. Alternatively, you can use a table and select the two numeric fields you want to use in the chart options. +Scatterplots and bubble charts visualize the relationship between values. -If you have a third numeric field, you can also create a **bubble chart**. Select the Scatter visualization, then open up the chart settings and select a field in the **bubble size** dropdown. This field will be used to determine the size of each bubble on your chart. For example, you could use a field that contains the total dollar amount for each x-y pair — i.e. larger bubbles for larger total dollar amounts spent on orders. - -Scatterplots and bubble charts also have similar chart options as line, bar, and area charts, including the option to display trend or goal lines, or stack series. +Scatterplots show two numeric values per data point, while bubble charts show three by using the size of each dot to represent a third value. In Metabase, both chart types use the same **Scatter** visualization type. Adding a bubble size column turns a scatterplot into a bubble chart. ![Scatter](../images/scatter.png) + +## How to create a scatterplot or bubble chart + +You can create a scatterplot or bubble chart from a few different data shapes, depending on whether you want to add bubble sizing or colored series. + +### Create a scatterplot + +1. Create a question that returns two numeric columns. For example, summarize `Count of orders` and `Average of total` grouped by `Product ID`: + + | Product ID | Count of orders | Average of total | + | ---------- | --------------- | ---------------- | + | 1 | 93 | 42.48 | + | 2 | 98 | 104.48 | + | 3 | 77 | 52.68 | + | 4 | 89 | 108.95 | + | 5 | 97 | 117.08 | + + You can also use one numeric column grouped by a category or time dimension. For example, summarize `Average of total` grouped by `Product Category`: + + | Product Category | Average of total | + | ---------------- | ---------------- | + | Gizmo | 84.12 | + | Doohickey | 76.95 | + | Gadget | 92.40 | + | Widget | 88.27 | + +2. In the visualization picker, select **Scatter**. + +Each row in the result becomes a single dot on the chart. One column maps to the x-axis and the other to the y-axis. + +![Scatterplot example](../images/scatterplot-example.png) + +### Create a bubble chart + +1. Create a question that returns three numeric columns. For example, summarize `Count of orders`, `Average of total`, and `Sum of total` grouped by `Product ID`: + + | Product ID | Count of orders | Average of total | Sum of total | + | ---------- | --------------- | ---------------- | ------------ | + | 1 | 93 | 42.48 | 3,950.53 | + | 2 | 98 | 104.48 | 10,238.92 | + | 3 | 77 | 52.68 | 4,056.36 | + | 4 | 89 | 108.95 | 9,696.46 | + | 5 | 97 | 117.08 | 11,356.66 | + + You can also use two numeric columns grouped by a category or time dimension. For example, summarize `Average of total` and `Sum of total` grouped by `Product Category`: + + | Product Category | Average of total | Sum of total | + | ---------------- | ---------------- | ------------ | + | Gizmo | 84.12 | 425,000 | + | Doohickey | 76.95 | 312,400 | + | Gadget | 92.40 | 587,200 | + | Widget | 88.27 | 401,800 | + + You can also use one numeric column grouped by two category or time dimensions. For example, summarize `Average of total` grouped by `Product ID` and `Product Category`: + + | Product ID | Product Category | Average of total | + | ---------- | ---------------- | ---------------- | + | 1 | Gizmo | 42.48 | + | 2 | Doohickey | 104.48 | + | 3 | Doohickey | 52.68 | + | 4 | Doohickey | 108.95 | + | 5 | Gadget | 117.08 | + +2. In the visualization picker, select **Scatter**. +3. In chart settings, select a numeric column from the **Bubble size** menu. + +Each row in the result becomes a single dot on the chart. One column maps to the x-axis, one to the y-axis, and the bubble size column determines the size of the dot. + +![Bubble chart example](../images/bubble-chart-example.png) + +### Add a category for colored series + +1. Create a question with the data shape for a scatterplot or bubble chart. Include a category column for the colored series. For example, summarize `Count of orders` and `Average of total` grouped by `Product ID` and `Product Category`: + + | Product ID | Product Category | Count of orders | Average of total | + | ---------- | ---------------- | --------------- | ---------------- | + | 1 | Gizmo | 93 | 42.48 | + | 2 | Doohickey | 98 | 104.48 | + | 3 | Doohickey | 77 | 52.68 | + | 4 | Doohickey | 89 | 108.95 | + | 5 | Gadget | 97 | 117.08 | + +2. In the visualization picker, select **Scatter**. + +Each category becomes its own colored series. The example chart shows the Gizmo, Doohickey, Gadget, and Widget series. + +![Bubble chart colored series example](../images/bubble-chart-colored-series-example.png) + +## Scatterplot and bubble chart settings + +To open chart settings, click the **Gear** icon in the bottom left of the visualization. + +### Data + +In chart settings, click the **Data** tab to configure which columns appear on the chart. + +- **X-axis:** The column(s) to plot on the x-axis +- **Y-axis:** The column(s) to plot on the y-axis +- **Bubble size:** The column that determines the size of each dot (leave empty for a standard scatterplot) + +### Display + +In chart settings, click the **Display** tab to edit how the chart looks. + +To add a goal line, enable the **Goal line** toggle. Use the **Goal value** and **Goal label** fields to set the value and label. + +> You can't set [alerts](../alerts) on goal lines in scatterplots or bubble charts. + +To stack series on top of each other, enable the **Stack series** toggle. + +To show extra information when hovering over a dot, add columns to **Additional tooltip columns**. + +### Axes + +In chart settings, click the **Axes** tab to edit the chart axes. + +#### X-axis + +Use the following options for the x-axis: + +- **Show label:** Enable the toggle to display the x-axis label. +- **Label:** Name the x-axis label. +- **Show lines and tick marks:** Select how to display the x-axis line, tick marks, and labels. Choose between **Hide**, **Show**, **Compact**, **Rotate 45°**, and **Rotate 90°**. +- **Scale:** Select how values are spaced along the x-axis. Choose between **Linear**, **Power**, **Log**, **Histogram**, and **Ordinal**. + +#### Y-axis + +Use the following options for the y-axis: + +- **Show label:** Enable the toggle to display the y-axis label. +- **Label:** Name the y-axis label. +- **Split y-axis when necessary:** When enabled, Metabase displays separate y-axes for series with very different value ranges. +- **Auto y-axis range:** When enabled, Metabase sets the y-axis range automatically based on your data. When disabled, use the **Min** and **Max** fields to set custom values. +- **Unpin from zero:** When enabled, the y-axis can start at a value other than zero. +- **Scale:** Select how values are spaced along the y-axis. Choose between **Linear**, **Power**, and **Log**. +- **Show lines and tick marks:** Select how to display the y-axis line, tick marks, and labels. Choose between **Hide**, **Show**, **Compact**, **Rotate 45°**, and **Rotate 90°**. +- **Number of tick marks:** Set how many tick marks appear on the y-axis. Defaults to **auto**. + +## Limitations and alternatives + +- If you only have one numeric value to plot, or if you want to show how a value changes over time, consider a [bar chart, histogram, or line chart](./line-bar-and-area-charts) instead. +- Scatterplots can become hard to read with very large datasets because of overlapping dots. For large datasets, consider aggregating your data, or using a [heat map](./pivot-table#using-pivot-tables-as-heatmaps) or [box plot](./box-plot) instead. +- You can't set [alerts](../alerts) on goal lines in scatterplots or bubble charts. diff --git a/_docs/master/questions/visualizations/waterfall-chart.md b/_docs/master/questions/visualizations/waterfall-chart.md index 9bc0cca1c6..79b136cd73 100644 --- a/_docs/master/questions/visualizations/waterfall-chart.md +++ b/_docs/master/questions/visualizations/waterfall-chart.md @@ -13,10 +13,114 @@ redirect_from: # Waterfall charts -Waterfall charts are a kind of bar chart useful for visualizing results that contain both positive and negative values. Each bar on a waterfall chart shows either an increase or decrease, with a final bar on the right of the chart that represents the total value. +Waterfall charts are a type of bar chart for visualizing data with both positive and negative values. Each bar shows an increase or decrease, and a final bar on the right shows the running total. ![Waterfall chart](../images/waterfall-chart.png) -In the example above, the waterfall chart displays "Profit" for each "Product:" apples, bananas, oranges, peaches, and mangos. From left to right, each bar indicates the change in total. The products with green bars indicate positive values (they made a profit). Peaches, however, lost money, indicated by a red bar, which signals a negative value. The bar at the end shows the total profit of all products combined. You can show values on each bar, and change the colors for increases and decreases. +## When to use a waterfall chart -For waterfall charts, you'll want a query that is a single metric grouped by a single dimension: by time or category. +Use a waterfall chart to show how a starting value changes through a series of increases and decreases to arrive at a final total. + +Waterfall charts are useful for financial breakdowns, inventory changes, or anywhere you need to show how a value changes step by step. + +## Data shape for a waterfall chart + +To create a waterfall chart, create a question that returns a single metric grouped by a single dimension, such as time or category. + +Waterfall charts work best when each row represents a *change* in some value rather than the raw value itself. For example, use the change in sales from one month to the next, rather than the monthly sales totals. + +Here's the data shape for the example chart above: + +| Month | Change in sales | +| ---------- | --------------- | +| January | 12,500 | +| February | -3,200 | +| March | 5,800 | +| April | -1,600 | +| May | 7,100 | +| June | 4,200 | + +Green bars represent months where sales increased, and red bars represent months where sales decreased. The dark bar at the end shows the net change across all six months. + +Here's another example grouped by category instead of time: + +| Category | Net revenue | +| ----------- | ----------- | +| Gizmo | 18,400 | +| Doohickey | -2,100 | +| Widget | 9,700 | +| Gadget | -4,500 | + +## Build a query for a waterfall chart + +Your data might contain raw values like monthly sales totals but not the change in sales from one month to the next: + +| Month | Sales | +| ---------- | ------- | +| January | 50,000 | +| February | 46,800 | +| March | 52,600 | + +To compute the change from one row to the next, use the `Offset` [custom expression](../query-builder/expressions) in a custom aggregation. `Offset` returns the value of an expression from another row, either earlier or later in the result set. + +To compute the change in sales from the previous month: + +1. In the query builder, click **Summarize**. +2. Group by **Created At: Month**. +3. Add a **Custom Expression** with the formula: `Sum([Sales]) - Offset(Sum([Sales]), -1)`. Name the column "Change in sales". + +The resulting question returns the data shape you need for a waterfall chart. + +If your data already contains the changes you want to plot (for example, individual transactions with positive and negative amounts), you can skip this step and use the data directly. + +## Waterfall chart settings + +To open chart settings, click the **Gear** icon in the bottom left of the visualization. + +### Display + +In chart settings, click the **Display** tab to edit how the chart looks. + +To add a goal line to your waterfall chart, enable the **Goal line** toggle. Use the **Goal value** and **Goal label** fields to set the goal value and label. + +> You can't set [alerts](../alerts) on goal lines in waterfall charts. + +Set the colors for each bar type: + +- **Increase color:** The color for bars that represent positive values (defaults to green) +- **Decrease color:** The color for bars that represent negative values (defaults to red) +- **Total color:** The color for the final total bar (defaults to black) + +To display the value for the final total bar, enable the **Show total** toggle. + +To display values for all bars, enable the **Show values on data points** toggle. + +### Axes + +In chart settings, click the **Axes** tab to edit the chart axes. + +#### X-axis + +Use the following options for the x-axis: + +- **Show label:** Enable the toggle to display the x-axis label. +- **Label:** Name the x-axis label. +- **Show lines and tick marks:** Display the x-axis line and tick marks. + +#### Y-axis + +Use the following options for the y-axis: + +- **Show label:** Enable the toggle to display the y-axis label. +- **Label:** Name the y-axis label. +- **Auto y-axis range:** When enabled, Metabase sets the y-axis range automatically based on your data. When disabled, use the **Min** and **Max** fields to set custom values. +- **Scale:** Choose how values are spaced along the y-axis. Choose between **Linear**, **Power**, and **Log**. +- **Show lines and tick marks:** Display the y-axis line and tick marks. +- **Number of tick marks:** Set how many tick marks appear on the y-axis. Defaults to **auto**. + +## Limitations and alternatives + +- If your data only contains positive values, or if you don't need to track a running total, consider a [bar chart](./line-bar-and-area-charts) instead. +- If you want to show progress toward a single value, consider a [progress bar](./progress-bar) or [gauge chart](./gauge) instead. +- Waterfall charts only support a single metric grouped by a single dimension. You can't add breakouts or display multiple series. +- You can't set [alerts](../alerts) on goal lines in waterfall charts. diff --git a/_docs/master/usage-and-performance-tools/usage-analytics-reference.md b/_docs/master/usage-and-performance-tools/usage-analytics-reference.md new file mode 100644 index 0000000000..97eada11da --- /dev/null +++ b/_docs/master/usage-and-performance-tools/usage-analytics-reference.md @@ -0,0 +1,714 @@ +--- +version: master +has_magic_breadcrumbs: true +show_category_breadcrumb: true +show_title_breadcrumb: true +category: 'Usage and Performance Tools' +title: 'Usage analytics reference' +source_url: 'https://github.com/metabase/metabase/blob/master/docs/usage-and-performance-tools/usage-analytics-reference.md' +layout: new-docs +summary: 'A list of the dashboards and models included in the Usage Analytics collection.' +--- + +# Usage analytics reference + +_This page is generated by `bin/generate-usage-analytics-docs.bb`._ + +Here is a list of all of the dashboards and models included in the Usage Analytics collection, as well as the list of topics and entity types found in the models. + +For an overview of access, retention, and custom reports, see [Usage analytics](usage-analytics). + +For more on AI usage data, see [AI usage auditing](../ai/usage-auditing). + +## Dashboards + +### Content with cobwebs + +Dashboards and questions that you could consider archiving. + +Cards: + +- Dashboards without recent views +- Questions that don't belong to a dashboard +- Questions without recent views + +### Dashboard overview + +Information on the performance, views, activity, and more for a particular dashboard. + +Cards: + +- Dashboard metadata +- Dashboard views per month +- Most active people on this dashboard +- Questions in this dashboard +- Recent activity on dashboard +- Subscriptions on this dashboard + +### Dashboard subscriptions and alerts + +All active notifications + +Cards: + +- Active dashboard subscriptions +- Alerts + +### Embedding Usage + +General information about embedding usage, including views across embedded dashboards and questions + +Cards: + +- Active tenants +- Authenticated views +- Guest views +- Most viewed authenticated embeds +- Most viewed guest embeds +- Most viewed public links +- Public link views +- Tenants with most views +- Unique users +- Views by auth method +- Views by embedding client +- Views by embedding host +- Views by user agent + +### Metabase metrics + +General information about people viewing and creating dashboards, questions, subscriptions, and alerts. + +Cards: + +- Active users last week +- Alerts and subscriptions created last week +- Dashboards created last week +- Most active creators +- Most active viewers +- Most viewed cards +- Most viewed dashboards +- Question views last week +- Question views per week +- Questions created last week +- Weekly active users + +### Most viewed content + +Most viewed dashboards, questions, and tables in your Metabase. + +Cards: + +- Most viewed dashboards +- Most viewed models +- Most viewed questions +- Most viewed tables + +### Performance overview + +Question, dashboard and database performance. + +Cards: + +- 50th and 90th percentile of query running time (seconds) +- 90th percentile of query run time (seconds) +- Dashboards consuming most resources +- Dashboards with more questions in the same tab +- Questions consuming most resources +- Slowest dashboards +- Slowest questions +- Total number of queries +- Total time looking for field values per day +- Total time spent on sync per day +- Users consuming most resources +- Weekly cache hit rate + +### Person overview + +See what someone's been up to in your Metabase. + +Cards: + +- Active alerts +- Last downloads +- Last queries +- Last viewed dashboards +- Last viewed models +- Last viewed questions +- Last viewed tables +- Member of +- Most viewed dashboards +- Most viewed models +- Most viewed questions +- Most viewed tables +- Person detail +- Question views per month +- Questions created per month +- Recent activity + +### Question overview + +Views, performance, activity, and other data for a particular question. + +Cards: + +- Alerts on this question +- Dashboards with this question +- Last activity on question +- Last downloads +- Most active people on this question +- Question metadata +- Question views per month + +## Models + +### Activity log + +Things that happened in your Metabase. + +Columns: + +- ID +- Topic +- Timestamp +- End Timestamp +- User ID +- Entity Type +- Entity ID +- Entity Qualified ID +- Details + +### AI Usage Log + +One row per LLM round-trip with per-call tokens, source, model, profile, and more. + +Columns: + +- Usage Log ID +- Created At +- Source +- Source Name +- Model +- Profile ID +- Prompt Tokens +- Completion Tokens +- Total Tokens +- Conversation ID +- User ID +- User Qualified ID +- User Display Name +- Group Name +- IP Address +- Tenant ID +- Request ID +- Cache Creation Tokens +- Cache Read Tokens + +### Alerts + +All alerts, both active and archived. + +Columns: + +- Entity ID +- Entity Qualified ID +- Created At +- Updated At +- Creator ID +- Card ID +- Card Qualified ID +- Alert Condition +- Schedule Type +- Schedule Day +- Schedule Hour +- Archived +- Recipient Type +- Recipients +- Recipient External + +### Content + +All Metabase content, including questions, models, dashboards, events, and collections. + +Columns: + +- Entity ID +- Entity Qualified ID +- Entity Type +- Created At +- Updated At +- Creator ID +- Name +- Description +- Collection ID +- Made Public By User +- Is Embedding Enabled +- Is Verified +- Archived +- Action Type +- Action Model ID +- Collection Is Official +- Collection Is Personal +- Question Viz Type +- Question Database ID +- Question Is Native +- Event Timestamp + +### Dashboard cards + +Records of all dashboard cards (including text cards). + +Columns: + +- Entity ID +- Entity Qualified ID +- Dashboard Qualified ID +- Dashboardtab ID +- Card Qualified ID +- Created At +- Updated At +- Visualization Settings +- Parameter Mappings + +### Dashboard subscriptions + +Which subscriptions are active, who created them, who's subscribed to them, when they're sent, and more. + +Columns: + +- Entity ID +- Entity Qualified ID +- Created At +- Updated At +- Creator ID +- Archived +- Dashboard Qualified ID +- Schedule Type +- Schedule Day +- Schedule Hour +- Recipient Type +- Recipients +- Recipient External +- Parameters + +### Databases + +Information about your connected data sources. + +Columns: + +- Entity ID +- Entity Qualified ID +- Created At +- Updated At +- Name +- Description +- Database Type +- Metadata Sync Schedule +- Cache Field Values Schedule +- Timezone +- Is On Demand +- Auto Run Queries +- Cache Ttl +- Creator ID +- Db Version + +### Fields + +All fields from all connected data sources. + +Columns: + +- Entity ID +- Entity Qualified ID +- Created At +- Updated At +- Name +- Display Name +- Description +- Base Type +- Visibility Type +- Fk Target Field ID +- Has Field Values +- Active +- Table ID + +### Group Members + +Metabase group membership + +Columns: + +- User ID +- Group ID +- Group Name + +### Metabot Conversations + +One row per Metabot conversation, with message counts, token totals, owning user/group, source, and tenant. + +Columns: + +- Conversation ID +- Created At +- User ID +- Summary +- User Display Name +- Message Count +- User Message Count +- Assistant Message Count +- Total Tokens +- Prompt Tokens +- Completion Tokens +- Last Message At +- Profile ID +- Profile Name +- Group Name +- Source +- Source Name +- IP Address +- Tenant ID +- Tenant Name +- Model + +### Metabot Messages + +One row per non-deleted Metabot message, with role, profile, tokens, user, and the owning conversation. + +Columns: + +- Message ID +- Conversation ID +- Created At +- Role +- Profile ID +- Total Tokens +- User ID +- Slack Msg ID +- Channel ID + +### People + +Everyone who's ever had an account in your Metabase, including both active and deactivated accounts. + +Columns: + +- User ID +- Entity Qualified ID +- Type +- Email +- First Name +- Last Name +- Full Name +- Date Joined +- Last Login +- Updated At +- Is Admin +- Is Active +- Sso Source +- Locale +- Tenant ID + +### Query log + +Information about all queries Metabase ran across all dashboards + +Columns: + +- Entity ID +- Started At +- Running Time Seconds +- Result Rows +- Is Native +- Query Source +- Error +- User ID +- Card ID +- Card Qualified ID +- Dashboard ID +- Dashboard Qualified ID +- Pulse ID +- Database ID +- Database Qualified ID +- Cache Hit +- Action ID +- Action Qualified ID +- Query +- Embedding Client +- Is Preview +- Embedding SDK Package Version +- Metabase Version +- Auth Method +- Is Sandboxed +- Is Impersonated +- Is Db Routed +- Parameters +- Tenant ID +- Embedding Hostname +- Embedding Path +- User Agent +- Sanitized User Agent +- IP Address + +### System tasks + +Describes the last 14 days of Metabase internal processes tasks + +Columns: + +- ID +- Task +- Status +- Database Qualified ID +- Started At +- Ended At +- Duration Seconds +- Details + +### Tables + +List of all tables across all connected data sources. + +Columns: + +- Entity ID +- Entity Qualified ID +- Created At +- Updated At +- Name +- Display Name +- Description +- Active +- Database ID +- Schema +- Is Upload +- Entity Type +- Visibility Type +- Estimated Row Count +- View Count +- Owner Email +- Owner User ID +- Database ID + +### Task Runs + +Tracks job executions + +Columns: + +- ID +- Run Type +- Entity Type +- Entity ID +- Entity Qualified ID +- Started At +- Ended At +- Duration Seconds +- Status +- Process UUID +- Updated At + +### Tenants + +All tenants in this Metabase instance + +Columns: + +- Tenant ID +- Entity Qualified ID +- Name +- Slug +- Is Active +- Attributes +- Created At +- Updated At +- Tenant Collection ID +- Tenant Collection Qualified ID + +### View log + +Each row describes a question, model, table or dashboard view + +Columns: + +- ID +- Timestamp +- User ID +- Entity Type +- Entity ID +- Entity Qualified ID +- Embedding Client +- Auth Method +- Is Preview +- Metabase Version +- Embedding SDK Package Version +- Tenant ID +- Embedding Hostname +- Embedding Path +- User Agent +- Sanitized User Agent +- IP Address +- Context + +## Categorical column values + +Some columns in the models above hold one of a fixed set of values. + +### Activity log topics + +The Topic column on the [Activity log](#activity-log) model takes one of: + +- action-v2-execute +- alert-create +- alert-delete +- alert-send +- alert-unsubscribe +- alert-update +- api-key-create +- api-key-delete +- api-key-regenerate +- api-key-update +- cache-config-update +- card-create +- card-delete +- card-public-link-created +- card-public-link-deleted +- card-update +- channel-create +- channel-update +- cloud-add-on-purchase +- comment-create +- comment-delete +- comment-update +- create-permission-failure +- custom-viz-plugin-create +- custom-viz-plugin-delete +- custom-viz-plugin-update +- dashboard-add-cards +- dashboard-create +- dashboard-delete +- dashboard-public-link-created +- dashboard-public-link-deleted +- dashboard-remove-cards +- database-create +- database-delete +- database-discard-field-values +- database-manual-scan +- database-manual-sync +- database-update +- document-create +- document-delete +- document-update +- glossary-create +- glossary-delete +- glossary-update +- group-create +- group-delete +- group-membership-create +- group-membership-delete +- group-membership-update +- group-update +- install +- measure-create +- measure-delete +- measure-update +- notification-create +- notification-unsubscribe +- notification-unsubscribe-ex +- notification-unsubscribe-undo-ex +- notification-update +- password-reset-initiated +- password-reset-successful +- remote-sync-create-branch +- remote-sync-export +- remote-sync-import +- remote-sync-settings-update +- remote-sync-stash +- security-advisory-acknowledge +- security-advisory-match +- segment-create +- segment-delete +- segment-update +- setting-update +- subscription-create +- subscription-delete +- subscription-send +- subscription-unsubscribe +- subscription-unsubscribe-undo +- subscription-update +- table-manual-scan +- table-manual-sync +- table-publish +- table-unpublish +- tenant-create +- tenant-update +- transform-create +- transform-delete +- transform-inspect-discover +- transform-inspect-lens +- transform-run-start +- update-permission-failure +- update-transform +- upload-append +- upload-create +- upload-replace +- user-deactivated +- user-invited +- user-joined +- user-reactivated +- user-update +- write-permission-failure + +### Query log query sources + +The Query Source column on the [Query log](#query-log) model takes one of: + +- action +- ad-hoc +- agent +- cache-refresh +- collection +- csv-download +- dashboard +- dashboard-subscription +- embedded-csv-download +- embedded-dashboard +- embedded-json-download +- embedded-question +- embedded-xlsx-download +- json-download +- map-tiles +- public-csv-download +- public-dashboard +- public-json-download +- public-question +- public-xlsx-download +- pulse +- question +- slackbot +- table-grid +- table-rows-sample +- transform-inspector +- xlsx-download + +### Content entity types + +The Entity Type column on the [Content](#content) model takes one of: + +- action +- collection +- dashboard +- document +- event +- glossary +- model +- question +- transform + +### View log entity types + +The Entity Type column on the [View log](#view-log) model takes one of: + +- card +- collection +- dashboard +- table diff --git a/_docs/master/usage-and-performance-tools/usage-analytics.md b/_docs/master/usage-and-performance-tools/usage-analytics.md index e4bec13aee..50601e3bbf 100644 --- a/_docs/master/usage-and-performance-tools/usage-analytics.md +++ b/_docs/master/usage-and-performance-tools/usage-analytics.md @@ -51,9 +51,9 @@ Metabase will take you to the relevant usage dashboard and plug in the item's ID ## How long Metabase keeps usage data -By default, Metabase will keep the data about [activity](#activity-log-model), [views](#view-log-model), and [query execution](#query-log-model) for **720 days**. Twice a day, Metabase will delete rows older than this threshold. You can change this limit by adjusting the environment variable [`MB_AUDIT_MAX_RETENTION_DAYS`](../configuring-metabase/environment-variables#mb_audit_max_retention_days). +By default, Metabase will keep the data about [activity](./usage-analytics-reference#activity-log), [views](./usage-analytics-reference#view-log), and [query execution](./usage-analytics-reference#query-log) for **720 days**. Twice a day, Metabase will delete rows older than this threshold. You can change this limit by adjusting the environment variable [`MB_AUDIT_MAX_RETENTION_DAYS`](../configuring-metabase/environment-variables#mb_audit_max_retention_days). -If you're on the Metabase Open Source Edition, or on the [Metabase Cloud Starter plan](/pricing/), Metabase doesn't collect [Activity](#activity-log-model) and [View](#view-log-model) data. If you upgrade to a Pro or Enterprise plan, either self-hosted or Cloud, you'll only see View and Activity data in Usage Analytics _starting from the time when you upgraded_. +If you're on the Metabase Open Source Edition, or on the [Metabase Cloud Starter plan](/pricing/), Metabase doesn't collect [Activity](./usage-analytics-reference#activity-log) and [View](./usage-analytics-reference#view-log) data. If you upgrade to a Pro or Enterprise plan, either self-hosted or Cloud, you'll only see View and Activity data in Usage Analytics _starting from the time when you upgraded_. ## Creating custom reports @@ -65,358 +65,14 @@ While you _can_ save custom questions, models, and dashboards wherever you like There is one thing to know about the Custom reports collection: its metadata resets whenever Metabase restarts. While you are able to temporarily rename the Custom reports collection, or give it a description or an Official badge, Metabase will drop this collection's metadata when it restarts. But rest assured that Metabase will preserve any questions, models, events, or dashboards that you add to the Custom reports collection. -## Dashboards +## Dashboards and models -The Usage analytics collection includes a set of read-only dashboards. +The Usage analytics collection ships a set of read-only dashboards and models that you can browse from the **collections** sidebar. -### Metabase metrics dashboard +For dashboards and models specifically about Metabot and LLM usage, see [AI usage auditing](../ai/usage-auditing). -General information about people viewing and creating dashboards, questions, subscriptions, and alerts. Cards include: +See also the [Usage analytics reference](./usage-analytics-reference). -- Active users last week -- Question views last week -- Questions created last week -- Dashboards created last week -- Alerts and subscriptions created last week -- Weekly active users -- Question views per week -- Most active users -- Most active creators -- Most viewed dashboards -- Most viewed cards +### Performance overview on MySQL or MariaDB -### Most viewed content dashboard - -View the most relevant content in your Metabase. Cards include: - -- Most viewed dashboards -- Most viewed questions -- Most viewed tables - -### Person overview dashboard - -See what someone's been up to in your Metabase. Cards include: - -- Member of -- Active alerts -- Questions created per month -- Question views per month -- Most viewed dashboards -- Most viewed questions -- Last viewed dashboards -- Last viewed questions -- Last viewed tables -- Recent activity -- Last queries - -### Dashboard overview dashboard - -Information about dashboards, questions, models, and tables. Cards include: - -- Dashboard metadata -- Dashboard views per month -- Question performance -- Most active people on this dashboard -- Questions in this dashboard -- Most active people on this dashboard -- Questions in this dashboard -- Recent activity on dashboard -- Subscriptions on this dashboard - -### Question overview dashboard - -Views, performance, activity, and other data for a particular question. Cards include: - -- Question metadata -- Question views per month -- Question performance -- Most active people on this question -- Dashboards with this question -- Last activity on this question -- Alerts on this question - -### Performance overview dashboard - -Question, dashboard and database performance. Cards include: - -- Slowest dashboards -- Dashboards consuming most resources -- Slowest questions -- Questions consuming the most resources -- Dashboards with more questions in the same tab -- Users consuming the most resources - -> If you're using MySQL or MariaDB as your application database, the Performance overview dashboard won't display results for the cards displaying the 50th and 90th percentile query running times, because MySQL and MariaDB don't support the [Percentile aggregation](../questions/query-builder/expressions-list#percentile). We recommend using PostgreSQL as your application database. - -### Content with cobwebs dashboard - -Dashboards and questions that you could consider archiving. Cards include: - -- Dashboards without recent reviews -- Questions without recent reviews -- Questions that don't belong to a dashboard - -## Models - -The Usage analytics collection includes a bunch of useful models based on Metabase's application database. - -## Activity log model - -Each row of this model describes one event of a particular topic. Fields include: - -- ID -- Topic -- Timestamp -- End Timestamp -- User ID -- Model -- Model ID -- Details - -The topics include: - -- alert-create -- alert-delete -- card-create -- card-delete -- card-update -- dashboard-add-cards -- dashboard-create -- dashboard-delete -- dashboard-remove-cards -- install -- metric-create -- metric-delete -- metric-update -- segment-create -- segment-delete -- segment-update -- setting-update -- subscription-create -- subscription-delete -- user-joined - -## View log model - -Tracks views cards (which includes models), dashboards, and tables. Fields include: - -- ID -- Timestamp -- User ID -- Entity Type (card, dashboard, or table) -- Entity ID -- Entity Qualified ID - -## Query log model - -Information about all queries Metabase ran across all dashboards. Fields include: - -- Entity ID -- Started At -- Running Time Seconds -- Result Rows -- Is Native -- Query Source -- Error -- User ID -- Card ID -- Card Qualified ID -- Dashboard ID -- Dashboard Qualified ID -- Pulse ID -- Database ID -- Database Qualified ID -- Cache Hit -- Action ID - -Query sources include: - -- action -- ad-hoc -- collection -- csv-download -- dashboard -- embedded-dashboard -- embedded-csv-download -- embedded-json-download -- embedded-question -- embedded-xlsx-download -- json-download -- map-tiles -- metabot (experimental) -- public-dashboard -- public-question -- pulse (which includes dashboard subscriptions and alerts) -- question -- xlsx-download - -## Alerts model - -All alerts, both active and archived. - -- Entity ID -- Entity Qualified ID -- Created At -- Updated At -- Creator ID -- Card ID -- Card Qualified ID -- Alert Condition -- Schedule Type -- Schedule Day -- Schedule Hour -- Archived -- Recipient Type -- Recipients -- Recipient External - -### Content model - -Questions, dashboards, models, events, and collections. - -- Entity ID -- Entity Qualified ID -- Entity Type -- Created At -- Updated At -- Creator ID -- Name -- Description -- Collection ID -- Made Public By User -- Is Embedding Enabled -- Archived -- Action Type -- Action Model ID -- Collection Is Official -- Collection Is Personal -- Question Viz Type -- Question Database ID -- Question Is Native -- Event Timestamp - -Entity types include: - -- action -- collection -- dashboard -- event -- model -- question - -## People model - -Everyone in your Metabase, including deactivated accounts. Fields include: - -- User ID -- Email -- First Name -- Last Name -- Full Name -- Date Joined -- Last Login -- Updated At -- Is Admin -- Is Active -- SSO Source -- Locale - -## Dashboard subscriptions model - -Which subscriptions are active, who created them, who's subscribed to them, when they're sent, and more. - -- Entity ID -- Entity Qualified ID -- Created At -- Updated At -- Creator ID -- Archived -- Dashboard Qualified ID -- Schedule Type -- Schedule Day -- Schedule Hour -- Recipient Type -- Recipients -- Recipient External -- Parameters - -## Dashboard cards model - -Each row is a dashboard card: either a question card or a text card. Fields include: - -- ID -- Dashboard ID -- Dashboardtab ID -- Question ID -- Created At -- Updated At -- Size X -- Size Y -- Visualization Settings -- Parameter Mappings - -## Databases model - -Information about your connected data sources. Fields include: - -- Entity ID -- Entity Qualified ID -- Created At -- Updated At -- Name -- Description -- Database Type -- Metadata Sync Schedule -- Cache Field Values Schedule -- Timezone -- Is On Demand -- Auto Run Queries -- Cache Ttl -- Creator ID -- Db Version - -## Tables model - -List of all tables across all connected data sources. Fields include: - -- Entity ID -- Entity Qualified ID -- Created At -- Updated At -- Name -- Display Name -- Description -- Active -- Database ID -- Schema -- Is Upload - -## Fields model - -All fields from all connected data sources. Fields include: - -- Entity ID -- Entity Qualified ID -- Created At -- Updated At -- Name -- Display Name -- Description -- Base Type -- Visibility Type -- Fk Target Field ID -- Has Field Values -- Active -- Table ID - -## System tasks model - -Describes the last 14 days of Metabase internal processes tasks. - -- ID -- Task -- Database Qualified ID -- Started At -- Ended At -- Duration Seconds -- Details +If you're using MySQL or MariaDB as your application database, the Performance overview dashboard won't display results for the cards showing 50th and 90th percentile query running times, because MySQL and MariaDB don't support the [Percentile aggregation](../questions/query-builder/expressions-list#percentile). We recommend using PostgreSQL as your application database. diff --git a/_site/docs/master/CONTRIBUTING.html b/_site/docs/master/CONTRIBUTING.html index f724909d6e..236456f68a 100644 --- a/_site/docs/master/CONTRIBUTING.html +++ b/_site/docs/master/CONTRIBUTING.html @@ -113,61 +113,193 @@ + + + - - - - - - - - - + - + + + + + + + + + + + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - + - - + @@ -187,21 +319,21 @@ - +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Source nameWhere it comes from
    MetabotThe Metabot chat sidebar inside Metabase.
    DocumentsContent generation inside Documents.
    Suggested PromptsBackground generation of suggested prompts.
    SlackbotConversations that started in Slack.
    SQLInline SQL editing in the native editor.
    UnknownA conversation Metabase couldn’t classify (distinct from no-source conversations, which appear as (empty) on charts).
    + +

    Profiles

    + +

    A profile is the configuration Metabot uses for a conversation: which prompt, which tools, and what it’s allowed to do. The Conversations admin page, the By profile chart in Stats, and the Metabot Conversations model (see Building custom reports) all show the human-readable profile name. The AI Usage Log model exposes the raw profile_id instead (e.g. internal, transforms_codegen, embedding_next).

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    ProfileWhat it does
    InternalThe default Metabot in the chat sidebar. Can build query-builder questions and write SQL.
    NLQNatural-language querying only. Always returns a query builder result, never SQL.
    SQLSQL writing only. Used by inline SQL editing and similar surfaces.
    SlackbotThe persona behind Metabot in Slack.
    EmbeddingThe Metabot persona used inside embedded Metabase.
    Transforms codegenGenerates transform, SQL, or Python.
    DocumentsGenerates content inside Documents.
    + +

    Conversations

    + +

    Admin > AI > Usage auditing > Conversations

    + +

    The Conversations page lists every Metabot conversation Metabase has on file, newest first.

    + +

    Filters

    + + + +

    Columns

    + +

    Each row shows:

    + +
      +
    • User: who started the conversation.
    • +
    • Profile: which Metabot persona answered.
    • +
    • Date: when the conversation started.
    • +
    • Messages: total messages, including both sides.
    • +
    • Tokens: total LLM tokens spent.
    • +
    • Queries: how many queries (SQL or query-builder) Metabot generated during the conversation.
    • +
    • Searches: how many search-tool calls Metabot made.
    • +
    • IP: the IP address the request came from.
    • +
    + +

    You can sort by Date, Messages, or Tokens. Click any row to open the conversation detail.

    + +

    Conversation detail

    + +

    The detail view is a full audit of a single conversation. It includes:

    + +
      +
    • Header: start date, the person who chatted with Metabot, the profile Metabot used, the person’s groups (including whether they’re an admin), and tenant if applicable. From the menu next to the person’s name you can jump to all of their conversations, or to their account details.
    • +
    • Stat tiles: Messages, Total tokens, Queries run, Searches.
    • +
    • Feedback (if any): thumbs-up or thumbs-down and comments. The agent response that triggered the feedback is shown alongside.
    • +
    • Conversation transcript: the full message-by-message exchange. Tool calls (search calls, query construction, etc.) are inlined. You can click “View” to open a modal with the info.
    • +
    • Queries generated: every SQL or query builder (MBQL) query Metabot wrote during the conversation, with the referenced tables listed underneath. Hit Visit on a query to open the item in a new tab and run it yourself. Transform code-gen queries are shown read-only and can’t be re-run from here.
    • +
    + +

    The /inspect shortcut

    + +

    If you’re an admin chatting with Metabot, type /inspect in the chat to jump straight from the current conversation to its detail page in Usage auditing.

    + +

    Building custom reports

    + +

    Three Usage Analytics models back the Usage auditing pages.

    + + + +

    Save your custom questions in the Custom reports sub-collection so the reports inherit the right permissions.

    + +

    What isn’t tracked

    + +

    MCP activity isn’t included in Usage auditing. MCP requests don’t go through Metabot’s conversation pipeline, so they don’t generate conversations or token rows.

    + +

    Further reading

    + + + + +
    +
    + +

    + Read docs for other versions of Metabase. +

    + +
    + + +
    + +
    +
    +
    Was this helpful?
    + + +
    + +
    +

    + +
    + + + +
    +
    + +
    +
    Thanks for your feedback!
    +
    + + + + Want to improve these docs? Propose a change. + + +
    + + + +
    + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/_site/docs/master/ai/usage-controls.html b/_site/docs/master/ai/usage-controls.html new file mode 100644 index 0000000000..40fd154839 --- /dev/null +++ b/_site/docs/master/ai/usage-controls.html @@ -0,0 +1,2506 @@ + + + + + + + + + + + + + + + + + + + + + + +AI usage controls | Metabase Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + + + + +
    + + + + +
    +
    + + + +
    +
    +
    + +
    + + + + + + + + + +
    + + + +
    + + +
    + +
    + +
    + + + +
    + + + master + + + + + + + + +
    + + + + + What’s new + + + + + +
    + + + + +
    +
    + + +
    + + +
    + + +
    + These are the docs for the Metabase master branch. Some features documented here may not yet be available in the current release. + Check out the docs for the current stable version, Metabase v0.61. +
    + + +
    + + +

    AI usage controls

    + +
    +
    + + + + + + + + + + + +

    + AI controls are only available on + Pro and + Enterprise + plans (both self-hosted and on Metabase Cloud). +

    +
    +
    + +

    Admin > AI > Usage controls

    + +

    Once you’ve connected an AI provider (see AI settings), you can can control who can use Metabot and set usage budgets.

    + + + +

    AI feature access

    + +

    Admin > AI > Usage controls > AI feature access

    + +

    The AI feature access table lets you toggle Metabot on or off per group, and pick what Metabot can do for each group. Rows are your internal groups and tenant groups; columns are Metabot capabilities.

    + +
      +
    • AI features — the master toggle for the group. When off, people in that group won’t see the Metabot icon, keyboard shortcuts, or any inline AI affordances.
    • +
    • Chat and NLQ — access to the Metabot chat sidebar and natural language querying.
    • +
    • SQL generation — permission to have Metabot write or edit SQL (from the sidebar or inline).
    • +
    • Other tools — other AI tools like error-fixing and chart analysis.
    • +
    + +

    These controls are granular. If you uncheck SQL generation but leave Chat and NLQ checked, Metabot will try to answer SQL-shaped prompts with a query builder result.

    + +

    Tenant groups follow the same model as regular groups.

    + +

    AI usage limits

    + +

    Admin > AI > Usage controls > AI usage limits

    + +

    AI usage limits

    + +

    By default, AI usage is unlimited.

    + +

    These limits let you cap how much Metabot traffic Metabase allows — either across your whole instance, or for people in specific groups.

    + +

    Settings and general limits

    + +
      +
    • How do you want to limit AI usage? Choose between: +
        +
      • By token usage in millions of tokens, so 2 would be 2 million tokens.
      • +
      • By message count. Each message someone sends to Metabot counts as one message (not a conversation, but a single message).
      • +
      +
    • +
    • When should usage limits reset? The counter resets automatically; the limit values stay put. Pick from: +
        +
      • Daily (resets at midnight).
      • +
      • Weekly (resets on Monday).
      • +
      • Monthly (resets the 1st).
      • +
      +
    • +
    + +

    You can also set:

    + +
      +
    • Total instance limit: the total pool of tokens or messages across every person and group. Once this limit is hit, Metabot stops responding to requests until the next reset.
    • +
    • Quota-reached message: the error Metabot shows when someone hits a limit. Write whatever makes sense for your Metabase (like a Slack channel to ping, or a link to a request form).
    • +
    + +

    Group limits

    + +

    Group limits set a per-_person_ cap for everyone in a user group. So, each person in the group gets the limit, not the group as a whole.

    + +

    If a person belongs to multiple groups, Metabase gives them the highest limit across those groups (not the cumulative number across all of their groups). So if someone is in two groups, one group capped to 100 messages per week, and another group capped to 500, that person would enjoy 500 per week (not 600).

    + +

    Tenant group limits

    + +

    You can set a limit for each tenant group. They work just like the group limits described above.

    + +

    Specific tenant limits

    + +

    This specific tenant limit is an aggregate pool shared by everyone in a single tenant. When the pool is empty, no one in that tenant can use Metabot for the rest of the period, regardless of how generous their tenant-group limits are.

    + +

    Per-tenant limits are handy for billing scenarios. Say you have a customer, Megafauna Analytics, who pays you for 100 million tokens a month. Set Megafauna Analytics’s tenant limit to 100, and Metabase enforces that cap across every seat they provision.

    + +

    Further reading

    + + + + +
    +
    + +

    + Read docs for other versions of Metabase. +

    + +
    +
    + +
    + +
    +
    +
    Was this helpful?
    + + +
    + +
    +

    + +
    + + + +
    +
    + +
    +
    Thanks for your feedback!
    +
    + + + + Want to improve these docs? Propose a change. + + +
    + + + +
    +
    +
    +
    + + + + + + + + + + + + + + + +
    + + +
    + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/_site/docs/master/api.html b/_site/docs/master/api.html index 094baf6def..90fb6898f8 100644 --- a/_site/docs/master/api.html +++ b/_site/docs/master/api.html @@ -113,54 +113,187 @@ + + + - - - - - - - + - + + + + + + + + + + + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - + - -