--- name: metabase_create_card kind: function lang: py domain: infra version: "1.0.0" purity: impure signature: "def metabase_create_card(client: MetabaseClient, name: str, dataset_query: dict, display: str = 'table', collection_id: int = 0, description: str = '') -> dict" description: "Crea una card/pregunta en Metabase con query SQL nativa o MBQL. Endpoint: POST /api/card." tags: [metabase, card, question, create, api, python] uses_functions: [] uses_types: [] returns: [] returns_optional: false error_type: "error_go_core" imports: [httpx] params: - name: client desc: "instancia autenticada de MetabaseClient" - name: name desc: "nombre descriptivo de la pregunta/card" - name: dataset_query desc: "dict con configuración de query (SQL nativa o MBQL)" - name: display desc: "tipo de visualización (table, scalar, bar, etc.)" - name: collection_id desc: "ID de colección donde guardar la card (0=root)" - name: description desc: "descripción opcional de la card" output: "dict: objeto card creado con id y toda su configuración" tested: false tests: [] test_file_path: "" file_path: "python/functions/metabase/cards.py" --- ## Ejemplo ```python card = metabase_create_card(client, "Revenue", { "database": 1, "type": "native", "native": {"query": "SELECT SUM(total) FROM orders"}, }, display="scalar") ``` ## Ejemplo con template-tags (filtros) ```python card = metabase_create_card(client, "Revenue filtrable", { "database": 6, "type": "native", "native": { "query": "SELECT * FROM orders WHERE 1=1 [[AND date >= {{fecha_desde}}]]", "template-tags": { "fecha_desde": { "name": "fecha_desde", "display-name": "Fecha desde", "id": "fecha_desde_tag", "type": "text" } } }, }, display="table") ``` ## Formato dataset_query — IMPORTANTE Hay DOS formatos y hay que saber cuál usar: **Para CREAR cards (POST /api/card) — formato legacy:** ```python {"database": id, "type": "native", "native": {"query": "SELECT ..."}} ``` **Lo que DEVUELVE Metabase al LEER cards (GET /api/card/:id) — formato MBQL5:** ```python {"lib/type": "mbql/query", "database": id, "stages": [{"lib/type": "mbql.stage/native", "native": "SELECT ..."}]} ``` Son representaciones distintas de lo mismo. Al leer una card existente y querer extraer el SQL: ```python card = metabase_get_card(client, 42) ds = card["dataset_query"] # Formato MBQL5 (Metabase reciente) stages = ds.get("stages", []) if stages: sql = stages[0].get("native", "") # Formato legacy else: sql = ds.get("native", {}).get("query", "") ``` Al crear/actualizar cards, usar SIEMPRE el formato legacy — Metabase lo acepta y lo convierte internamente. ## Notas - `display` válidos: scalar, table, line, bar, pie, area, row, funnel, combo, pivot, map, scatter, waterfall, gauge, progress, smartscalar, sankey. - Para queries que se repiten como base de otras cards, considerar crear un "model" (type="model") y referenciar desde otras cards con `source-table: "card__"`.