Charts
A chart is a saved query with a visual config. Create it, share a link, done. No dashboard builder, no drag-and-drop - just data rendered as a chart behind a URL.
Why Charts Exist
rawquery is not a BI tool. Charts solve the last mile problem: you wrote a SQL query, got the answer, and now someone else needs to see it. A Slack message with a screenshot doesn't cut it - it's stale the moment you send it. A live link does.
The philosophy: declarative over interactive. Charts are JSON configs. You describe what you want (bar chart, x is month, y is revenue) and rawquery renders it. No WYSIWYG. No canvas. No state to corrupt.
If you need Sankey diagrams, pivot tables, or cross-filtering - use Metabase, Evidence, or Superset on top of rawquery's wire protocol. Charts & Pages are for the 80% case: share a number, a trend, a breakdown.
Quick Start
Every chart is backed by a saved query. Create the query first, then the chart:
# 1. Save a queryrq queries create monthly-revenue \ --sql "SELECT month, revenue FROM billing.mrr ORDER BY month"
# 2. Create a chartrq charts create mrr \ --query monthly-revenue \ --type line \ --x month \ --y revenue
# 3. Share itrq charts publish mrr# -> https://rawquery.dev/c/abc123# 1. Save a queryrq queries create monthly-revenue \ --sql "SELECT month, revenue FROM billing.mrr ORDER BY month"
# 2. Create a chartrq charts create mrr \ --query monthly-revenue \ --type line \ --x month \ --y revenue
# 3. Share itrq charts publish mrr# -> https://rawquery.dev/c/abc123That's it. Anyone with the link sees a live chart. No login, no account needed.
Chart Types
| Type | Use Case | Required Fields |
|---|---|---|
bar | Categorical comparison (revenue by plan) | x, y |
horizontal_bar | Rankings, long labels (top customers) | x, y |
line | Time series, trends (MRR over time) | x, y |
area | Cumulative, volume (total signups) | x, y |
scatter | Correlation (price vs. churn) | x, y |
pie | Part-of-whole (revenue by region) | label, value |
number | Single KPI (current MRR, active users) | value |
table | Raw data display | (none) |
Config Reference
The chart config is a JSON object stored alongside the chart. You can set fields via CLI flags or the API:
| Field | Type | Description |
|---|---|---|
type | string | Chart type (required). See table above. |
x | string | X-axis column name |
y | string | Y-axis column name |
y2 | string | Second y-axis column for dual-axis charts |
label | string | Label column (pie charts) |
value | string | Value column (pie, number) |
title | string | Display title (defaults to chart name) |
color | string | Primary color as hex (#2563EB) |
colors | object | Color map by series or label value ({"US": "#2563EB", "EU": "#DC2626"}) |
group_by | string | Column to group/stack by (creates one series per group value) |
sort | string | Sort data by y-value: asc, desc, or none |
y_format | string | Format string for y-axis values ($,.0f ,.0f .1% .2f d) |
x_format | string | Format string for x-axis values |
show_legend | boolean | Show legend (auto-enabled when multiple series) |
show_grid | boolean | Show grid lines (default: true) |
height | integer | Chart height in px (100-1000, default: 300) |
Examples
Revenue by Region (Grouped Bar)
# Query returns: month, revenue, regionrq charts create revenue-by-region \ --query regional-revenue \ --type bar \ --x month \ --y revenue
# Add grouping + colors via APIcurl -X PATCH /api/v1/workspaces/{workspace_id}/charts/revenue-by-region \ -H "Authorization: Bearer ..." \ -H "Content-Type: application/json" \ -d '{"config": { "type": "bar", "x": "month", "y": "revenue", "group_by": "region", "colors": {"US": "#2563EB", "EU": "#059669", "APAC": "#D97706"}, "y_format": "$,.0f" }}'# Query returns: month, revenue, regionrq charts create revenue-by-region \ --query regional-revenue \ --type bar \ --x month \ --y revenue
# Add grouping + colors via APIcurl -X PATCH /api/v1/workspaces/{workspace_id}/charts/revenue-by-region \ -H "Authorization: Bearer ..." \ -H "Content-Type: application/json" \ -d '{"config": { "type": "bar", "x": "month", "y": "revenue", "group_by": "region", "colors": {"US": "#2563EB", "EU": "#059669", "APAC": "#D97706"}, "y_format": "$,.0f" }}'Revenue + Users Dual Axis
# Query returns: month, revenue, active_userscurl -X POST /api/v1/workspaces/{workspace_id}/charts \ -H "Authorization: Bearer ..." \ -H "Content-Type: application/json" \ -d '{"name": "rev-and-users", "query_name": "monthly-metrics", "config": { "type": "line", "x": "month", "y": "revenue", "y2": "active_users", "y_format": "$,.0f", "colors": {"active_users": "#059669"} }}'# Query returns: month, revenue, active_userscurl -X POST /api/v1/workspaces/{workspace_id}/charts \ -H "Authorization: Bearer ..." \ -H "Content-Type: application/json" \ -d '{"name": "rev-and-users", "query_name": "monthly-metrics", "config": { "type": "line", "x": "month", "y": "revenue", "y2": "active_users", "y_format": "$,.0f", "colors": {"active_users": "#059669"} }}'Top Customers (Sorted Bar)
rq charts create top-customers \ --query customer-revenue \ --type horizontal_bar \ --x customer \ --y revenue
# Add sorting + format via APIcurl -X PATCH /api/v1/workspaces/{workspace_id}/charts/top-customers \ -d '{"config": { "type": "horizontal_bar", "x": "customer", "y": "revenue", "sort": "desc", "y_format": "$,.0f" }}'rq charts create top-customers \ --query customer-revenue \ --type horizontal_bar \ --x customer \ --y revenue
# Add sorting + format via APIcurl -X PATCH /api/v1/workspaces/{workspace_id}/charts/top-customers \ -d '{"config": { "type": "horizontal_bar", "x": "customer", "y": "revenue", "sort": "desc", "y_format": "$,.0f" }}'Single KPI
rq charts create current-mrr \ --query mrr-total \ --type number \ --value total_mrrrq charts create current-mrr \ --query mrr-total \ --type number \ --value total_mrrPublishing & Sharing
Publishing generates a public URL. Anyone with the link can view the chart - no login, no account. Unpublishing kills the link instantly.
# Publish - generates a public URLrq charts publish mrr# -> https://rawquery.dev/c/abc123
# With password protectionrq charts publish mrr --password mySecret
# Revoke accessrq charts unpublish mrr# Publish - generates a public URLrq charts publish mrr# -> https://rawquery.dev/c/abc123
# With password protectionrq charts publish mrr --password mySecret
# Revoke accessrq charts unpublish mrrPublic endpoints are rate-limited to 30 requests/minute per chart. Charts work in iframes for embedding.
CLI Commands
rq charts # List all chartsrq charts create <name> \ --query <saved-query> \ --type bar \ [--x col] [--y col] \ [--value col] [--label col] \ [--title "Display Title"]rq charts show <name> # View chart configrq charts update <name> [--type ...] [--x ...] [--y ...]rq charts delete <name> # Fails if referenced by a pagerq charts delete <name> --force # Force deleterq charts publish <name> [--password]rq charts unpublish <name>rq charts # List all chartsrq charts create <name> \ --query <saved-query> \ --type bar \ [--x col] [--y col] \ [--value col] [--label col] \ [--title "Display Title"]rq charts show <name> # View chart configrq charts update <name> [--type ...] [--x ...] [--y ...]rq charts delete <name> # Fails if referenced by a pagerq charts delete <name> --force # Force deleterq charts publish <name> [--password]rq charts unpublish <name>Format Strings
Use y_format and x_format to control how
axis values display. Supports a subset of D3 format syntax:
| Format | Example Input | Output |
|---|---|---|
$,.0f | 1234567 | $1,234,567 |
,.0f | 1234567 | 1,234,567 |
.1% | 0.123 | 12.3% |
.2f | 3.14159 | 3.14 |
d | 1234 | 1,234 |