Skip to main content

A Python wrapper for the Metabase API developed by the ⭐️ Spark Tech team

Project description

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

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

spark_metabase_api-0.3.0.tar.gz (34.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

spark_metabase_api-0.3.0-py3-none-any.whl (35.4 kB view details)

Uploaded Python 3

File details

Details for the file spark_metabase_api-0.3.0.tar.gz.

File metadata

  • Download URL: spark_metabase_api-0.3.0.tar.gz
  • Upload date:
  • Size: 34.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.4

File hashes

Hashes for spark_metabase_api-0.3.0.tar.gz
Algorithm Hash digest
SHA256 c904d965ca19918b4a24f03928c7f05b71841b9008f1dd52130a05b84843c740
MD5 3471697f7d2732ba8c4c03e405538cef
BLAKE2b-256 55e7b76488b7f85f769a8833559687a26b610790f82e8491798f8eb05f8703bc

See more details on using hashes here.

File details

Details for the file spark_metabase_api-0.3.0-py3-none-any.whl.

File metadata

File hashes

Hashes for spark_metabase_api-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 6d886d4183b6d6ff8736ee6974815a8e25d358eb0b7f7bc7b4d3dff40ba7f035
MD5 b346e2474cb2b8109901eca59d904cbb
BLAKE2b-256 5cbc478cb737e82cee69c5f00cf7af1a055c9d4b946a757ad0f478fda6e5f1a2

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page