Guides/How to build a dashboard from CSV or JSON data

How to build a dashboard from CSV or JSON data

Your data. One API call. Shareable URL.

Updated March 2026

You have a spreadsheet, a JSON export, or a database dump. You want a dashboard. You do not want to set up Metabase or write D3 code for this. Sutrena dashboards accept inline JSON or uploaded CSV. Define widgets with a JSON DSL, point them at your columns, get a shareable URL. No frontend. No database. The dashboard renders with recharts and auto-refreshes every 30 seconds.

1. Create a dashboard from inline JSON

If you already have the data in memory (an agent parsed it, a script produced it, you copied it from an API response), pass it directly as the data field. Works for up to 1,000 rows or 1MB, whichever comes first. Good for small datasets where the overhead of a file upload is not worth it.

curl -X POST https://sutrena.com/api/dashboards \
  -H "Authorization: Bearer st_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Q1 Sales",
    "isPublic": true,
    "data": [
      { "rep": "Alice", "region": "West", "deal_size": 12000, "closed_date": "2026-01-15" },
      { "rep": "Bob", "region": "East", "deal_size": 8500, "closed_date": "2026-01-22" },
      { "rep": "Alice", "region": "West", "deal_size": 15000, "closed_date": "2026-02-03" },
      { "rep": "Carol", "region": "East", "deal_size": 9200, "closed_date": "2026-02-18" },
      { "rep": "Bob", "region": "West", "deal_size": 11000, "closed_date": "2026-03-01" }
    ],
    "dsl": {
      "version": 1,
      "widgets": [
        { "type": "metric_card", "title": "Total Deals", "value": "count(*)" },
        { "type": "metric_card", "title": "Total Revenue", "value": "sum(deal_size)" },
        { "type": "pie_chart", "title": "Revenue by Region", "groupBy": "region", "aggregate": "sum(deal_size)" },
        { "type": "bar_chart", "title": "Revenue per Rep", "groupBy": "rep", "aggregate": "sum(deal_size)" },
        { "type": "data_table", "title": "All Deals", "columns": ["rep", "region", "deal_size", "closed_date"], "limit": 25 }
      ]
    }
  }'

# Response:
# {
#   "id": "dsh_q1sales",
#   "title": "Q1 Sales",
#   "dashboardUrl": "https://sutrena.com/d/dsh_q1sales",
#   "dataSource": "inline",
#   "rowCount": 5
# }

2. Upload a CSV and create a dashboard

For larger datasets (up to 10MB, 100K rows, 50 columns), upload a CSV file first, then reference it when creating the dashboard. Three steps: presign the upload, PUT the file, create the dashboard with the returned csvObjectId. Sutrena auto-detects column types (numbers, dates, booleans, strings) from the first 20 rows.

# Step 1: Get a presigned upload URL
curl -X POST https://sutrena.com/api/dashboards/upload \
  -H "Authorization: Bearer st_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{"filename": "sales-2026.csv", "sizeBytes": 524288}'

# Response:
# {
#   "csvObjectId": "obj_abc123",
#   "uploadUrl": "https://r2.example.com/presigned...",
#   "uploadHeaders": { "Content-Type": "text/csv" }
# }

# Step 2: Upload the file to the presigned URL
curl -X PUT "UPLOAD_URL_FROM_STEP_1" \
  -H "Content-Type: text/csv" \
  --data-binary @sales-2026.csv

# Step 3: Create the dashboard referencing the uploaded CSV
curl -X POST https://sutrena.com/api/dashboards \
  -H "Authorization: Bearer st_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Sales Report 2026",
    "csvObjectId": "obj_abc123",
    "isPublic": true,
    "dsl": {
      "version": 1,
      "widgets": [
        { "type": "metric_card", "title": "Total Rows", "value": "count(*)" },
        { "type": "metric_card", "title": "Avg Deal Size", "value": "avg(deal_size)" },
        { "type": "pie_chart", "title": "Revenue by Region", "groupBy": "region", "aggregate": "sum(deal_size)" },
        { "type": "bar_chart", "title": "Monthly Revenue", "groupBy": "$closed_date:month", "aggregate": "sum(deal_size)" },
        { "type": "line_chart", "title": "Deals Over Time", "groupBy": "$closed_date:day" },
        { "type": "data_table", "title": "Recent Deals", "columns": ["rep", "region", "deal_size", "closed_date"], "limit": 50, "sort": "newest" }
      ]
    }
  }'

# Response:
# {
#   "id": "dsh_sales2026",
#   "dashboardUrl": "https://sutrena.com/d/dsh_sales2026",
#   "dataSource": "csv",
#   "rowCount": 4823,
#   "columnCount": 8
# }

3. Choose the right groupBy for your data

groupBy controls how charts slice your data. Two kinds: field groupBy and time groupBy. Field groupBy uses a column name directly. The chart counts rows per unique value. Good for categorical data like region, status, or rep name. Works with pie_chart, bar_chart. Time groupBy uses the format $column_name:interval where interval is day, week, or month. It buckets date values into time periods and counts rows per bucket. Required for line_chart. Also works with bar_chart for time-series bar views. Pie charts only accept field groupBy (no time groupBy). Line charts only accept time groupBy. Bar charts accept both.

# Field groupBy — count rows per unique value
{ "type": "pie_chart", "title": "By Region", "groupBy": "region" }
# If your data has region: "West", "East", "West", "East", "West"
# → West: 3, East: 2

# Time groupBy — bucket dates and count per period
{ "type": "line_chart", "title": "Daily Deals", "groupBy": "$closed_date:day" }
# Buckets each closed_date into its calendar day

{ "type": "bar_chart", "title": "Monthly Deals", "groupBy": "$closed_date:month" }
# Buckets into months: 2026-01, 2026-02, 2026-03

{ "type": "bar_chart", "title": "Weekly Deals", "groupBy": "$closed_date:week" }
# Buckets into ISO weeks starting Monday

# metric_card — counts rows, no groupBy needed
{ "type": "metric_card", "title": "Total", "value": "count(*)" }
# count(field_name) counts non-null values of that field
{ "type": "metric_card", "title": "Has Email", "value": "count(email)" }

FAQ

Can I update the data in a dashboard?

No. Inline and CSV dashboards are static snapshots. To update, delete the old dashboard and create a new one with fresh data. If you need live-updating dashboards, create a form-based dashboard instead. Form dashboards pull from live submissions and refresh every 30 seconds.

What CSV formats are supported?

Standard CSV with a header row. UTF-8 encoding (BOM is handled automatically). Sutrena auto-detects column types from the first 20 rows: numbers, ISO dates (2026-01-15 or 2026-01-15T10:30:00Z), booleans (true/false), and strings. Max file size: 10MB. Max rows: 100,000. Max columns: 50.

Does count(*) sum my numbers?

No. count(*) counts rows. count(field_name) counts non-null values of that field. To sum numeric values, use sum(field_name) instead. For example, a metric_card with "value": "sum(revenue)" gives you the total. You can also use avg(field_name), min(field_name), and max(field_name). Chart widgets (pie_chart, bar_chart, line_chart) accept an optional aggregate field with the same expressions -- e.g. "aggregate": "sum(revenue)" to show totals per group instead of counts.

Can I combine form data and CSV data in one dashboard?

No. Each dashboard has exactly one data source: a formId, inline JSON data, or a csvObjectId. You cannot mix them. Create separate dashboards for each data source.

How long does the dashboard URL last?

As long as your account exists. Paid plans: indefinitely. Free plan: as long as the account is active. Unclaimed trial accounts auto-delete after 24 hours, taking all dashboards with them. Claim your account to make it permanent.

What is Sutrena?

Sutrena is the web runtime for AI agents. Three primitives — pages, forms, and dashboards — accessible through one API. Your agent creates web artifacts, humans interact with them, and your agent gets the data back. Framework-agnostic. Works from any MCP client or HTTP client.

Get started in two API calls

1. Get a trial key (no auth, no signup)

curl -X POST https://sutrena.com/api/trial

2. Create a form + dashboard from a template

curl -X POST https://sutrena.com/api/forms \
  -H "Authorization: Bearer st_trial_xxx" \
  -H "Content-Type: application/json" \
  -d '{"templateId": "waitlist", "createDashboard": true}'

Ready to build?

Get a trial API key instantly with no signup, or create an account for the full experience.

How to build a dashboard from CSV or JSON data — Sutrena | Sutrena