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.

RouteUseCLI equivalent
GET /insightsList insight metadata.ax insight list
POST /insightsCreate an insight.ax insight create
GET /insights/{ref}Execute or inspect one insight.ax insight view
POST /insights/{ref}/executeExecute a chart with parameters.ax insight view --parameters --json
POST /insights/{ref}/sharePublish 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"
ParameterWhat it does
searchText search over slug, heading, description, owner (query is an alias).
ownerOriginal owner's user id (owner_user_id is an alias).
experiment / runProvenance filters (experiment_id / run_id are aliases).
labelRequire this label.
limit / page_tokenPagination (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 fieldWhat it does
headingRequired. Human heading; mints the slug unless slug is given.
sqlRequired. The SQL body.
slugExplicit slug (immutable after create).
description / labelsOptional metadata.
forceOverwrite mutable content when the slug already exists.
provenance{kind, experimentId, runId} where kind is none, experiment, or run.
dataSchemaThe 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).

ParameterWhat it does
sql_onlytrue returns metadata and available SQL without executing (sqlOnly is an alias).
limitMax 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 fieldWhat it does
parametersChart parameters as a JSON object. Omitted parameters use their documented defaults.
result_viewsummary (default), points, or runs. Heatmaps support summary and runs.
group_valueRequired for runs. Exact group value. An empty string selects the group with no recorded dimension value.
test_nameRequired for heatmap runs. Exact test name for cell drill-down.
cursorContinuation cursor from the previous points or runs response.

Common chart parameters:

ParameterWhat it does
group_byvariant (default), model, agent, agent_mode, prompt, environment, or product.
versionExperiment version reference or all. Omit to use the Results page's initial version scope.
agents, agent_modes, models, products, environments, prompt_idsLists of filter values. Empty lists apply no filter.
full_pass_onlyKeep only runs whose tests all passed. Defaults to false.
include_test_awareInclude runs with a test-awareness verdict. Defaults to false.
test_searchHeatmap only: trimmed, case-insensitive substring of the test name.
metricSingle-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);
ChartSummary 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 fieldWhat it does
headingNew heading.
sqlNew SQL.
descriptionNew description; an empty string clears it.
labelsReplace 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.