REST API Reference
This reference is grounded in the analytics service's source-owned OpenAPI 3.1.1 documents. The portal vendors the aggregate document and serves it at /openapi.json; it covers the latest 20260709 contract, the deprecated /v1 compatibility contract, and shared MCP/OAuth paths.
Authentication
REST callers can authenticate with:
Authorization: Bearer <token>
Authorization is preferred. The portal's own live tools call server-side BFF routes so bearer tokens do not live in browser localStorage.
REST Query Flow
Production REST path: build or receive a trusted structured analytics query, optionally validate it, then call POST /api/20260709/queries/run. The run endpoint validates again before execution, so backend integrations should treat this as the primary REST execution call.
analytics_query.execution.status, execution.result, and table_preview when available.Endpoints
| Method | Path | Purpose |
|---|---|---|
GET | /health | Service liveness check. |
GET | /openapi.json | Aggregate machine-readable contract for every supported public version. |
GET | /api/20260709/openapi.json | Latest-version OpenAPI document. |
GET | /api/20260709/catalog | Normalized metric, dimension, and client catalog. |
GET | /api/20260709/clients | Paginated active clients available to the caller token. |
GET | /api/20260709/clients/{client_id}/freshness | Latest successful regular DBT attribution update and vendor pull for one token-authorized client. |
POST | /api/20260709/catalog/search | Search metrics, dimensions, clients, and indexed dimension values. |
POST | /api/20260709/questions/compile | Compile and validate natural-language questions without execution. |
POST | /api/20260709/questions/enqueue | Compile, validate, and enqueue async execution. |
POST | /api/20260709/questions/run | Compile, validate, enqueue, poll, and fetch a result. |
POST | /api/20260709/queries/run | Validate and run a trusted structured analytics query directly. |
POST | /api/20260709/queries/explain | Explain validation or result metadata. |
GET | /api/20260709/mcp/tools | Inspect advertised MCP tools. |
POST | /api/20260709/mcp/tools/call | Call an MCP tool over REST for inspection. |
Question endpoints are documented for agent and MCP-style workflows. Backend REST integrations should prefer direct structured-query execution through POST /api/20260709/queries/run.
Client Listing
Use GET /api/20260709/clients when an integration only needs accessible client IDs and names. It is lighter than fetching the full catalog and is the preferred backing endpoint for searchable client pickers.
| Query parameter | Notes |
|---|---|
q | Optional substring filter across client ID, display name, external name, parent/child IDs, and stack name. |
limit | Defaults to 100 and is capped at 500. |
offset | Pagination offset. Continue with next_offset until it is null. |
The response includes client_count, returned_count, next_offset, and clients. Each client contains id, client_id, optional display/external names, optional stack metadata, parent client ID, and child client IDs.
Data Freshness
Use GET /api/20260709/clients/{client_id}/freshness before
interpreting results that cover today or yesterday, or whenever ingestion lag
could affect an answer.
curl -sS "https://api.admetrics.io/api/20260709/clients/2938354/freshness" \
-H "Authorization: Bearer ${AQL_BEARER_TOKEN}"
{
"client_id": "2938354",
"observed_at": "2026-08-03T10:00:00Z",
"dbt": { "last_success_at": "2026-08-03T08:00:00Z" },
"vendor_pull": {
"last_success_at": "2026-08-03T09:00:00Z",
"vendors": ["google"]
}
}
All timestamps are UTC completion times. Both checkpoints include only regular
successful runs; backfills are excluded. A token-authorized client with no
successful history returns null for the relevant timestamp. Missing or
invalid credentials return 401, and a valid token without access to the
requested client returns 403.
Common Natural-Language Request Fields
| Field | Notes |
|---|---|
question | Required for /api/20260709/questions/*. Ask for one atomic analytics query. |
client_id, client_ids | Optional but recommended. |
date_context | Optional YYYY-MM-DD base date for relative phrases. |
metric_ids, dimension_ids, sort_id, sort_direction | Exact catalog overrides. |
attribution_model, attribution_window, metric_params | Optional attribution parameters validated against the live catalog. |
limit | Optional row limit. |
format, result_format | records, rows, columnar, csv, txt, xlsx, dataframe, or arrow. |
wait_for_result | Optional async behavior. |
timeout_ms, poll_interval_ms | Optional polling controls. |
Structured Analytics Query Run Fields
| Field | Notes |
|---|---|
analytics_query | Required non-empty object. Use the structured query shape with options, shape, select, and filters. |
query_source | Required. Use user_provided_query for Query Builder or backend-provided JSON, or compiled_question for compiler output. |
format, result_format | Optional output format override. result_format is preferred when both are supplied. |
timeout_ms, poll_interval_ms | Optional polling controls for run-and-wait flows. |
Metadata-Aware Filters
The Query Builder can add any token-visible metric or dimension as an additional filter. Client and date scope stay in their dedicated controls, filter-only fields do not need to be selected as outputs, and additional rows are combined with AND.
Builder selections and filter editor values are restored when you navigate away and return in the same browser tab. This session-scoped workspace stores query configuration only; authentication credentials and query results are not persisted there.
| Field class | Builder operators | AQL operators |
|---|---|---|
| Numeric | equals, comparisons, between, in/not in, exists/not exists | $eq, $ne, $gt, $gte, $lt, $lte, $in, $nin, $exists, $notexists |
| Date | on, before/after, between, in/not in, exists/not exists | $eq, $ne, $gt, $gte, $lt, $lte, $in, $nin, $exists, $notexists |
| Text | equals, in/not in, contains/not contains, regex/not regex, exists/not exists | $eq, $ne, $in, $nin, $regex, $notregex, $exists, $notexists |
| Identifier | equals, in/not in, exists/not exists | $eq, $ne, $in, $nin, $exists, $notexists |
| Boolean | is/is not, exists/not exists | $eq, $ne, $exists, $notexists |
Contains filters escape the typed value and emit a case-insensitive regex. Explicit regex operators preserve the raw pattern for expert use. Indexed dimensions offer client-scoped value suggestions through /api/20260709/catalog/search, but typed values remain valid:
{
"dimension": "campaign_name",
"value_query": "brand",
"client_ids": [2617401],
"value_limit": 12
}
A query can repeat a field; AQL merges the constraints. A range and a case-insensitive contains filter serialize as:
"filters": [
{ "id": "client_id", "filter": { "$in": [2617401] } },
{ "id": "date", "filter": { "$gte": "2026-06-01", "$lte": "2026-06-30" } },
{ "id": "attributed_events.visits", "filter": { "$gte": 1000, "$lte": 5000 } },
{ "id": "campaign_name", "filter": { "$regex": "(?i).*brand.*" } }
]
Return Formats
| Format | Notes |
|---|---|
records | JSON-style row objects. |
rows | Row-oriented output. |
columnar | Column-oriented output. |
csv | Comma-separated text payload. |
txt | Text payload. |
xlsx | Spreadsheet payload. |
dataframe | DataFrame-oriented payload for connector workflows. |
arrow | Arrow binary payload. This is the Query Builder default; responses may include execution.result.table_preview for UI inspection. |
json | Alias for records. |
text | Alias for txt. |
Return Format Examples
These examples show the shape a run response might expose under execution.result. Exact wrappers and metadata can vary by endpoint, timeout behavior, and format.
records or json
{
"format": "records",
"content_type": "application/json",
"data": [
{
"date": "2026-06-01",
"campaign_name": "Brand Search",
"spend": 1284.5,
"revenue": 8120.2,
"roas": 6.32
}
]
}
rows
{
"format": "rows",
"columns": ["date", "campaign_name", "spend", "revenue", "roas"],
"data": [
["2026-06-01", "Brand Search", 1284.5, 8120.2, 6.32]
]
}
columnar
{
"format": "columnar",
"data": {
"date": ["2026-06-01"],
"campaign_name": ["Brand Search"],
"spend": [1284.5],
"revenue": [8120.2],
"roas": [6.32]
}
}
csv or txt
date,campaign_name,spend,revenue,roas
2026-06-01,Brand Search,1284.50,8120.20,6.32
arrow, xlsx, or dataframe
{
"format": "arrow",
"content_type": "application/vnd.apache.arrow.stream",
"byte_length": 1024,
"base64": "<encoded binary payload>",
"table_preview": {
"columns": ["date", "campaign_name", "spend", "revenue", "roas"],
"rows": [
{
"date": "2026-06-01",
"campaign_name": "Brand Search",
"spend": 1284.5,
"revenue": 8120.2,
"roas": 6.32
}
],
"row_count": 1,
"truncated": false
}
}
Binary-oriented formats usually include content metadata and may include table_preview so portal users can inspect rows without decoding the full payload in the browser.
Troubleshooting Failed Requests
Most failures mean the request needs a more precise analytics contract. Treat these as recoverable integration states rather than generic server errors.
| What you see | What it means | What to do |
|---|---|---|
| The response asks for clarification. | AQL could not infer enough scope to build one clear query. | Add an explicit client, date range, metric, and grouping. For REST integrations, prefer exact catalog IDs over labels. |
| Validation failed. | The generated or supplied structured query contains an unsupported field, filter, parameter, or field combination. | Read validation.errors, replace guessed fields with IDs from Catalog Explorer or /api/20260709/catalog/search, then retry. |
| The run timed out. | The portal or API stopped waiting for the result before upstream execution finished. | Use a larger timeout_ms for bounded queries, or use the enqueue/poll flow when a query can run longer. |
The request returns 401. | The bearer token is missing, expired, or not authorized for the requested client/resource. | Refresh the caller token, complete OAuth again, and confirm the token can access the requested client. |
| The response says the output format is unsupported. | The requested format or result_format is not available for this endpoint. | Use one of the supported formats listed above, such as records, csv, xlsx, or arrow. |
