Skip to main content
Create interactive, embeddable cards from your own data using the Tako Thin-Viz API.

Why Thin-Viz

  • Your data, Tako’s rendering. Post your own values and component configs; Tako returns a polished, interactive card — no charting library or frontend work on your side.
  • A full component gallery. Timeseries, bar, pie, table, treemap, sankey, choropleth, heatmap, waterfall, and more — composed top to bottom in a single card.
  • Embed anywhere. Every card comes back with an embed_url (interactive iframe) and an image_url (static image) for chat, dashboards, or docs.

Creating a Card

Create a card by posting your component configurations. One API call, one card.
curl -X POST https://tako.com/api/v1/thin_viz/create/ \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Monthly Revenue",
    "source": "Internal Analytics",
    "components": [
      {
        "component_type": "generic_timeseries",
        "config": {
          "datasets": [
            {
              "label": "Revenue",
              "data": [
                {"x": "2024-01", "y": 50000},
                {"x": "2024-02", "y": 62000},
                {"x": "2024-03", "y": 71000}
              ],
              "units": "$"
            }
          ],
          "chart_type": "line",
          "title": "Monthly Revenue"
        }
      }
    ]
  }'
Response:
{
  "card_id": "abc123xyz",
  "title": "Monthly Revenue",
  "description": "",
  "embed_url": "https://tako.com/embed/abc123xyz",
  "image_url": "https://tako.com/api/v1/image/abc123xyz/",
  "webpage_url": "https://tako.com/card/abc123xyz",
  "card_type": "chart",
  "visualization_data": { ... }
}

Request Fields

FieldTypeRequiredDescription
componentsarrayYesList of component configurations (see Available Components)
titlestringNoCard title (falls back to header component title if not provided)
descriptionstringNoCard description
sourcestringNoData source attribution displayed in footer
image_ttl_minutesintegerNoMinutes to keep a preview image available for download (1–1440). ZDR cards only. See Preview Images for ZDR Cards

Embedding Your Card

Use the embed_url from the response in an iframe:
<iframe
  src="https://tako.com/embed/abc123xyz"
  width="600"
  height="400"
  frameborder="0"
></iframe>
Add ?dark_mode=true or ?dark_mode=false to control the theme.

Preview Images for ZDR Cards

Cards created with zero data retention (ZDR) don’t normally support preview images because the visualization data isn’t persisted. To get a downloadable image for a ZDR card, set image_ttl_minutes when creating the card:
curl -X POST https://tako.com/api/v1/thin_viz/create/ \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Monthly Revenue",
    "image_ttl_minutes": 60,
    "components": [ ... ]
  }'
# Reuses the client from the first example above
card = client.create_card(CreateCardRequest(
    title="Monthly Revenue",
    image_ttl_minutes=60,
    components=[...],  # see the examples below for full component configs
))
The response includes an image_url that renders a screenshot on demand. You can customize the image with query parameters:
ParameterTypeDescription
dark_modebooleantrue for dark theme, false for light
widthintegerImage width in pixels
heightintegerImage height in pixels
hideFooterbooleanHide the card footer
https://tako.com/api/v1/image/abc123xyz/?dark_mode=true&width=800&height=600
After the TTL expires, the image endpoint returns 410 Gone. The TTL must be between 1 and 1440 minutes (24 hours).
image_ttl_minutes is only supported for ZDR cards and is ignored for standard cards, which already have persistent preview images.

Example: Stock Card with Kicker Boxes

For financial data, use the generic_timeseries component with show_kicker_boxes enabled:
curl -X POST https://tako.com/api/v1/thin_viz/create/ \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "AAPL vs GOOGL",
    "source": "Market Data",
    "components": [
      {
        "component_type": "generic_timeseries",
        "config": {
          "datasets": [
            {
              "label": "AAPL",
              "kicker": "NASDAQ",
              "data": [
                {"x": "2024-01-01", "y": 185.50},
                {"x": "2024-01-02", "y": 195.20}
              ],
              "units": "$"
            },
            {
              "label": "GOOGL",
              "kicker": "NASDAQ",
              "data": [
                {"x": "2024-01-01", "y": 152.60},
                {"x": "2024-01-02", "y": 150.10}
              ],
              "units": "$"
            }
          ],
          "chart_type": "line",
          "title": "Stock Price (USD)",
          "show_kicker_boxes": true
        }
      }
    ]
  }'
# Reuses the client from the first example above
card = client.create_card(CreateCardRequest(
    title="AAPL vs GOOGL",
    source="Market Data",
    components=[
        ComponentConfig(
            component_type="generic_timeseries",
            config={
                "datasets": [
                    {
                        "label": "AAPL",
                        "kicker": "NASDAQ",
                        "data": [
                            {"x": "2024-01-01", "y": 185.50},
                            {"x": "2024-01-02", "y": 195.20}
                        ],
                        "units": "$"
                    },
                    {
                        "label": "GOOGL",
                        "kicker": "NASDAQ",
                        "data": [
                            {"x": "2024-01-01", "y": 152.60},
                            {"x": "2024-01-02", "y": 150.10}
                        ],
                        "units": "$"
                    }
                ],
                "chart_type": "line",
                "title": "Stock Price (USD)",
                "show_kicker_boxes": True
            },
        ),
    ],
))
When show_kicker_boxes is enabled, each dataset with a kicker field renders a stock box above the chart showing the exchange label, current value, and change.

Example: Stock Card with Explicit Stock Boxes

Alternatively, use separate stock_boxes and generic_timeseries components for full control:
curl -X POST https://tako.com/api/v1/thin_viz/create/ \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "AAPL vs GOOGL",
    "source": "Market Data",
    "components": [
      {
        "component_type": "stock_boxes",
        "config": {
          "items": [
            {
              "labelPrimary": "AAPL",
              "labelSecondary": "NASDAQ",
              "valuePrimary": "$195.20",
              "subValue": "+$9.70 (+5.24%)"
            },
            {
              "labelPrimary": "GOOGL",
              "labelSecondary": "NASDAQ",
              "valuePrimary": "$150.10",
              "subValue": "-$2.50 (-1.64%)"
            }
          ]
        }
      },
      {
        "component_type": "generic_timeseries",
        "config": {
          "datasets": [
            {
              "label": "AAPL",
              "data": [
                {"x": "2024-01-01", "y": 185.50},
                {"x": "2024-01-02", "y": 195.20}
              ],
              "units": "$"
            },
            {
              "label": "GOOGL",
              "data": [
                {"x": "2024-01-01", "y": 152.60},
                {"x": "2024-01-02", "y": 150.10}
              ],
              "units": "$"
            }
          ],
          "chart_type": "line",
          "title": "Stock Price (USD)"
        }
      }
    ]
  }'
# Reuses the client from the first example above
card = client.create_card(CreateCardRequest(
    title="AAPL vs GOOGL",
    source="Market Data",
    components=[
        ComponentConfig(
            component_type="stock_boxes",
            config={
                "items": [
                    {
                        "labelPrimary": "AAPL",
                        "labelSecondary": "NASDAQ",
                        "valuePrimary": "$195.20",
                        "subValue": "+$9.70 (+5.24%)"
                    },
                    {
                        "labelPrimary": "GOOGL",
                        "labelSecondary": "NASDAQ",
                        "valuePrimary": "$150.10",
                        "subValue": "-$2.50 (-1.64%)"
                    }
                ]
            },
        ),
        ComponentConfig(
            component_type="generic_timeseries",
            config={
                "datasets": [
                    {
                        "label": "AAPL",
                        "data": [
                            {"x": "2024-01-01", "y": 185.50},
                            {"x": "2024-01-02", "y": 195.20}
                        ],
                        "units": "$"
                    },
                    {
                        "label": "GOOGL",
                        "data": [
                            {"x": "2024-01-01", "y": 152.60},
                            {"x": "2024-01-02", "y": 150.10}
                        ],
                        "units": "$"
                    }
                ],
                "chart_type": "line",
                "title": "Stock Price (USD)"
            },
        ),
    ],
))
For stock_boxes, the subValue color is automatic: values starting with + appear green, - appear red.

Example: Bar Chart

curl -X POST https://tako.com/api/v1/thin_viz/create/ \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Revenue by Region",
    "source": "Internal Analytics",
    "components": [
      {
        "component_type": "header",
        "config": {
          "title": "Revenue by Region"
        }
      },
      {
        "component_type": "categorical_bar",
        "config": {
          "datasets": [
            {
              "label": "Revenue",
              "data": [
                {"x": "North", "y": 120000},
                {"x": "South", "y": 98000},
                {"x": "East", "y": 87000},
                {"x": "West", "y": 145000}
              ],
              "units": "$"
            }
          ]
        }
      }
    ]
  }'
# Reuses the client from the first example above
card = client.create_card(CreateCardRequest(
    title="Revenue by Region",
    source="Internal Analytics",
    components=[
        ComponentConfig(
            component_type="header",
            config={"title": "Revenue by Region"},
        ),
        ComponentConfig(
            component_type="categorical_bar",
            config={
                "datasets": [
                    {
                        "label": "Revenue",
                        "data": [
                            {"x": "North", "y": 120000},
                            {"x": "South", "y": 98000},
                            {"x": "East", "y": 87000},
                            {"x": "West", "y": 145000}
                        ],
                        "units": "$"
                    }
                ]
            },
        ),
    ],
))

Example: Data Table Chart

A bar chart with an auto-generated data table below showing the values:
curl -X POST https://tako.com/api/v1/thin_viz/create/ \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Q4 Sales by Product",
    "source": "Sales Team",
    "components": [
      {
        "component_type": "header",
        "config": {
          "title": "Q4 Sales by Product"
        }
      },
      {
        "component_type": "data_table_chart",
        "config": {
          "datasets": [
            {
              "label": "Units Sold",
              "data": [
                {"x": "Widget A", "y": 1200},
                {"x": "Widget B", "y": 850},
                {"x": "Widget C", "y": 2100}
              ]
            }
          ]
        }
      }
    ]
  }'
# Reuses the client from the first example above
card = client.create_card(CreateCardRequest(
    title="Q4 Sales by Product",
    source="Sales Team",
    components=[
        ComponentConfig(
            component_type="header",
            config={"title": "Q4 Sales by Product"},
        ),
        ComponentConfig(
            component_type="data_table_chart",
            config={
                "datasets": [
                    {
                        "label": "Units Sold",
                        "data": [
                            {"x": "Widget A", "y": 1200},
                            {"x": "Widget B", "y": 850},
                            {"x": "Widget C", "y": 2100}
                        ]
                    }
                ]
            },
        ),
    ],
))

Example: Financial Boxes

Display financial metrics with growth indicators:
curl -X POST https://tako.com/api/v1/thin_viz/create/ \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "AAPL Financials",
    "source": "SEC Filings",
    "components": [
      {
        "component_type": "financial_boxes",
        "config": {
          "items": [
            {
              "header": "Revenue",
              "value": "$94.9B",
              "growth": {"formattedValue": "6.1% YoY", "value": 0.061}
            },
            {
              "header": "Net Income",
              "value": "$23.6B",
              "growth": {"formattedValue": "-3.4% YoY", "value": -0.034}
            },
            {
              "header": "EPS",
              "value": "$1.64"
            }
          ]
        }
      }
    ]
  }'
# Reuses the client from the first example above
card = client.create_card(CreateCardRequest(
    title="AAPL Financials",
    source="SEC Filings",
    components=[
        ComponentConfig(
            component_type="financial_boxes",
            config={
                "items": [
                    {
                        "header": "Revenue",
                        "value": "$94.9B",
                        "growth": {"formattedValue": "6.1% YoY", "value": 0.061}
                    },
                    {
                        "header": "Net Income",
                        "value": "$23.6B",
                        "growth": {"formattedValue": "-3.4% YoY", "value": -0.034}
                    },
                    {"header": "EPS", "value": "$1.64"}
                ]
            },
        ),
    ],
))
Growth indicator colors are automatic: positive value appears green, negative appears red.

Example: Data Table

A configurable table with columns, sorting, and pagination:
curl -X POST https://tako.com/api/v1/thin_viz/create/ \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Product Performance",
    "components": [
      {
        "component_type": "table",
        "config": {
          "columns": [
            {"field": "name", "label": "Product", "type": "string"},
            {"field": "revenue", "label": "Revenue", "type": "currency", "units": "$"},
            {"field": "growth", "label": "Growth", "type": "percent", "units": "%"},
            {"field": "rating", "label": "Rating", "type": "rating"},
            {"field": "in_stock", "label": "In Stock", "type": "boolean"}
          ],
          "rows": [
            {"name": "Product A", "revenue": 1500000, "growth": 15.0, "rating": 4, "in_stock": true},
            {"name": "Product B", "revenue": 2300000, "growth": -5.0, "rating": 3, "in_stock": true},
            {"name": "Product C", "revenue": 980000, "growth": 22.3, "rating": 5, "in_stock": false}
          ],
          "searchable": true,
          "paginated": true,
          "rows_per_page": 25,
          "initial_sort_field": "revenue",
          "initial_sort_order": "desc",
          "highlight_best": true
        }
      }
    ]
  }'
# Reuses the client from the first example above
card = client.create_card(CreateCardRequest(
    title="Product Performance",
    components=[
        ComponentConfig(
            component_type="table",
            config={
                "columns": [
                    {"field": "name", "label": "Product", "type": "string"},
                    {
                        "field": "revenue",
                        "label": "Revenue",
                        "type": "currency",
                        "units": "$"
                    },
                    {
                        "field": "growth",
                        "label": "Growth",
                        "type": "percent",
                        "units": "%"
                    },
                    {"field": "rating", "label": "Rating", "type": "rating"},
                    {
                        "field": "in_stock",
                        "label": "In Stock",
                        "type": "boolean"
                    }
                ],
                "rows": [
                    {
                        "name": "Product A",
                        "revenue": 1500000,
                        "growth": 15.0,
                        "rating": 4,
                        "in_stock": True
                    },
                    {
                        "name": "Product B",
                        "revenue": 2300000,
                        "growth": -5.0,
                        "rating": 3,
                        "in_stock": True
                    },
                    {
                        "name": "Product C",
                        "revenue": 980000,
                        "growth": 22.3,
                        "rating": 5,
                        "in_stock": False
                    }
                ],
                "searchable": True,
                "paginated": True,
                "rows_per_page": 25,
                "initial_sort_field": "revenue",
                "initial_sort_order": "desc",
                "highlight_best": True
            },
        ),
    ],
))

Table Column Types

TypeRenderingDefault Alignment
stringPlain textLeft
numberFormatted with unitsRight
dateDate valuesLeft
percentPercentage formattingRight
currencyRight-aligned with currency formatting (uses units field)Right
booleanCheckmarks (✓/✗) with green/red colorsCenter
ratingStars (★★★☆☆) clamped to 1-5 rangeCenter

Table Config Fields

FieldTypeDefaultDescription
columnsarrayrequiredColumn definitions (see column types above)
rowsarrayrequiredRow data as list of objects. Keys should match column field values
titlestringOptional title displayed above the table
searchablebooleanfalseEnable search/filter functionality
paginatedbooleanfalseEnable pagination
rows_per_pageinteger25Number of rows per page when paginated
initial_sort_fieldstringField to sort by initially
initial_sort_order"asc" | "desc""desc"Initial sort direction
highlight_bestbooleanfalseHighlight the best value in numeric columns with a green background. For currency: lowest is best. For number/rating: highest is best. Only highlights when there is a unique winner
Each column also supports an optional align field ("left", "right", or "center") to override the default alignment.
When highlight_best is enabled, the best value in each currency, number, and rating column is highlighted with a green background. Currency columns treat the lowest value as best; number and rating columns treat the highest value as best. Boolean columns are excluded — they use checkmark colors instead.

Example: Timeline

A timeline showing events or periods along a time axis:
curl -X POST https://tako.com/api/v1/thin_viz/create/ \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Product Launch Timeline",
    "source": "Product Team",
    "components": [
      {
        "component_type": "timeline",
        "config": {
          "events": [
            {
              "start_date": "2024-01-15",
              "end_date": "2024-03-30",
              "label": "Research & Design",
              "value": "2.5 months"
            },
            {
              "start_date": "2024-04-01",
              "end_date": "2024-07-15",
              "label": "Development",
              "value": "3.5 months"
            },
            {
              "start_date": "2024-07-16",
              "end_date": "2024-08-31",
              "label": "Beta Testing",
              "value": "1.5 months"
            },
            {
              "start_date": "2024-09-01",
              "end_date": "2024-09-15",
              "label": "Launch",
              "value": "2 weeks",
              "color": "#22C55E"
            }
          ],
          "title": "Product Launch Timeline"
        }
      }
    ]
  }'
# Reuses the client from the first example above
card = client.create_card(CreateCardRequest(
    title="Product Launch Timeline",
    source="Product Team",
    components=[
        ComponentConfig(
            component_type="timeline",
            config={
                "events": [
                    {
                        "start_date": "2024-01-15",
                        "end_date": "2024-03-30",
                        "label": "Research & Design",
                        "value": "2.5 months"
                    },
                    {
                        "start_date": "2024-04-01",
                        "end_date": "2024-07-15",
                        "label": "Development",
                        "value": "3.5 months"
                    },
                    {
                        "start_date": "2024-07-16",
                        "end_date": "2024-08-31",
                        "label": "Beta Testing",
                        "value": "1.5 months"
                    },
                    {
                        "start_date": "2024-09-01",
                        "end_date": "2024-09-15",
                        "label": "Launch",
                        "value": "2 weeks",
                        "color": "#22C55E"
                    }
                ],
                "title": "Product Launch Timeline"
            },
        ),
    ],
))

Timeline Fields

FieldTypeRequiredDescription
eventsarrayYesList of timeline events (see below)
titlestringNoChart title
series_color_themestringNoColor theme for events
timeline_mode"absolute" | "ordinal"NoX-axis spacing mode. absolute spaces events proportional to real dates. ordinal spaces events evenly. Auto-detected if not set
ordinal_label_prefixstringNoPrefix for ordinal x-axis labels (e.g., "Week" renders as “Week 1”, “Week 2”)
Each event in the events array has:
FieldTypeRequiredDescription
start_datestringYesStart date in ISO format (e.g., "2024-01-15")
end_datestringYesEnd date in ISO format (e.g., "2024-06-30")
labelstringYesEvent label
valuestringNoValue to display (e.g., duration, cost)
colorstringNoOverride color for this event (hex format, e.g., "#FF5733")
When timeline_mode is not set, the mode is auto-detected based on the distribution of events. Use "ordinal" mode when events have very different time gaps and you want them spaced evenly, or "absolute" mode when the proportional time spacing is meaningful.

Example: Pie Chart

Show proportional data as slices of a circle:
curl -X POST https://tako.com/api/v1/thin_viz/create/ \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Browser Market Share",
    "source": "Statcounter",
    "components": [
      {
        "component_type": "pie",
        "config": {
          "datasets": [
            {
              "label": "Share",
              "data": [
                {"x": "Chrome", "y": 65.2},
                {"x": "Safari", "y": 18.7},
                {"x": "Edge", "y": 5.4},
                {"x": "Firefox", "y": 3.0},
                {"x": "Other", "y": 7.7}
              ],
              "units": "%"
            }
          ],
          "title": "Global Desktop Browser Share"
        }
      }
    ]
  }'
# Reuses the client from the first example above
card = client.create_card(CreateCardRequest(
    title="Browser Market Share",
    source="Statcounter",
    components=[
        ComponentConfig(
            component_type="pie",
            config={
                "datasets": [
                    {
                        "label": "Share",
                        "data": [
                            {"x": "Chrome", "y": 65.2},
                            {"x": "Safari", "y": 18.7},
                            {"x": "Edge", "y": 5.4},
                            {"x": "Firefox", "y": 3.0},
                            {"x": "Other", "y": 7.7}
                        ],
                        "units": "%"
                    }
                ],
                "title": "Global Desktop Browser Share"
            },
        ),
    ],
))
Each data point uses x for the slice label and y for the value. Slices are colored automatically from the theme palette.

Example: Histogram

Bin raw values into a frequency distribution:
curl -X POST https://tako.com/api/v1/thin_viz/create/ \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Order Value Distribution",
    "source": "Internal Analytics",
    "components": [
      {
        "component_type": "histogram",
        "config": {
          "datasets": [
            {
              "label": "Order Values",
              "data": [
                {"x": "1", "y": 12.50}, {"x": "2", "y": 18.30}, {"x": "3", "y": 22.10},
                {"x": "4", "y": 25.00}, {"x": "5", "y": 28.40}, {"x": "6", "y": 31.20},
                {"x": "7", "y": 33.50}, {"x": "8", "y": 35.00}, {"x": "9", "y": 38.20},
                {"x": "10", "y": 41.00}, {"x": "11", "y": 42.50}, {"x": "12", "y": 45.00},
                {"x": "13", "y": 47.30}, {"x": "14", "y": 50.00}, {"x": "15", "y": 52.10},
                {"x": "16", "y": 55.00}, {"x": "17", "y": 58.40}, {"x": "18", "y": 62.00},
                {"x": "19", "y": 68.50}, {"x": "20", "y": 75.20}, {"x": "21", "y": 82.00},
                {"x": "22", "y": 90.10}, {"x": "23", "y": 95.00}, {"x": "24", "y": 105.00},
                {"x": "25", "y": 120.00}
              ],
              "units": "$"
            }
          ],
          "title": "Order Values ($)",
          "num_bins": 8
        }
      }
    ]
  }'
# Reuses the client from the first example above
card = client.create_card(CreateCardRequest(
    title="Order Value Distribution",
    source="Internal Analytics",
    components=[
        ComponentConfig(
            component_type="histogram",
            config={
                "datasets": [
                    {
                        "label": "Order Values",
                        "data": [
                            {"x": "1", "y": 12.50},
                            {"x": "2", "y": 18.30},
                            {"x": "3", "y": 22.10},
                            {"x": "4", "y": 25.00},
                            {"x": "5", "y": 28.40},
                            {"x": "6", "y": 31.20},
                            {"x": "7", "y": 33.50},
                            {"x": "8", "y": 35.00},
                            {"x": "9", "y": 38.20},
                            {"x": "10", "y": 41.00},
                            {"x": "11", "y": 42.50},
                            {"x": "12", "y": 45.00},
                            {"x": "13", "y": 47.30},
                            {"x": "14", "y": 50.00},
                            {"x": "15", "y": 52.10},
                            {"x": "16", "y": 55.00},
                            {"x": "17", "y": 58.40},
                            {"x": "18", "y": 62.00},
                            {"x": "19", "y": 68.50},
                            {"x": "20", "y": 75.20},
                            {"x": "21", "y": 82.00},
                            {"x": "22", "y": 90.10},
                            {"x": "23", "y": 95.00},
                            {"x": "24", "y": 105.00},
                            {"x": "25", "y": 120.00}
                        ],
                        "units": "$"
                    }
                ],
                "title": "Order Values ($)",
                "num_bins": 8
            },
        ),
    ],
))
The y values are the raw data — bins are computed automatically. Use num_bins to set the number of bins, or bin_width to set a fixed width.

Example: Scatter Plot

Show the relationship between two continuous variables:
curl -X POST https://tako.com/api/v1/thin_viz/create/ \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Height vs Weight",
    "source": "Survey Data",
    "components": [
      {
        "component_type": "scatter",
        "config": {
          "datasets": [
            {
              "label": "Participants",
              "data": [
                {"x": 165, "y": 60, "label": "P1"},
                {"x": 170, "y": 68, "label": "P2"},
                {"x": 175, "y": 72, "label": "P3"},
                {"x": 180, "y": 78, "label": "P4"},
                {"x": 185, "y": 85, "label": "P5"},
                {"x": 190, "y": 92, "label": "P6"}
              ],
              "x_units": "cm",
              "y_units": "kg"
            }
          ],
          "title": "Height vs Weight",
          "x_axis_label": "Height (cm)",
          "y_axis_label": "Weight (kg)"
        }
      }
    ]
  }'
# Reuses the client from the first example above
card = client.create_card(CreateCardRequest(
    title="Height vs Weight",
    source="Survey Data",
    components=[
        ComponentConfig(
            component_type="scatter",
            config={
                "datasets": [
                    {
                        "label": "Participants",
                        "data": [
                            {"x": 165, "y": 60, "label": "P1"},
                            {"x": 170, "y": 68, "label": "P2"},
                            {"x": 175, "y": 72, "label": "P3"},
                            {"x": 180, "y": 78, "label": "P4"},
                            {"x": 185, "y": 85, "label": "P5"},
                            {"x": 190, "y": 92, "label": "P6"}
                        ],
                        "x_units": "cm",
                        "y_units": "kg"
                    }
                ],
                "title": "Height vs Weight",
                "x_axis_label": "Height (cm)",
                "y_axis_label": "Weight (kg)"
            },
        ),
    ],
))
Each data point’s optional label is shown in the tooltip on hover.

Example: Bubble Chart

A scatter plot with a size dimension — useful for plotting three variables at once:
curl -X POST https://tako.com/api/v1/thin_viz/create/ \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Product Performance",
    "source": "Internal Analytics",
    "components": [
      {
        "component_type": "bubble",
        "config": {
          "datasets": [
            {
              "label": "Products",
              "data": [
                {"x": 4.2, "y": 12.5, "r": 15, "label": "Widget A"},
                {"x": 3.8, "y": 18.2, "r": 22, "label": "Widget B"},
                {"x": 4.6, "y": 8.7, "r": 30, "label": "Widget C"},
                {"x": 3.5, "y": 22.0, "r": 12, "label": "Widget D"},
                {"x": 4.8, "y": 15.3, "r": 25, "label": "Widget E"}
              ]
            }
          ],
          "title": "Rating vs Margin (bubble = revenue)",
          "x_axis_label": "Avg Rating (out of 5)",
          "y_axis_label": "Margin (%)"
        }
      }
    ]
  }'
# Reuses the client from the first example above
card = client.create_card(CreateCardRequest(
    title="Product Performance",
    source="Internal Analytics",
    components=[
        ComponentConfig(
            component_type="bubble",
            config={
                "datasets": [
                    {
                        "label": "Products",
                        "data": [
                            {"x": 4.2, "y": 12.5, "r": 15, "label": "Widget A"},
                            {"x": 3.8, "y": 18.2, "r": 22, "label": "Widget B"},
                            {"x": 4.6, "y": 8.7, "r": 30, "label": "Widget C"},
                            {"x": 3.5, "y": 22.0, "r": 12, "label": "Widget D"},
                            {"x": 4.8, "y": 15.3, "r": 25, "label": "Widget E"}
                        ]
                    }
                ],
                "title": "Rating vs Margin (bubble = revenue)",
                "x_axis_label": "Avg Rating (out of 5)",
                "y_axis_label": "Margin (%)"
            },
        ),
    ],
))
The third dimension is encoded as bubble radius via r on each data point.

Example: Choropleth Map

Color geographic regions by value. map_type is "us_states" or "world":
curl -X POST https://tako.com/api/v1/thin_viz/create/ \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Population by State",
    "source": "US Census",
    "components": [
      {
        "component_type": "choropleth",
        "config": {
          "datasets": [
            {
              "label": "Population (millions)",
              "data": [
                {"x": "California", "y": 39.0},
                {"x": "Texas", "y": 30.5},
                {"x": "Florida", "y": 22.6},
                {"x": "New York", "y": 19.5},
                {"x": "Pennsylvania", "y": 12.9},
                {"x": "Illinois", "y": 12.5},
                {"x": "Ohio", "y": 11.8},
                {"x": "Georgia", "y": 11.0},
                {"x": "North Carolina", "y": 10.7},
                {"x": "Michigan", "y": 10.0}
              ],
              "units": "M"
            }
          ],
          "title": "US State Population",
          "map_type": "us_states"
        }
      }
    ]
  }'
# Reuses the client from the first example above
card = client.create_card(CreateCardRequest(
    title="Population by State",
    source="US Census",
    components=[
        ComponentConfig(
            component_type="choropleth",
            config={
                "datasets": [
                    {
                        "label": "Population (millions)",
                        "data": [
                            {"x": "California", "y": 39.0},
                            {"x": "Texas", "y": 30.5},
                            {"x": "Florida", "y": 22.6},
                            {"x": "New York", "y": 19.5},
                            {"x": "Pennsylvania", "y": 12.9},
                            {"x": "Illinois", "y": 12.5},
                            {"x": "Ohio", "y": 11.8},
                            {"x": "Georgia", "y": 11.0},
                            {"x": "North Carolina", "y": 10.7},
                            {"x": "Michigan", "y": 10.0}
                        ],
                        "units": "M"
                    }
                ],
                "title": "US State Population",
                "map_type": "us_states"
            },
        ),
    ],
))
For US states, x is the full state name (e.g. "California"). For world maps, use "map_type": "world" and country names.

Example: Heatmap

A 2D grid where color encodes value. Useful for things like correlation matrices or activity by day-and-hour:
curl -X POST https://tako.com/api/v1/thin_viz/create/ \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Sales by Day & Shift",
    "source": "POS System",
    "components": [
      {
        "component_type": "heatmap",
        "config": {
          "data": [
            {"x": "Mon", "y": "Morning",   "v": 12},
            {"x": "Mon", "y": "Midday",    "v": 38},
            {"x": "Mon", "y": "Afternoon", "v": 22},
            {"x": "Mon", "y": "Evening",   "v": 45},
            {"x": "Tue", "y": "Morning",   "v": 15},
            {"x": "Tue", "y": "Midday",    "v": 42},
            {"x": "Tue", "y": "Afternoon", "v": 28},
            {"x": "Tue", "y": "Evening",   "v": 50},
            {"x": "Wed", "y": "Morning",   "v": 18},
            {"x": "Wed", "y": "Midday",    "v": 45},
            {"x": "Wed", "y": "Afternoon", "v": 30},
            {"x": "Wed", "y": "Evening",   "v": 55},
            {"x": "Thu", "y": "Morning",   "v": 20},
            {"x": "Thu", "y": "Midday",    "v": 48},
            {"x": "Thu", "y": "Afternoon", "v": 35},
            {"x": "Thu", "y": "Evening",   "v": 62},
            {"x": "Fri", "y": "Morning",   "v": 25},
            {"x": "Fri", "y": "Midday",    "v": 55},
            {"x": "Fri", "y": "Afternoon", "v": 40},
            {"x": "Fri", "y": "Evening",   "v": 78}
          ],
          "title": "Orders by Day & Shift",
          "x_axis_label": "Day",
          "y_axis_label": "Shift",
          "v_label": "Orders"
        }
      }
    ]
  }'
# Reuses the client from the first example above
card = client.create_card(CreateCardRequest(
    title="Sales by Day & Shift",
    source="POS System",
    components=[
        ComponentConfig(
            component_type="heatmap",
            config={
                "data": [
                    {"x": "Mon", "y": "Morning", "v": 12},
                    {"x": "Mon", "y": "Midday", "v": 38},
                    {"x": "Mon", "y": "Afternoon", "v": 22},
                    {"x": "Mon", "y": "Evening", "v": 45},
                    {"x": "Tue", "y": "Morning", "v": 15},
                    {"x": "Tue", "y": "Midday", "v": 42},
                    {"x": "Tue", "y": "Afternoon", "v": 28},
                    {"x": "Tue", "y": "Evening", "v": 50},
                    {"x": "Wed", "y": "Morning", "v": 18},
                    {"x": "Wed", "y": "Midday", "v": 45},
                    {"x": "Wed", "y": "Afternoon", "v": 30},
                    {"x": "Wed", "y": "Evening", "v": 55},
                    {"x": "Thu", "y": "Morning", "v": 20},
                    {"x": "Thu", "y": "Midday", "v": 48},
                    {"x": "Thu", "y": "Afternoon", "v": 35},
                    {"x": "Thu", "y": "Evening", "v": 62},
                    {"x": "Fri", "y": "Morning", "v": 25},
                    {"x": "Fri", "y": "Midday", "v": 55},
                    {"x": "Fri", "y": "Afternoon", "v": 40},
                    {"x": "Fri", "y": "Evening", "v": 78}
                ],
                "title": "Orders by Day & Shift",
                "x_axis_label": "Day",
                "y_axis_label": "Shift",
                "v_label": "Orders"
            },
        ),
    ],
))
Heatmap takes a flat data array of {x, y, v} points (not a datasets list). v is the value used to determine color intensity.

Example: Box Plot

Show the statistical distribution (min, Q1, median, Q3, max) of values across categories. Provide raw values per category — quartiles are computed for you:
curl -X POST https://tako.com/api/v1/thin_viz/create/ \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Response Time by Region",
    "source": "Telemetry",
    "components": [
      {
        "component_type": "boxplot",
        "config": {
          "categories": [
            {
              "category": "US-East",
              "values": [42, 48, 51, 55, 58, 60, 62, 65, 68, 72, 75, 80, 85, 90, 110]
            },
            {
              "category": "US-West",
              "values": [38, 42, 45, 48, 50, 52, 55, 58, 62, 65, 70, 75, 82, 95, 120]
            },
            {
              "category": "EU",
              "values": [55, 60, 65, 70, 75, 80, 85, 90, 95, 100, 110, 120, 135, 150, 180]
            },
            {
              "category": "APAC",
              "values": [80, 90, 100, 110, 120, 130, 140, 150, 160, 175, 190, 210, 240, 280, 350]
            }
          ],
          "title": "p50/p95 Response Time by Region",
          "y_axis_label": "Response time",
          "units": "ms"
        }
      }
    ]
  }'
# Reuses the client from the first example above
card = client.create_card(CreateCardRequest(
    title="Response Time by Region",
    source="Telemetry",
    components=[
        ComponentConfig(
            component_type="boxplot",
            config={
                "categories": [
                    {
                        "category": "US-East",
                        "values": [
                            42,
                            48,
                            51,
                            55,
                            58,
                            60,
                            62,
                            65,
                            68,
                            72,
                            75,
                            80,
                            85,
                            90,
                            110
                        ]
                    },
                    {
                        "category": "US-West",
                        "values": [
                            38,
                            42,
                            45,
                            48,
                            50,
                            52,
                            55,
                            58,
                            62,
                            65,
                            70,
                            75,
                            82,
                            95,
                            120
                        ]
                    },
                    {
                        "category": "EU",
                        "values": [
                            55,
                            60,
                            65,
                            70,
                            75,
                            80,
                            85,
                            90,
                            95,
                            100,
                            110,
                            120,
                            135,
                            150,
                            180
                        ]
                    },
                    {
                        "category": "APAC",
                        "values": [
                            80,
                            90,
                            100,
                            110,
                            120,
                            130,
                            140,
                            150,
                            160,
                            175,
                            190,
                            210,
                            240,
                            280,
                            350
                        ]
                    }
                ],
                "title": "p50/p95 Response Time by Region",
                "y_axis_label": "Response time",
                "units": "ms"
            },
        ),
    ],
))
Box plot uses categories (not datasets) and each category has a values array of raw numbers.

Example: Treemap

Show hierarchical data as area-proportional rectangles — good for spend breakdowns or composition:
curl -X POST https://tako.com/api/v1/thin_viz/create/ \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Cloud Spend by Service",
    "source": "AWS Cost Explorer",
    "components": [
      {
        "component_type": "treemap",
        "config": {
          "datasets": [
            {
              "label": "Monthly Spend",
              "data": [
                {"x": "EC2", "y": 12500},
                {"x": "RDS", "y": 6800},
                {"x": "S3", "y": 3200},
                {"x": "Lambda", "y": 1450},
                {"x": "CloudFront", "y": 980},
                {"x": "DynamoDB", "y": 720},
                {"x": "ElastiCache", "y": 540},
                {"x": "Other", "y": 410}
              ],
              "units": "$"
            }
          ],
          "title": "AWS Spend by Service ($)"
        }
      }
    ]
  }'
# Reuses the client from the first example above
card = client.create_card(CreateCardRequest(
    title="Cloud Spend by Service",
    source="AWS Cost Explorer",
    components=[
        ComponentConfig(
            component_type="treemap",
            config={
                "datasets": [
                    {
                        "label": "Monthly Spend",
                        "data": [
                            {"x": "EC2", "y": 12500},
                            {"x": "RDS", "y": 6800},
                            {"x": "S3", "y": 3200},
                            {"x": "Lambda", "y": 1450},
                            {"x": "CloudFront", "y": 980},
                            {"x": "DynamoDB", "y": 720},
                            {"x": "ElastiCache", "y": 540},
                            {"x": "Other", "y": 410}
                        ],
                        "units": "$"
                    }
                ],
                "title": "AWS Spend by Service ($)"
            },
        ),
    ],
))
Each rectangle’s area is proportional to its y value.

Example: Waterfall

Show how a starting value changes through a series of additions and subtractions to reach an ending value. Use is_anchor: true for totals/subtotals (bars that start at zero):
curl -X POST https://tako.com/api/v1/thin_viz/create/ \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Income Statement",
    "source": "Q3 Earnings",
    "components": [
      {
        "component_type": "waterfall",
        "config": {
          "items": [
            {"category": "Revenue",          "value": 100.0, "is_anchor": true},
            {"category": "COGS",             "value": -38.0},
            {"category": "Gross Profit",     "value": 62.0,  "is_anchor": true},
            {"category": "OpEx",             "value": -28.0},
            {"category": "Operating Income", "value": 34.0,  "is_anchor": true},
            {"category": "Tax",              "value": -7.0},
            {"category": "Net Income",       "value": 27.0,  "is_anchor": true}
          ],
          "title": "Q3 Income Breakdown",
          "units": "$"
        }
      }
    ]
  }'
# Reuses the client from the first example above
card = client.create_card(CreateCardRequest(
    title="Income Statement",
    source="Q3 Earnings",
    components=[
        ComponentConfig(
            component_type="waterfall",
            config={
                "items": [
                    {"category": "Revenue", "value": 100.0, "is_anchor": True},
                    {"category": "COGS", "value": -38.0},
                    {
                        "category": "Gross Profit",
                        "value": 62.0,
                        "is_anchor": True
                    },
                    {"category": "OpEx", "value": -28.0},
                    {
                        "category": "Operating Income",
                        "value": 34.0,
                        "is_anchor": True
                    },
                    {"category": "Tax", "value": -7.0},
                    {"category": "Net Income", "value": 27.0, "is_anchor": True}
                ],
                "title": "Q3 Income Breakdown",
                "units": "$"
            },
        ),
    ],
))
By default, positive deltas are green and negative deltas are red. Anchor bars (is_anchor: true) are drawn as solid bars rising from zero.

Example: Sankey

Show directed flows between nodes — revenue splitting into cost and profit branches, a user funnel, energy flow, or any weighted graph. Provide a list of nodes and a list of links; every link’s source and target must reference a node id. Links must form a DAG (no cycles or self-loops); duplicate (source, target) pairs are summed.
curl -X POST https://tako.com/api/v1/thin_viz/create/ \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Q1 Income Statement",
    "source": "Company Financials",
    "components": [
      {
        "component_type": "sankey",
        "config": {
          "nodes": [
            {"id": "data_center", "label": "Data Center"},
            {"id": "gaming",      "label": "Gaming"},
            {"id": "revenue",     "label": "Revenue"},
            {"id": "cogs",        "label": "Cost of Revenue",  "polarity": "negative"},
            {"id": "gross",       "label": "Gross Profit",     "polarity": "positive"},
            {"id": "opex",        "label": "Operating Expenses", "polarity": "negative"},
            {"id": "op_profit",   "label": "Operating Profit", "polarity": "positive"},
            {"id": "tax",         "label": "Tax",              "polarity": "negative"},
            {"id": "net_profit",  "label": "Net Profit",       "polarity": "positive"}
          ],
          "links": [
            {"source": "data_center", "target": "revenue",   "value": 22.6},
            {"source": "gaming",      "target": "revenue",   "value": 2.6},
            {"source": "revenue",     "target": "cogs",      "value": 5.6},
            {"source": "revenue",     "target": "gross",     "value": 20.4},
            {"source": "gross",       "target": "opex",      "value": 3.5},
            {"source": "gross",       "target": "op_profit", "value": 17.3},
            {"source": "op_profit",   "target": "tax",       "value": 2.4},
            {"source": "op_profit",   "target": "net_profit","value": 14.9}
          ],
          "title": "Revenue to Net Profit",
          "units": "$B"
        }
      }
    ]
  }'
# Reuses the client from the first example above
card = client.create_card(CreateCardRequest(
    title="Q1 Income Statement",
    source="Company Financials",
    components=[
        ComponentConfig(
            component_type="sankey",
            config={
                "nodes": [
                    {"id": "data_center", "label": "Data Center"},
                    {"id": "gaming", "label": "Gaming"},
                    {"id": "revenue", "label": "Revenue"},
                    {
                        "id": "cogs",
                        "label": "Cost of Revenue",
                        "polarity": "negative"
                    },
                    {
                        "id": "gross",
                        "label": "Gross Profit",
                        "polarity": "positive"
                    },
                    {
                        "id": "opex",
                        "label": "Operating Expenses",
                        "polarity": "negative"
                    },
                    {
                        "id": "op_profit",
                        "label": "Operating Profit",
                        "polarity": "positive"
                    },
                    {"id": "tax", "label": "Tax", "polarity": "negative"},
                    {
                        "id": "net_profit",
                        "label": "Net Profit",
                        "polarity": "positive"
                    }
                ],
                "links": [
                    {
                        "source": "data_center",
                        "target": "revenue",
                        "value": 22.6
                    },
                    {"source": "gaming", "target": "revenue", "value": 2.6},
                    {"source": "revenue", "target": "cogs", "value": 5.6},
                    {"source": "revenue", "target": "gross", "value": 20.4},
                    {"source": "gross", "target": "opex", "value": 3.5},
                    {"source": "gross", "target": "op_profit", "value": 17.3},
                    {"source": "op_profit", "target": "tax", "value": 2.4},
                    {
                        "source": "op_profit",
                        "target": "net_profit",
                        "value": 14.9
                    }
                ],
                "title": "Revenue to Net Profit",
                "units": "$B"
            },
        ),
    ],
))
Each flow is colored by its target node’s polarity: positive renders green, negative red, and neutral (the default) gray. Use this to make a profit-vs-cost story read at a glance — leave upstream/source nodes neutral so only the meaningful splits carry color.

Sankey fields

FieldRequiredDescription
nodesyesList of nodes (min 2). Each has id (canonical key) and label (display string), plus optional polarity.
nodes[].polaritynopositive, negative, or neutral (default). Sets the node and its incoming flow color.
linksyesList of directed flows (min 1). Each has source (node id), target (node id), and value (positive number).
titlenoChart title.
unitsnoUnits for flow values (e.g. $, $B, %), used in tooltips.

Example: Marimekko

Show a two-level part-to-whole breakdown as a mosaic of variable-width stacked columns — market share by region and brand, spend by department and category, or contract obligations by agency and vendor. Each column’s width is proportional to its total, and each stacked segment’s height is its share within that column. Marimekko takes the same flat data array of {x, y, v} points as the heatmap: x is the column (X dimension), y is the stacked segment (Y dimension), and v is the cell magnitude.
curl -X POST https://tako.com/api/v1/thin_viz/create/ \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Smartphone Market Share",
    "source": "Internal Analytics",
    "components": [
      {
        "component_type": "marimekko",
        "config": {
          "data": [
            {"x": "North America", "y": "Apple",   "v": 52},
            {"x": "North America", "y": "Samsung", "v": 28},
            {"x": "North America", "y": "Google",  "v": 9},
            {"x": "Europe",        "y": "Samsung", "v": 34},
            {"x": "Europe",        "y": "Apple",   "v": 31},
            {"x": "Europe",        "y": "Xiaomi",  "v": 18},
            {"x": "Asia Pacific",  "y": "Xiaomi",  "v": 25},
            {"x": "Asia Pacific",  "y": "Samsung", "v": 22},
            {"x": "Asia Pacific",  "y": "Oppo",    "v": 19},
            {"x": "Asia Pacific",  "y": "Apple",   "v": 15}
          ],
          "title": "Units Sold by Region & Brand",
          "x_axis_label": "Region",
          "y_axis_label": "Brand",
          "units": "M units",
          "top_n_columns": 8,
          "top_m_segments": 6
        }
      }
    ]
  }'
# Reuses the client from the first example above
card = client.create_card(CreateCardRequest(
    title="Smartphone Market Share",
    source="Internal Analytics",
    components=[
        ComponentConfig(
            component_type="marimekko",
            config={
                "data": [
                    {"x": "North America", "y": "Apple", "v": 52},
                    {"x": "North America", "y": "Samsung", "v": 28},
                    {"x": "North America", "y": "Google", "v": 9},
                    {"x": "Europe", "y": "Samsung", "v": 34},
                    {"x": "Europe", "y": "Apple", "v": 31},
                    {"x": "Europe", "y": "Xiaomi", "v": 18},
                    {"x": "Asia Pacific", "y": "Xiaomi", "v": 25},
                    {"x": "Asia Pacific", "y": "Samsung", "v": 22},
                    {"x": "Asia Pacific", "y": "Oppo", "v": 19},
                    {"x": "Asia Pacific", "y": "Apple", "v": 15}
                ],
                "title": "Units Sold by Region & Brand",
                "x_axis_label": "Region",
                "y_axis_label": "Brand",
                "units": "M units",
                "top_n_columns": 8,
                "top_m_segments": 6
            },
        ),
    ],
))
Cells that share an (x, y) pair are summed first; a pair is then dropped only if its net value is non-positive (so a downward adjustment nets against a positive value in the same cell rather than being dropped on its own). The largest top_n_columns columns and, within each, the largest top_m_segments segments render individually; everything else rolls into an “Other” column / “Other” segment so the mosaic always conserves the total. Segments are colored from the theme palette and labeled on the chart canvas (no separate legend).

Marimekko fields

FieldRequiredDescription
datayesList of {x, y, v} cells. x is the column label, y is the stacked segment label, v is the cell magnitude.
titlenoChart title.
x_axis_labelnoLabel for the columns dimension (e.g. Region).
y_axis_labelnoLabel for the segments dimension (e.g. Brand).
unitsnoUnits for values (e.g. $, %), used in tooltips and on-canvas labels.
top_n_columnsnoColumns shown individually before the rest roll into an “Other” column (default 8).
top_m_segmentsnoSegments shown individually per column before the rest roll into an “Other” segment (default 6).

Combining Multiple Components

Cards can contain multiple components stacked together. This lets you build richer visualizations by pairing related data.

Financial Boxes + Timeseries Chart

Pair summary metrics with a trend chart:
curl -X POST https://tako.com/api/v1/thin_viz/create/ \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "AAPL Quarterly Overview",
    "source": "SEC Filings",
    "components": [
      {
        "component_type": "financial_boxes",
        "config": {
          "items": [
            {
              "header": "Revenue",
              "value": "$94.9B",
              "growth": {"formattedValue": "6.1% YoY", "value": 0.061}
            },
            {
              "header": "Net Income",
              "value": "$23.6B",
              "growth": {"formattedValue": "-3.4% YoY", "value": -0.034}
            },
            {
              "header": "EPS",
              "value": "$1.64"
            }
          ]
        }
      },
      {
        "component_type": "generic_timeseries",
        "config": {
          "datasets": [
            {
              "label": "Revenue",
              "data": [
                {"x": "2023-Q1", "y": 94.8},
                {"x": "2023-Q2", "y": 81.8},
                {"x": "2023-Q3", "y": 89.5},
                {"x": "2023-Q4", "y": 119.6},
                {"x": "2024-Q1", "y": 90.8},
                {"x": "2024-Q2", "y": 85.8},
                {"x": "2024-Q3", "y": 94.9}
              ],
              "units": "$"
            }
          ],
          "chart_type": "bar",
          "title": "Quarterly Revenue ($B)"
        }
      }
    ]
  }'
# Reuses the client from the first example above
card = client.create_card(CreateCardRequest(
    title="AAPL Quarterly Overview",
    source="SEC Filings",
    components=[
        ComponentConfig(
            component_type="financial_boxes",
            config={
                "items": [
                    {
                        "header": "Revenue",
                        "value": "$94.9B",
                        "growth": {"formattedValue": "6.1% YoY", "value": 0.061}
                    },
                    {
                        "header": "Net Income",
                        "value": "$23.6B",
                        "growth": {"formattedValue": "-3.4% YoY", "value": -0.034}
                    },
                    {"header": "EPS", "value": "$1.64"}
                ]
            },
        ),
        ComponentConfig(
            component_type="generic_timeseries",
            config={
                "datasets": [
                    {
                        "label": "Revenue",
                        "data": [
                            {"x": "2023-Q1", "y": 94.8},
                            {"x": "2023-Q2", "y": 81.8},
                            {"x": "2023-Q3", "y": 89.5},
                            {"x": "2023-Q4", "y": 119.6},
                            {"x": "2024-Q1", "y": 90.8},
                            {"x": "2024-Q2", "y": 85.8},
                            {"x": "2024-Q3", "y": 94.9}
                        ],
                        "units": "$"
                    }
                ],
                "chart_type": "bar",
                "title": "Quarterly Revenue ($B)"
            },
        ),
    ],
))

Header + Bar Chart

Add a styled header above any chart:
curl -X POST https://tako.com/api/v1/thin_viz/create/ \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Team Headcount",
    "components": [
      {
        "component_type": "header",
        "config": {
          "title": "Team Headcount by Department",
          "subtitle": "As of January 2025"
        }
      },
      {
        "component_type": "categorical_bar",
        "config": {
          "datasets": [
            {
              "label": "Headcount",
              "data": [
                {"x": "Engineering", "y": 142},
                {"x": "Sales", "y": 89},
                {"x": "Marketing", "y": 54},
                {"x": "Operations", "y": 67}
              ]
            }
          ]
        }
      }
    ]
  }'
# Reuses the client from the first example above
card = client.create_card(CreateCardRequest(
    title="Team Headcount",
    components=[
        ComponentConfig(
            component_type="header",
            config={
                "title": "Team Headcount by Department",
                "subtitle": "As of January 2025"
            },
        ),
        ComponentConfig(
            component_type="categorical_bar",
            config={
                "datasets": [
                    {
                        "label": "Headcount",
                        "data": [
                            {"x": "Engineering", "y": 142},
                            {"x": "Sales", "y": 89},
                            {"x": "Marketing", "y": 54},
                            {"x": "Operations", "y": 67}
                        ]
                    }
                ]
            },
        ),
    ],
))
Components render in the order they appear in the components array - top to bottom on the card.

Available Components

ComponentDescription
headerCard header with title and optional subtitle
generic_timeseriesLine, bar, or scatter timeseries charts
categorical_barBar chart with categorical x-axis (regions, products, etc.)
data_table_chartBar chart with auto-generated data table below
financial_boxesFinancial metric boxes with values and growth indicators
tableData table with configurable columns (string, number, date, percent, currency, boolean, rating), sorting, formatting, and pagination
timelineTimeline chart showing events or periods along a time axis
piePie chart showing proportional data as slices of a circle
histogramHistogram chart showing frequency distribution of values
scatterScatter plot showing relationships between two continuous variables
bubbleBubble chart (scatter plot with size dimension) for 3-variable data
choroplethChoropleth map showing geographic data with color intensity by region
heatmap2D heatmap with color intensity representing values
boxplotBox plot showing statistical distributions (min, Q1, median, Q3, max)
treemapTreemap chart showing hierarchical data as proportional rectangles
waterfallWaterfall chart showing incremental positive/negative changes
sankeySankey diagram showing directed flows between nodes (revenue → cost/profit, funnels, energy flow)
marimekkoMarimekko (mosaic) chart showing a two-level part-to-whole breakdown as variable-width stacked columns (region × brand, agency × vendor)