mcpField
C
card-creation

card-creation

github.com/stahuraData & databases24177 installsUpdated 26w ago
Repository

About card-creation

A reference skill for creating, reading, and updating Domo KPI cards programmatically. It is aimed at people building card-management workflows with community-domo-cli, and includes card schemas, column mappings, formulas, and chart-type guidance.

Key features

  1. 01Card create, read, and update guidance
  2. 02Complete card body schema
  3. 03Column mappings and aggregations
  4. 04Beast Mode formula references
  5. 05Chart type and override guidance

Use cases

  1. 01Building a KPI card from a dataset
  2. 02Updating a card while preserving its fields
  3. 03Choosing chart columns and aggregations

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/stahura/domo-ai-vibe-rules --skill card-creation

After installing, type/card-creationin Claude Code to confirm it loaded.

Bundled files

References and scripts installed along with SKILL.md.

README.md
references/
area.md
bar.md
barline.md
data-science.md
examples.md
gauge.md
line.md
map.md
period-over-period.md
pie.md
selector.md
small-charts.md
specialty.md
statistical.md
table.md

Details

From the project README

Domo Card CRUD Reference

CLI vs raw API: All card operations use the community-domo-cli. No raw curl/fetch needed. The CLI wraps the Domo Product API endpoints and handles auth automatically.

Complete reference for programmatic KPI card management. 207 chart types documented with override data. 206/207 confirmed working (only badge_line fails).


1. CRUD Operations

Create a Card
community-domo-cli --output json -y cards create \
  --body-file card.json --page-id $PAGE_ID > card_response.json

CARD_ID=$(python3 -c "import json; print(json.load(open('card_response.json'))['id'])")

--page-id is required for creation.

Read a Card Definition
community-domo-cli --output json cards definition $CARD_ID > card_def.json

Returns definition, dataSourceWrite, drillpath, columns. See Gotchas for read/write format mismatches.

Update a Card
community-domo-cli --output json -y cards update $CARD_ID \
  --body-file card_updated.json

Full body replacement — include ALL fields, not just changed ones. Always read first, modify, write back.

Copy a Card (raw API — no CLI command)
curl -X POST "https://$INSTANCE/api/content/v1/cards/$CARD_ID/copy" \
  -H "x-domo-developer-token: $TOKEN" -H "Content-Type: application/json" -d '{}'
Delete a Card (raw API — no CLI command)
curl -X DELETE "https://$INSTANCE/api/content/v1/cards/$CARD_ID" \
  -H "x-domo-developer-token: $TOKEN"

Permanent, cannot be undone.

Supporting Operations
# Discover dataset columns before creating cards
community-domo-cli --output json datasets schema $DATASET_ID > schema.json

# List cards on a page
community-domo-cli --output json pages list-cards $PAGE_ID

# Add an existing card to another page (goes to appendix)
community-domo-cli -y pages add-card $PAGE_ID $CARD_ID

# Create a beast mode / variable
community-domo-cli --output json -y beast-modes create --body-file beastmode.json

2. Complete Body Schema

This is the exact structure required for CREATE and UPDATE operations.

{
  "definition": {
    "subscriptions": {
      "big_number": {
        "name": "big_number",
        "columns": [
          {
            "column": "Revenue",
            "aggregation": "SUM",
            "alias": "Revenue",
            "format": {"type": "abbreviated", "format": "#A"}
          }
        ],
        "filters": []
      },
      "main": {
        "name": "main",
        "columns": [
          {"column": "Team", "mapping": "ITEM"},
          {"column": "Revenue", "mapping": "VALUE", "aggregation": "SUM"}
        ],
        "filters": [],
        "orderBy": [],
        "groupBy": [{"column": "Team"}],
        "fiscal": false,
        "projection": false,
        "distinct": false
      }
    },
    "formulas": {
      "dsUpdated": [],
      "dsDeleted": [],
      "card": []
    },
    "annotations": {
      "new": [],
      "modified": [],
      "deleted": []
    },
    "conditionalFormats": {
      "card": [],
      "datasource": []
    },
    "controls": [],
    "segments": {
      "active": [],
      "create": [],
      "update": [],
      "delete": []
    },
    "charts": {
      "main": {
        "component": "main",
        "chartType": "badge_vert_bar",
        "overrides": {},
        "goal": null
      }
    },
    "dynamicTitle": {
      "text": [{"text": "My Card Title", "type": "TEXT"}]
    },
    "dynamicDescription": {
      "text": [{"text": "Card description here", "type": "TEXT"}],
      "displayOnCardDetails": true
    },
    "chartVersion": "12",
    "inputTable": false,
    "noDateRange": false,
    "title": "My Card Title",
    "description": "Card description here"
  },
  "dataProvider": {
    "dataSourceId": "DATASET_UUID_HERE"
  },
  "variables": true,
  "columns": false
}
Field-by-Field Reference
Root Level
FieldTypeRequiredDescription
definitionobjectYesContains all card configuration
dataProvider.dataSourceIdstringYesDataset UUID. Must use dataSourceId, NOT dsId!
variablesbooleanYesMust be true.
columnsbooleanYesMust be false.
definition.subscriptions.big_number

Controls the summary number at the top of the card. Always required, but columns should be empty for badge_singlevalue (the card itself displays the number).

FieldTypeDescription
namestringAlways "big_number"
columnsarrayEmpty [] for badge_singlevalue. First VALUE column for all other types.
columns[].columnstringColumn name (for dataset columns)
columns[].formulaIdstringBeast mode ID (for calculated fields)
columns[].aggregationstringSUM, AVG, COUNT, MIN, MAX
columns[].aliasstringDisplay name
columns[].formatobject{"type": "abbreviated", "format": "#A"}
filtersarrayAlways [] for big_number
definition.subscriptions.main
FieldTypeDescription
namestringAlways "main"
columnsarrayAll column definitions with mappings (see Section 3)
filtersarrayFilter objects
orderByarraySort definitions
groupByarrayAuto-built from ITEM and SERIES columns: [{"column": "Name"}]
fiscalbooleanfalse default
projectionbooleanfalse default
distinctbooleanfalse default

Filter object structure:

{
  "column": "Type",
  "values": ["New Business"],
  "filterType": "LEGACY",
  "operand": "IN"
}
definition.formulas
FieldTypeDescription
dsUpdatedarrayDataset-level formulas updated
dsDeletedarrayDataset-level formulas deleted
cardarrayCard-level beast modes (see Section 4)
definition.charts.main
FieldTypeDescription
componentstringAlways "main"
chartTypestringOne of 207 types (see Section 5)
overridesobjectChart styling overrides (all values are strings)
goalnull/objectGoal line configuration
definition.conditionalFormats — MUST be object
{"card": [], "datasource": []}
definition.segments — MUST be object
{"active": [], "create": [], "update": [], "delete": []}
definition.dynamicTitle / dynamicDescription
{
  "text": [{"text": "Title goes here", "type": "TEXT"}]
}

dynamicDescription also has "displayOnCardDetails": true.

Other definition fields
FieldTypeDefaultDescription
chartVersionstring"12"Chart rendering version
inputTablebooleanfalseWhether card is an input table
noDateRangebooleanfalseDisable date range filtering
titlestring--Plain text title (also set dynamicTitle)
descriptionstring--Plain text description

3. Column Mapping

Mapping Types
MappingVisual RoleRequiredDescription
ITEMX-axis / CategoryYes (most charts)The dimension/category axis
VALUEY-axis / MeasureYesThe numeric value being measured
SERIESColor / LegendNoGroups data into colored series
Column Object Structure

For dataset columns:

{
  "column": "Team",
  "mapping": "ITEM",
  "aggregation": "SUM",
  "alias": "Team Name",
  "format": {"type": "number", "format": "###,##0"}
}

For beast mode columns:

{
  "formulaId": "calculation_123456",
  "mapping": "VALUE",
  "aggregation": "SUM",
  "alias": "Win Rate %"
}
Field Reference
FieldRequiredDescription
columnYes*Column name from the dataset
formulaIdYes*Beast mode legacy ID (use instead of column for calculated fields)
mappingYesITEM, VALUE, or SERIES
aggregationNoSUM, AVG, COUNT, MIN, MAX, UNIQUE
aliasNoDisplay name override
formatNoNumber/date formatting object

*One of column or formulaId is required.

Examples by Chart Type

Bar chart (category + measure):

[
  {"column": "Region", "mapping": "ITEM"},
  {"column": "Revenue", "mapping": "VALUE", "aggregation": "SUM"}
]

Stacked bar (category + measure + series):

[
  {"column": "Region", "mapping": "ITEM"},
  {"column": "Revenue", "mapping": "VALUE", "aggregation": "SUM"},
  {"column": "Product Line", "mapping": "SERIES"}
]

Single value (measure only):

[
  {"column": "Revenue", "mapping": "VALUE", "aggregation": "SUM", "alias": "Total Revenue"}
]

Table (multiple items):

[
  {"column": "Name", "mapping": "ITEM"},
  {"column": "Department", "mapping": "ITEM"},
  {"column": "Revenue", "mapping": "VALUE", "aggregation": "SUM"},
  {"column": "Deals", "mapping": "VALUE", "aggregation": "COUNT"}
]
groupBy Auto-Generation

Build groupBy from all ITEM and SERIES columns:

group_by = []
for c in columns:
    if c.get("mapping") in ("ITEM", "SERIES") and "column" in c:
        group_by.append({"column": c["column"]})

4. Beast Modes

Card-Level vs Dataset-Level
ScopeStorageVisibilityHow to Reference
Card-leveldefinition.formulas.card[]Only on this cardIncluded inline in card body
Dataset-levelCreated via APIAll cards using that datasetReferenced by formulaId
Creating a Beast Mode (Dataset-Level)
community-domo-cli --output json -y beast-modes create \
  --body-file beastmode.json > bm_response.json

Body:

{
  "name": "Revenue per Deal",
  "owner": 705231757,
  "locked": false,
  "global": false,
  "expression": "SUM(`Distinct Closed Won ACV`) / COUNT(`Opportunity ID`)",
  "links": [
    {
      "resource": {"type": "DATA_SOURCE", "id": "DATASET_UUID"},
      "visible": true,
      "active": false,
      "valid": "VALID"
    }
  ],
  "aggregated": true,
  "analytic": false,
  "nonAggregatedColumns": [],
  "dataType": "DECIMAL",
  "status": "VALID",
  "cacheWindow": "non_dynamic",
  "columnPositions": [],
  "functions": [],
  "functionTemplateDependencies": [],
  "archived": false,
  "hidden": false,
  "variable": false
}

The response includes id (UUID) and legacyId — use legacyId as formulaId in card columns.

dataType Options
ValueUse For
DECIMALCurrency, percentages, ratios (default)
LONGWhole numbers, counts
DOUBLEHigh-precision decimals
STRINGText/category results
DATEDate calculations

5. Chart Type Index

207 chart types across 22 groups. Pick a badge_* type string from the index below, then read the corresponding reference file for override details.

badge_line is the only type that returns HTTP 400 on creation. Use badge_two_trendline or badge_spark_line instead.

GroupCountTypesReference
Bar24badge_vert_bar, badge_horiz_bar, badge_vert_stackedbar, badge_horiz_stackedbar, badge_vert_multibar, badge_horiz_multibar, badge_vert_nestedbar, badge_horiz_nestedbar, badge_vert_percentbar, badge_horiz_percentbar, badge_vert_100pct, badge_horiz_100pct, badge_vert_dual_stackedbar, badge_horiz_dual_stackedbar, badge_vert_rtbar, badge_horiz_rtbar, badge_vert_rtmultibar, badge_horiz_rtmultibar, badge_vert_rtstackedbar, badge_horiz_rtstackedbar, badge_vert_bar_overlay, badge_horiz_bar_overlay, badge_vert_symbol, badge_spark_barreferences/bar.md
Line16badge_trendline, badge_two_trendline, badge_curvedline, badge_stepline, badge_symbolline, badge_rttrendline, badge_stackedtrend, badge_variance_line, badge_spark_line, badge_curved_symbolline, badge_horiz_trendline, badge_horiz_curvedline, badge_horiz_stepline, badge_horiz_symbolline, badge_horiz_curved_symbolline, badge_horiz_stackedtrendreferences/line.md
Combo18badge_line_bar, badge_line_stackedbar, badge_line_clusterbar, badge_vert_bar_line, badge_horiz_bar_line, badge_curved_line_bar, badge_curved_line_stackedbar, badge_horiz_line_bar, badge_horiz_line_clusterbar, badge_horiz_line_stackedbar, badge_vert_100pct_linebar, badge_horiz_100pct_linebar, badge_vert_nested_linebar, badge_horiz_nested_linebar, badge_symbol_bar, badge_symbol_stackedbar, badge_horiz_symbol_bar, badge_horiz_symbol_stackedbarreferences/barline.md
Area + Dot Plot26badge_vert_area_overlay, badge_horiz_area_overlay, badge_vert_100pct_area, badge_horiz_100pct_area, badge_vert_curved_area_overlay, badge_horiz_curved_area_overlay, badge_vert_curved_stacked_area, badge_horiz_curved_stacked_area, badge_vert_curved_100pct_area, badge_horiz_curved_100pct_area, badge_vert_step_area_overlay, badge_horiz_step_area_overlay, badge_vert_step_stacked_area, badge_horiz_step_stacked_area, badge_vert_step_100pct_area, badge_horiz_step_100pct_area, badge_vert_dotplot_overlay, badge_horiz_dotplot_overlay, badge_vert_multi_dotplot, badge_horiz_multi_dotplot, badge_vert_stacked_dotplot, badge_horiz_stacked_dotplot, badge_vert_line_multi_dotplot, badge_horiz_line_multi_dotplot, badge_vert_line_stacked_dotplot, badge_horiz_line_stacked_dotplotreferences/area.md
Pie / Donut / Rose5badge_pie, badge_donut, badge_nautilus, badge_nautilus_donut, badge_nightingale_rosereferences/pie.md
Tables5badge_basic_table, badge_pivot_table, badge_flex_table, badge_table, badge_heatmap_tablereferences/table.md
Gauges + Multi-Value16badge_singlevalue, badge_filledgauge, badge_gauge, badge_facegauge, badge_shapegauge, badge_compgauge, badge_compfillgauge_basic, badge_compfillgauge_adv, badge_progressbar, badge_radial_progress, badge_multi_radial_progress, badge_in_range_gauge, badge_imagegauge, badge_bullet, badge_multi_value, badge_multi_value_colsreferences/gauge.md
Maps42badge_world_map, badge_map, badge_map_us_state, badge_map_us_county, badge_map_latlong, badge_map_latlong_route, + 36 country mapsreferences/map.md
Specialty16badge_treemap, badge_funnel, badge_funnel_bars, badge_funnel_swing, badge_waffle, badge_word_cloud, badge_stream, badge_stream_funnel, badge_slope, badge_bump, badge_pareto, badge_heatmap, badge_gantt, badge_gantt_dep, badge_gantt_percent, badge_calendarreferences/specialty.md
Data Science6badge_ds_forecasting, badge_ds_outliers, badge_ds_pred_modeling, badge_ds_spc, badge_correlation_matrix, badge_confusion_matrixreferences/data-science.md
Period over Period13badge_pop_trendline, badge_pop_trendline_var, badge_pop_rttrendline, badge_pop_bar_line, badge_pop_bar_line_var, badge_pop_line_bar, badge_pop_line_bar_var, badge_pop_vert_multibar, badge_pop_filledgauge, badge_pop_shapegauge, badge_pop_multi_value, badge_pop_progressbar, badge_pop_flex_tablereferences/period-over-period.md
Statistical8badge_vert_histogram, badge_horiz_histogram, badge_vert_boxplot, badge_horiz_boxplot, badge_vert_waterfall, badge_horiz_waterfall, badge_xy_line, badge_xybubblereferences/statistical.md
Selectors6badge_checkbox_selector, badge_date_selector, badge_dropdown_selector, badge_radio_selector, badge_range_selector, badge_slicerreferences/selector.md
Text + Small Charts6badge_textbox, badge_dynamic_textbox, badge_vert_marimekko, badge_horiz_marimekko, badge_vert_facetedbar, badge_horiz_facetedbarreferences/small-charts.md

Common Override Categories

Most chart types share these standard override categories:

CategoryPurposeKey Overrides
generalFonts, sorting, limitsdefault_font_family, font_size (Smaller/Larger/Largest), total_sort, display_limit, hide_interactivity, disable_animation
legendLegend position and stylinglrg_legend_position (Top/Bottom/Hide), details_legend_position, legend_font_family
bar_settingsBar width/heightwidth_percentage, fixed_bar_width, allow_wide_bars
grid_linesGrid, zero lines, calculated lineshide_value_gridlines, grid_line_color, zero_line_color, calculated_line (Median/Average)
data_label_settingsValue labels on chartshow_data_label (Always/Always - Rotated), datalabel_position, datalabel_fnt_clr, decimal_places_dl
value_scale_yY-axis formattingtitle_y, label_format_y (Number/Currency/Percentage), divide_value_scale_by_y, value_scale_min, value_scale_max, log_scale_y
category_scale_xX-axis formattingtitle_x, cat_scale_show_labels, cat_scale_manual_rotate, max_label_length, never_use_time_scale
hover_text_settingsTooltip formattinghover_text, hover_format, decimal_places_hvr
number_formatCurrency/decimal configcurrency_symbol, currency_sym_position, decimal_separator, thousands_separator
gradient_colorsColor gradientsuse_gradient_colors, gradient_start_fill_color, gradient_end_fill_color, gradient_by_value
scale_markerReference lines/rangessm_type (Line/Range/Quantiles), sm_val_type, sm_value, sm_line_color
colorsSeries colorsseries_1_color (hex string)
Override Value Types
TypeFormatExample
boolean"true" or "false" (as strings)"use_gradient_colors": "true"
stringFree text or hex color"gradient_start_fill_color": "#99CCEEFF"
floatNumber as string"display_limit": "10"
select_listOne of the predefined values"font_size": "Largest"

All override values are strings, even booleans and numbers.


6. Conditional Formats

The structure must be an object, not an array.

"conditionalFormats": {
  "card": [
    {
      "type": "COLOR",
      "column": "Revenue",
      "rules": [
        {"min": 0, "max": 50000, "color": "#FF0000", "label": "Below Target"},
        {"min": 50000, "max": 100000, "color": "#FFAA00", "label": "Near Target"},
        {"min": 100000, "color": "#00AA00", "label": "Above Target"}
      ]
    }
  ],
  "datasource": []
}

Passing conditionalFormats as an array [] instead of {card:[], datasource:[]} causes HTTP 400. The Domo UI returns it as an array when reading — convert to object before writing.


7. Gotchas

Critical — Will Cause Failures
GotchaDetails
dataProvider.dataSourceId NOT dsIdThe field name is dataSourceId. Using dsId silently fails.
variables: true required at rootMust be present at root level.
columns: false required at rootMust be present at root level.
Both subscriptions requiredMust include BOTH big_number AND main. Missing either causes HTTP 400.
conditionalFormats must be object{"card":[], "datasource":[]}. Passing [] causes HTTP 400.
segments must be object{"active":[], "create":[], "update":[], "delete":[]}. Passing [] causes HTTP 400.
badge_line failsAlways returns HTTP 400. Use badge_two_trendline or badge_spark_line.
CREATE requires --page-idcards create --page-id $PAGE_ID — mandatory.
UPDATE uses NO page-idcards update $CARD_ID — card ID only.
Important — Affects Behavior
GotchaDetails
Override values are stringsEven booleans ("true") and numbers ("10") must be strings.
UPDATE replaces entire definitionFull replacement. Read first, modify, write back.
READ→WRITE format mismatchesFix before updating: formulas (read=[], write={"dsUpdated":[],"dsDeleted":[],"card":[]}), conditionalFormats (read=[], write={"card":[],"datasource":[]}), annotations (read=[], write={"new":[],"modified":[],"deleted":[]}), segments (read={"active":[],"definitions":[]}, write={"active":[],"create":[],"update":[],"delete":[]}). Also add title, description, noDateRange if missing; remove modified, allowTableDrill.
groupBy auto-generationBuild from all ITEM and SERIES columns. Missing this = no grouping = all values aggregated into one.
big_number for singlevaluebadge_singlevalue needs columns: [] in big_number. All other types: first VALUE column.
PoP cards need dateRangeFilterbadge_pop_* cards show "0" comparison unless: date column with mapping:"ITEM", aggregation:"MAX" in main; dateRangeFilter with dateTimeRange and periods; time_period subscription. Remove dateGrain before adding periods (they conflict).
Selector cards need big_number columnsEmpty big_number.columns causes 400 {"message":"big_number subscription missing select columns"}. Use COUNT on the filtering column for dropdowns, MAX for date selectors.

Quick Reference

CREATE:  cards create --body-file card.json --page-id PAGE_ID
READ:    cards definition CARD_ID
UPDATE:  cards update CARD_ID --body-file card.json
COPY:    POST /content/v1/cards/CARD_ID/copy  (raw API)
DELETE:  DELETE /content/v1/cards/CARD_ID      (raw API)

Required root: variables=true, columns=false
Required data: dataProvider.dataSourceId (NOT dsId)
Required subs: big_number AND main
conditionalFormats: {card:[], datasource:[]}  (OBJECT)
segments:           {active:[], create:[], update:[], delete:[]}  (OBJECT)

Line charts: badge_two_trendline (NOT badge_line)
Total types: 207 (206 work, badge_line fails)

Comments

Markdown supported