Repository navigation
Description
[SIP] Proposal for extension APIs to export chart and dashboard data
Note: This is an approved feature as a part of the UTSC 2026 Fall batch - Slack Work Item
Status: in progress. The core changes are open as #45991 (backend) and #46014 (frontend). The first extension built on them, chart export to Google Sheets, is in review at orion222/superset-google-sheets. Dashboard export is next.
Motivation
Business users often want the numbers behind a chart or dashboard in a spreadsheet, to annotate, model or share them. Today that takes an Export to .CSV or Excel download followed by a manual upload to Google Drive.
The sqllab-gsheets extension already sends SQL Lab results straight to a new Google Sheet. Bringing the same workflow to charts and dashboards is blocked by two gaps in the extension framework:
- Backend:
superset_corecan run raw SQL (Database.execute, feat: SQL execution API for Superset #36529), but it can't run a chart's query context or walk a dashboard's charts. That logic exists only inside Superset:ChartDataCommandbehind/api/v1/chart/data, and the per-chart loop of the dashboard Excel export. Extensions must not import Superset internals. - Frontend:
- Extensions can contribute menu items only to SQL Lab panels, so they can't add an action to a chart's or dashboard's Download menu.
- Even if they could, the click would carry no context, so the extension wouldn't know which query or filters to export.
- Extensions also have no way to show Superset's toasts.
This SIP proposes small, general extension APIs that close both gaps. Nothing in Superset becomes Google-specific; Google Sheets is simply the first consumer.
Proposed Change
Backend: superset_core.exports (#45991)
A new package in superset-core. Its types and stubs are replaced with Superset's implementations at startup (core_api_injection.py), the same mechanism queries and tasks use, so Celery workers get them too.
| Function | Purpose |
|---|---|
run_query_context(payload) |
Runs a chart query context the way /api/v1/chart/data does (validation, raise_for_access, client-side post-processing) and returns JSON rows. Same rows as Export to .CSV. |
iter_dashboard_chart_results(dashboard_id, active_data_mask) |
Yields one result per chart in layout order, with the dashboard's filters applied. A failed chart is reported with a reason, not raised. |
describe_dashboard_export(dashboard_id, active_data_mask) |
Title, a permalink for the exported filter state, the applied native filters and Explore links. Can be dropped if reviewers prefer. |
build_tab_name(raw, used, max_len) |
Valid, unique tab names (the existing Excel sheet-name helper, with the length as a parameter). |
can_export_data(), can_export_dashboard(dashboard_id) |
The same export-permission checks the chart data API and the dashboard Excel export apply. |
as_user(user_id) |
Runs background work as the requesting user. Task workers don't set g.user, and extensions can't import override_user. |
The dashboard Excel export is refactored onto the same per-chart helper, so both exports share one path for query resolution, filtering and access checks. Its output doesn't change.
Frontend: download-menu locations and a toasts API (#46014)
- Eight menu locations, one per download menu that offers "Export to Excel":
- Explore's Export All Data (plus a pivoted entry);
- the standalone/embedded download control;
- the dashboard chart Download menu (plus a pivoted entry);
- Drill to Detail;
- Drill By;
- the dashboard header Download menu.
- Context on click:
- Chart locations pass
{ getPayload, chartName, canDownload }.getPayload()builds, at click time, the query context the CSV export would post. - The dashboard location passes
{ dashboardId, dashboardTitle, activeDataMask, canDownload }.
- Chart locations pass
- Unchanged without extensions: with no extension installed, every menu looks exactly as it does today.
- Toasts: a
toastsnamespace in@apache-superset/core(addSuccessToast,addDangerToast, …, plusremoveToast), backed by Superset's existing toast store, with an optional link button.
First consumer: Google Sheets export (orion222/superset-google-sheets)
An evolution of sqllab-gsheets:
- "Export to Google Sheets" in every chart download menu, using the same rows as Export to .CSV, typed cells and one tab per query.
- Files are created in a Shared Drive and shared with the user.
- It also tightens the SQL Lab export's permission check:
can_export_data()instead ofread. - Dashboard export, one spreadsheet with a tab per chart run as a background task, is the next phase.
New or Changed Public Interfaces
- Python (
apache-superset-core):- new package
superset_core.exports: the functions above, plus the frozen dataclassesChartQueryResult,ChartResult,AppliedFilter,DashboardExportInfo, and the enumsGenericDataTypeandSkipReason; - IDs are integers, matching the existing
superset_coreDAOs and the dashboard export endpoint.
- new package
- TypeScript (
@apache-superset/core):- new
toastsnamespace; - new menu location types
ChartDownloadLocationandDashboardDownloadLocation, and the context typesChartDownloadContextandDashboardDownloadContext.
- new
- No REST endpoint, model or permission changes in Superset. No path returns data a user couldn't already get from
/api/v1/chart/data. - Docs:
extensions/exports.md,extension-points/download-menus.mdandextensions/toasts.md.
New dependencies
None in Superset. The Google Sheets extension depends on google-api-python-client and google-auth (Apache-2.0, maintained by Google), installed only with the extension.
Migration Plan and Compatibility
- No database migrations or URL changes.
- The changes are additive. Existing menus, exports and extensions keep working unchanged.
- The Excel dashboard export produces identical workbooks before and after the refactor.
Rejected Alternatives
- Google Sheets support built into Superset: an integration with one vendor; the extension framework is the intended place for it.
- An extension calling Superset internals directly: fragile across releases, and against the extension model.
- An extension calling
/api/v1/chart/dataover HTTP from its backend: wouldn't run as the requesting user inside background tasks, and duplicates request handling. - A per-surface API instead of shared menu locations: seven menus would each need their own extension hook. One location scheme and one hook cover them all.
- Push status updates over websocket for long exports: they need the optional
superset-websocketsidecar. Polling the existing task status API is enough for now.
Metadata
Metadata
Assignees
Labels
Type
Projects
- StatusShow more project fieldsPre-discussion
Activity
orion222 commentedon Nov 4, 2026
I split this issue into a frontend and backend PR, if you guys would like it as one I'm happy to do that too.
[-][SIP] Extension APIs for exporting chart and dashboard data (Google Sheets export)[/-][+][SIP-238] Extension APIs for exporting chart and dashboard data (Google Sheets export)[/+]