Spark Metabase API
A Python wrapper for the Metabase API, developed by the Spark Tech team ⭐️
Installation
pip install spark-metabase-api
# Optional YAML support for the Infrastructure-as-Code module:
pip install "spark-metabase-api[iac]"
Quick start
from spark_metabase_api import Metabase_API
mb = Metabase_API(
domain="https://metabase.example.com",
email="me@example.com",
password="hunter2",
)
mb.copy_dashboard(source_dashboard_id=42, destination_collection_name="Acme")
Infrastructure-as-Code
Define a Metabase collection tree in YAML, version it in git, and apply it idempotently with a Terraform-style diff.
# Pull the live state for an existing collection
spark-metabase --domain "$MB_URL" --email "$MB_USER" --password "$MB_PASS" \
export "Acme Customer" specs/acme.yaml
# Show what would change after editing the spec
spark-metabase plan specs/acme.yaml
# Apply (with confirmation prompt unless --yes)
spark-metabase apply specs/acme.yaml
Example spec:
name: "Acme Customer"
description: "Customer-facing dashboards"
authority_level: official
collections:
- name: "Questions"
cards:
- name: "Daily revenue"
definition:
dataset_query:
type: native
database: 2
native:
query: "SELECT day, sum(amount) FROM sales GROUP BY 1"
display: line
visualization_settings: {}
dashboards:
- name: "Acme Dashboard"
description: "Top-level KPIs"
parameters: []
dashcards: [] # populated automatically by `export`
The Python API is also exposed:
from spark_metabase_api import Metabase_API, iac
mb = Metabase_API(domain=..., session_id=...)
# Export to YAML
spec = iac.export(mb, "Acme Customer")
iac.dump(spec, "specs/acme.yaml")
# Edit the file in git, then in CI:
spec = iac.load("specs/acme.yaml")
print(iac.plan(mb, spec).render())
iac.apply(mb, spec)
Natural keys & renames
Items are identified by (parent_path, kind, name) within the spec. Renaming
an item is therefore a destructive change (delete + create). To bind a spec
entry to a specific live item across renames, set entity_id (Metabase's
stable nanoid, available since v0.46) on the entry.
Forward references in dashcards
A dashcard can reference a card created by the same spec via
card_name: "<name>" instead of card_id. The applier looks the name up in
the cards present (or just created) inside the same collection and rewrites
the dashcard with the real id.
Natural-language dashboard authoring
pip install "spark-metabase-api[chatbot]"
Describe what you want; Claude inspects the live Metabase via read-only tools
(list_databases, list_tables, describe_table, search_metabase,
find_cards_using_table) and emits a CollectionSpec:
from spark_metabase_api import Metabase_API, iac
from spark_metabase_api.chatbot import chat
mb = Metabase_API(domain=..., session_id=...)
spec = chat(mb, "Build an Acme dashboard with monthly revenue and top accounts")
print(iac.plan(mb, spec).render())
iac.apply(mb, spec)
For UIs (Streamlit, Slack, etc.) use the streaming generator:
from spark_metabase_api.chatbot import stream
for event_type, payload in stream(mb, "..."):
if event_type == "text": render_assistant_text(payload)
elif event_type == "tool_call": render_tool_call(payload) # {name, input}
elif event_type == "tool_result": render_tool_result(payload) # {name, input, result}
elif event_type == "proposed": save_spec(payload) # CollectionSpec dict
Powered by Claude Opus 4.7 with adaptive thinking; the model needs an
ANTHROPIC_API_KEY environment variable.
Streamlit frontend
A single-file Streamlit app that wires the chatbot to a chat UI with live tool-call rendering, plan diffing, and an Apply button.
pip install "spark-metabase-api[streamlit]"
streamlit run streamlit_app.py
The app:
- collects Metabase + Anthropic credentials in the sidebar,
- streams Claude's progress (text, tool calls, expandable tool results) as the agent works,
- renders the proposed spec as YAML,
- previews the diff via
iac.planand applies it on demand.
Integration tests
A standalone script exercises the package against a live Metabase instance, in four phases with a sandboxed write area that's archived on exit:
python tests/integration_test.py \
--domain "$MB_URL" --email "$MB_USER" --password "$MB_PASS" \
--collection "My Reports" \
--source-dashboard-id 42 \
--chatbot
Phase 1 is fully read-only. Phase 2 creates a uniquely-named throwaway
collection, applies a tiny spec, exercises add_card_to_dashboard and
copy_dashboard(deepcopy=True), then archives the sandbox in a finally
block (use --keep-sandbox to keep it around for manual inspection).
Phase 3 (opt-in via --chatbot) runs the Claude agent but does not
apply the spec it proposes.
Acknowledgements
Release files for spark-metabase-api 0.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| spark_metabase_api-0.3.0.tar.gz | 34.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| spark_metabase_api-0.3.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 69.6 kB
Release files / spark_metabase_api-0.3.0.tar.gz
| Download URL | spark_metabase_api-0.3.0.tar.gz |
|---|---|
| Size | 34.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
c904d965ca19918b4a24f03928c7f05b71841b9008f1dd52130a05b84843c740
|
|
BLAKE2b-256 checksum How to use checksums |
55e7b76488b7f85f769a8833559687a26b610790f82e8491798f8eb05f8703bc
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.4
|
Release files / spark_metabase_api-0.3.0-py3-none-any.whl
| Download URL | spark_metabase_api-0.3.0-py3-none-any.whl |
|---|---|
| Size | 35.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
6d886d4183b6d6ff8736ee6974815a8e25d358eb0b7f7bc7b4d3dff40ba7f035
|
|
BLAKE2b-256 checksum How to use checksums |
5cbc478cb737e82cee69c5f00cf7af1a055c9d4b946a757ad0f478fda6e5f1a2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.4
|