Skip to main content

GPLv3 License

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.plan and 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)

Source distribution for spark-metabase-api 0.3.0
File Size Uploaded
spark_metabase_api-0.3.0.tar.gz 34.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for spark-metabase-api 0.3.0
File Interpreter ABI Platform
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

Release history Release notifications | RSS feed

This release

0.3.0 This release

2 release files

0.2.0

2 release files

0.1.12

2 release files

0.1.11

2 release files

0.1.10

2 release files

0.1.9

2 release files

0.1.8

2 release files

0.1.7

2 release files

0.1.6

2 release files

0.1.5

2 release files

0.1.4

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page