Chart Data API (v1)#
Overview#
The v1 chart data API (/api/v1/chart/data) is Superset's unified query endpoint that replaces the deprecated /superset/explore_json/ endpoint and superset/viz.py pipeline. All chart plugins communicate with the backend exclusively through this endpoint. The migration of all legacy NVD3/legacy charts to v1 was completed as part of a coordinated effort , culminating in the removal of the entire legacy pipeline .
Architecture#
Request: QueryContext#
The frontend constructs a QueryContext and POSTs it to /api/v1/chart/data. Each chart plugin's buildQuery.ts file is responsible for this construction, using the buildQueryContext helper from @superset-ui/core. A QueryContext contains one or more QueryObject items, allowing a single chart to issue multiple queries in parallel.
Key fields in a QueryObject:
is_timeseries— enables time-grain bucketingmetrics— list of metrics to computegroupby— dimension columnstime_range,granularity— extracted viaextractExtras()from form datapost_processing— optional server-side pandas pipeline steps (pivot, resample, rolling, etc.)
Response#
The backend returns an array of query result objects, each containing a data array of flat records (one object per row). This is distinct from the legacy format, which could return pre-shaped nested structures.
Plugin Wiring#
Each chart plugin wires together three pieces :
buildQuery.ts— constructs theQueryContext; absence of this file (and presence ofuseLegacyApi: truein metadata) was the signal that a plugin used the old pathtransformProps.ts— converts flat query results + form data into renderer-ready propscontrolPanel.tsx— declares chart editor UI controls
Legacy Migration#
Scope#
PR #41714 coordinated migration of 15 legacy charts, then removed viz.py (~2,000 lines) and the explore_json endpoints entirely . A follow-on PR renamed legacy-plugin-chart-* packages to drop the legacy- prefix .
Migration Strategies#
Four approaches were used depending on chart complexity:
1. In-Place Conversion (most charts)#
The most common pattern, used for Parallel Coordinates , Country Map , Bullet , Chord , World Map , Paired t-test , Horizon , Time Table , Partition , and Time-series Period Pivot :
- Add
buildQuery.tsmirroring the legacyviz.pyquery_obj()method - Port
get_data()reshape logic to a frontendtransformData.ts/transformProps.ts - Remove
useLegacyApi: truefrom plugin metadata - Wire
loadBuildQueryinindex.ts - No database migration —
viz_typekeys remain unchanged, so saved charts continue working
2. Server-Side Post-Processing (Rose chart)#
For charts requiring pandas semantics that are hard to replicate in JS, buildQuery.ts attaches a post_processing pipeline to the query object . The server executes the pipeline (pivot → resample → rolling → compare → contribution → flatten) and returns shaped data, keeping the frontend transformation simple.
3. Retargeting to ECharts (Bubble)#
Charts with mature ECharts equivalents are redirected via Alembic database migration . The saved viz_type is rewritten (e.g., bubble → bubble_v2), and form_data_bak is stored for rollback.
4. Client-Side Resolution (DeckGL Multi-Layer)#
The DeckGL Multiple Layers chart issues an empty queries context from its own buildQuery and lets each layer load independently through its own registered buildQuery/transformProps pair .
Case Study: time_pivot Migration#
The Time-series Period Pivot chart (time_pivot, NVD3-based) illustrates the in-place conversion pattern in detail :
buildQuery.ts — Issues a single is_timeseries: true query with one metric, mirroring the legacy NVD3TimePivotViz.query_obj().
transformData.ts — Ports the backend reshape logic entirely to the frontend:
- A
rollback()function implements pandas-compatible offset semantics for frequency aliases (AS/A,QS/Q,MS/M,W/W-XXX,D,H,T/MIN) to bucket timestamps into period starts. transformData()filters byDTTM_ALIAS, buckets timestamps, ranks periods most-recent-first (current,-1,-2, …), and shifts older period data onto the latest period's time axis for visual overlap comparison.
transformProps.ts — Detects v1 (flat array) vs. legacy (pre-shaped) payload: flat records go through transformData(), while legacy payloads pass through untouched (backward compatibility).
index.ts changes: removed useLegacyApi: true, added loadBuildQuery, swapped to local transformProps, removed the Legacy metadata tag.
Key Source Files#
| File | Purpose |
|---|---|
superset/charts/api.py | Backend v1 chart data API — POST /api/v1/chart/data handler |
superset-frontend/packages/superset-ui-core/src/query/buildQueryContext.ts | buildQueryContext helper — assembles QueryContext from form data |
legacy-plugin-chart-nvd3/src/TimePivot/buildQuery.ts | Example buildQuery.ts from time_pivot migration |
legacy-plugin-chart-nvd3/src/TimePivot/transformData.ts | Frontend port of get_data() / period-pivot reshape logic |
superset-frontend/src/visualizations/presets/MainPreset.js | Plugin registry — all chart types registered here |
References#
- PR #41714 — chore(viz): remove legacy explore_json + viz.py pipeline
- PR #41727 — feat(time-pivot): migrate time_pivot chart to v1 chart data API
- PR #41750 — chore(viz)!: remove explore_json endpoints, viz.py and the legacy chart data pipeline
- PR #41751 — chore(viz): drop the legacy- prefix from migrated chart plugin packages