Insights
HTTP API routes for insights.
Insights are org-scoped saved queries and built-in Results charts. {ref} is
an ins_... id, an immutable slug, or a chart reference returned by discovery.
Percent-encode the reference when inserting it into a URL path.
| Route | Use | CLI equivalent |
|---|---|---|
GET /insights | List insight metadata. | ax insight list |
POST /insights | Create an insight. | ax insight create |
GET /insights/{ref} | Execute or inspect one insight. | ax insight view |
POST /insights/{ref}/execute | Execute a chart with parameters. | ax insight view --parameters --json |
POST /insights/{ref}/share | Publish an immutable public insight URL. | ax insight share |
PATCH /insights/{ref} | Update mutable fields. | ax insight edit |
DELETE /insights/{ref} | Delete an insight. | ax insight delete |
Every route takes org_id (required only when the key can see several orgs).
Parameters are optional unless marked required. Insight export stays
client-side over the live GET response; there is no server export route.
GET /api/v1/insights
List insight metadata; no SQL runs.
curl -H "Authorization: Bearer $AX_API_KEY" \
"https://app.514.ax/api/v1/insights?search=cost&limit=20"| Parameter | What it does |
|---|---|
search | Text search over slug, heading, description, owner (query is an alias). |
owner | Original owner's user id (owner_user_id is an alias). |
experiment / run | Provenance filters (experiment_id / run_id are aliases). |
label | Require this label. |
limit / page_token | Pagination (page_size is an alias for limit). |
The response includes nextPageToken when another page exists.
Use experiment to discover the experiment's three built-in charts: test-results
heatmap (tests), quality/efficiency scatterplot (scatter), and single-metric
comparison (metric). These charts are available for existing and new
experiments. Use the returned reference rather than a chart's display title.
POST /api/v1/insights
Create an insight.
curl -X POST \
-H "Authorization: Bearer $AX_API_KEY" \
-H "Content-Type: application/json" \
-d '{"heading":"Cross-experiment cost","sql":"SELECT ..."}' \
"https://app.514.ax/api/v1/insights"| Body field | What it does |
|---|---|
heading | Required. Human heading; mints the slug unless slug is given. |
sql | Required. The SQL body. |
slug | Explicit slug (immutable after create). |
description / labels | Optional metadata. |
force | Overwrite mutable content when the slug already exists. |
provenance | {kind, experimentId, runId} where kind is none, experiment, or run. |
dataSchema | The results family the SQL targets: session_data_v1. With provenance, the family is resolved from the target and a mismatching value is rejected. Omitted on a force overwrite preserves the existing stamp. legacy names the retired V1 pipeline; an insight stamped legacy cannot be viewed or shared. |
Actor and org fields always come from authentication.
GET /api/v1/insights/{ref}
Execute the stored SQL live (the default, like ax insight view).
| Parameter | What it does |
|---|---|
sql_only | true returns metadata and available SQL without executing (sqlOnly is an alias). |
limit | Max live SQL rows, up to 10,000. Not supported for built-in chart execution. |
For a built-in chart, inspect insight.chartKind, parameterSchemaJson,
responseSchemaJson, and availableValuesJson. Parse each *Json field as
JSON. The metadata describes parameter types, defaults, allowed values, response
fields, and the experiment's available filters.
POST /api/v1/insights/{ref}/execute
Retrieve chart data with the same grouping and filtering as the Results page.
curl -X POST \
-H "Authorization: Bearer $AX_API_KEY" \
-H "Content-Type: application/json" \
-d '{"parameters":{"group_by":"model"},"result_view":"summary"}' \
"$AX_BASE_URL/api/v1/insights/$ENCODED_INSIGHT_REF/execute?org_id=$AX_ORG_ID"Set AX_BASE_URL to https://app.514.ax and ENCODED_INSIGHT_REF to the
percent-encoded reference returned by discovery. Use your organization's id for
AX_ORG_ID.
| Body field | What it does |
|---|---|
parameters | Chart parameters as a JSON object. Omitted parameters use their documented defaults. |
result_view | summary (default), points, or runs. Heatmaps support summary and runs. |
group_value | Required for runs. Exact group value. An empty string selects the group with no recorded dimension value. |
test_name | Required for heatmap runs. Exact test name for cell drill-down. |
cursor | Continuation cursor from the previous points or runs response. |
Common chart parameters:
| Parameter | What it does |
|---|---|
group_by | variant (default), model, agent, agent_mode, prompt, environment, or product. |
version | Experiment version reference or all. Omit to use the Results page's initial version scope. |
agents, agent_modes, models, products, environments, prompt_ids | Lists of filter values. Empty lists apply no filter. |
full_pass_only | Keep only runs whose tests all passed. Defaults to false. |
include_test_aware | Include runs with a test-awareness verdict. Defaults to false. |
test_search | Heatmap only: trimmed, case-insensitive substring of the test name. |
metric | Single-metric comparison only: passRate, costUsd (default), wallSeconds, toolCalls, toolFailures, inputTokens, outputTokens, or totalTokens. |
The execution envelope contains chartDataJson, a JSON string holding the
chart result. Parse it once after parsing the HTTP response:
const envelope = await response.json();
const chart = JSON.parse(envelope.chartDataJson);| Chart | Summary data |
|---|---|
| Heatmap | {groupBy, cells} with passed, failed, unresolved, and available errored/skipped counts. |
| Scatterplot | {groupBy, groups, totals} with per-group metric statistics and covariance. |
| Single-metric comparison | {groupBy, groups} with named metric distributions, including quartiles. |
Inspect responseSchemaJson for the complete field definitions. Pass rates
are fractions from 0 to 1. costUsd is USD, wallSeconds is seconds, and token
counts are separate from cost. Missing metric values remain null rather than
zero.
For points and runs, keep the same parameters and pass the returned nextCursor
as cursor until it is null. Summary statistics always cover the complete
filtered population, independently of point/run pagination. A GUI display limit
does not restrict programmatic retrieval.
Built-in chart definitions cannot be edited, deleted, or published through the saved-SQL insight mutation routes. Existing saved-SQL responses retain their columns/rows format.
Use chart data on your website
Call the API from your website's server and send the chart data your visitors need to the frontend. Keep the API key in your server's secret configuration. Protect your website route with your own authentication if the results are private.
This server-side TypeScript helper retrieves one fixed insight's summary. Set
AX_INSIGHT_REF to a reference from discovery, and configure AX_ORG_ID,
AX_API_KEY, and AX_BASE_URL on your server.
export async function loadChartSummary() {
const { AX_BASE_URL, AX_ORG_ID, AX_API_KEY, AX_INSIGHT_REF } = process.env;
if (!AX_BASE_URL || !AX_ORG_ID || !AX_API_KEY || !AX_INSIGHT_REF) {
throw new Error("Configure the chart API connection on the server.");
}
const url = new URL(
`/api/v1/insights/${encodeURIComponent(AX_INSIGHT_REF)}/execute`,
AX_BASE_URL,
);
url.searchParams.set("org_id", AX_ORG_ID);
const response = await fetch(url, {
method: "POST",
headers: {
Authorization: `Bearer ${AX_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
parameters: { group_by: "model" },
result_view: "summary",
}),
cache: "no-store",
});
if (!response.ok) {
throw new Error(`Chart request failed (${response.status}).`);
}
const envelope = await response.json();
if (typeof envelope.chartDataJson !== "string") {
throw new Error("The selected insight did not return chart data.");
}
return JSON.parse(envelope.chartDataJson);
}Render the returned named metrics with your chart library. To reproduce a specific Results view, use the parameters copied from Use data, including its version, filters, and selected metric. See the CLI reference for the equivalent command.
POST /api/v1/insights/{ref}/share
Create or reuse an insight's immutable public publication. The response is
{"url":"https://.../embed/insights/<token>"}. The URL is public: anyone who
has it can see the publication's live query result. The query definition and
presentation metadata are frozen on first share, while underlying data remains
live. Source edits do not refresh the publication, and repeated requests return
the same URL. Deleting the source insight is the only revocation mechanism in
this release.
PATCH /api/v1/insights/{ref}
Partially update mutable fields. Ids and slugs are immutable.
| Body field | What it does |
|---|---|
heading | New heading. |
sql | New SQL. |
description | New description; an empty string clears it. |
labels | Replace the label set; an empty array or clear_labels: true clears it (not both). |
DELETE /api/v1/insights/{ref}
Delete an insight. Deleting a missing reference is idempotent and returns
deleted: false.