curl --request POST \
--url https://app.traceroot.ai/api/v1/public/widgets/query \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"spec": {
"display": {},
"metric": {
"measure": "<string>"
},
"breakdown": "<string>",
"filters": [
{
"field": "<string>",
"value": "<string>",
"key": "<string>"
}
]
},
"bucket_seconds": 43200,
"end_time": "2023-11-07T05:31:56Z",
"start_time": "2023-11-07T05:31:56Z"
}
'import requests
url = "https://app.traceroot.ai/api/v1/public/widgets/query"
payload = {
"spec": {
"display": {},
"metric": { "measure": "<string>" },
"breakdown": "<string>",
"filters": [
{
"field": "<string>",
"value": "<string>",
"key": "<string>"
}
]
},
"bucket_seconds": 43200,
"end_time": "2023-11-07T05:31:56Z",
"start_time": "2023-11-07T05:31:56Z"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
spec: {
display: {},
metric: {measure: '<string>'},
breakdown: '<string>',
filters: [{field: '<string>', value: '<string>', key: '<string>'}]
},
bucket_seconds: 43200,
end_time: '2023-11-07T05:31:56Z',
start_time: '2023-11-07T05:31:56Z'
})
};
fetch('https://app.traceroot.ai/api/v1/public/widgets/query', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://app.traceroot.ai/api/v1/public/widgets/query",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'spec' => [
'display' => [
],
'metric' => [
'measure' => '<string>'
],
'breakdown' => '<string>',
'filters' => [
[
'field' => '<string>',
'value' => '<string>',
'key' => '<string>'
]
]
],
'bucket_seconds' => 43200,
'end_time' => '2023-11-07T05:31:56Z',
'start_time' => '2023-11-07T05:31:56Z'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://app.traceroot.ai/api/v1/public/widgets/query"
payload := strings.NewReader("{\n \"spec\": {\n \"display\": {},\n \"metric\": {\n \"measure\": \"<string>\"\n },\n \"breakdown\": \"<string>\",\n \"filters\": [\n {\n \"field\": \"<string>\",\n \"value\": \"<string>\",\n \"key\": \"<string>\"\n }\n ]\n },\n \"bucket_seconds\": 43200,\n \"end_time\": \"2023-11-07T05:31:56Z\",\n \"start_time\": \"2023-11-07T05:31:56Z\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://app.traceroot.ai/api/v1/public/widgets/query")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"spec\": {\n \"display\": {},\n \"metric\": {\n \"measure\": \"<string>\"\n },\n \"breakdown\": \"<string>\",\n \"filters\": [\n {\n \"field\": \"<string>\",\n \"value\": \"<string>\",\n \"key\": \"<string>\"\n }\n ]\n },\n \"bucket_seconds\": 43200,\n \"end_time\": \"2023-11-07T05:31:56Z\",\n \"start_time\": \"2023-11-07T05:31:56Z\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.traceroot.ai/api/v1/public/widgets/query")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"spec\": {\n \"display\": {},\n \"metric\": {\n \"measure\": \"<string>\"\n },\n \"breakdown\": \"<string>\",\n \"filters\": [\n {\n \"field\": \"<string>\",\n \"value\": \"<string>\",\n \"key\": \"<string>\"\n }\n ]\n },\n \"bucket_seconds\": 43200,\n \"end_time\": \"2023-11-07T05:31:56Z\",\n \"start_time\": \"2023-11-07T05:31:56Z\"\n}"
response = http.request(request)
puts response.read_body{
"columns": [
"<string>"
],
"rows": [
[
"<unknown>"
]
],
"window": {
"clamped": true,
"end_time": "2023-11-07T05:31:56Z",
"range": "30m",
"start_time": "2023-11-07T05:31:56Z"
},
"meta": {}
}{
"detail": "<string>"
}{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>",
"ctx": {},
"input": "<unknown>"
}
]
}{
"detail": "<string>"
}Run Widget Query
Run a widget spec for a window and return its rows with the window answered.
curl --request POST \
--url https://app.traceroot.ai/api/v1/public/widgets/query \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"spec": {
"display": {},
"metric": {
"measure": "<string>"
},
"breakdown": "<string>",
"filters": [
{
"field": "<string>",
"value": "<string>",
"key": "<string>"
}
]
},
"bucket_seconds": 43200,
"end_time": "2023-11-07T05:31:56Z",
"start_time": "2023-11-07T05:31:56Z"
}
'import requests
url = "https://app.traceroot.ai/api/v1/public/widgets/query"
payload = {
"spec": {
"display": {},
"metric": { "measure": "<string>" },
"breakdown": "<string>",
"filters": [
{
"field": "<string>",
"value": "<string>",
"key": "<string>"
}
]
},
"bucket_seconds": 43200,
"end_time": "2023-11-07T05:31:56Z",
"start_time": "2023-11-07T05:31:56Z"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
spec: {
display: {},
metric: {measure: '<string>'},
breakdown: '<string>',
filters: [{field: '<string>', value: '<string>', key: '<string>'}]
},
bucket_seconds: 43200,
end_time: '2023-11-07T05:31:56Z',
start_time: '2023-11-07T05:31:56Z'
})
};
fetch('https://app.traceroot.ai/api/v1/public/widgets/query', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://app.traceroot.ai/api/v1/public/widgets/query",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'spec' => [
'display' => [
],
'metric' => [
'measure' => '<string>'
],
'breakdown' => '<string>',
'filters' => [
[
'field' => '<string>',
'value' => '<string>',
'key' => '<string>'
]
]
],
'bucket_seconds' => 43200,
'end_time' => '2023-11-07T05:31:56Z',
'start_time' => '2023-11-07T05:31:56Z'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://app.traceroot.ai/api/v1/public/widgets/query"
payload := strings.NewReader("{\n \"spec\": {\n \"display\": {},\n \"metric\": {\n \"measure\": \"<string>\"\n },\n \"breakdown\": \"<string>\",\n \"filters\": [\n {\n \"field\": \"<string>\",\n \"value\": \"<string>\",\n \"key\": \"<string>\"\n }\n ]\n },\n \"bucket_seconds\": 43200,\n \"end_time\": \"2023-11-07T05:31:56Z\",\n \"start_time\": \"2023-11-07T05:31:56Z\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://app.traceroot.ai/api/v1/public/widgets/query")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"spec\": {\n \"display\": {},\n \"metric\": {\n \"measure\": \"<string>\"\n },\n \"breakdown\": \"<string>\",\n \"filters\": [\n {\n \"field\": \"<string>\",\n \"value\": \"<string>\",\n \"key\": \"<string>\"\n }\n ]\n },\n \"bucket_seconds\": 43200,\n \"end_time\": \"2023-11-07T05:31:56Z\",\n \"start_time\": \"2023-11-07T05:31:56Z\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.traceroot.ai/api/v1/public/widgets/query")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"spec\": {\n \"display\": {},\n \"metric\": {\n \"measure\": \"<string>\"\n },\n \"breakdown\": \"<string>\",\n \"filters\": [\n {\n \"field\": \"<string>\",\n \"value\": \"<string>\",\n \"key\": \"<string>\"\n }\n ]\n },\n \"bucket_seconds\": 43200,\n \"end_time\": \"2023-11-07T05:31:56Z\",\n \"start_time\": \"2023-11-07T05:31:56Z\"\n}"
response = http.request(request)
puts response.read_body{
"columns": [
"<string>"
],
"rows": [
[
"<unknown>"
]
],
"window": {
"clamped": true,
"end_time": "2023-11-07T05:31:56Z",
"range": "30m",
"start_time": "2023-11-07T05:31:56Z"
},
"meta": {}
}{
"detail": "<string>"
}{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>",
"ctx": {},
"input": "<unknown>"
}
]
}{
"detail": "<string>"
}Authorizations
Bearer authentication header of the form Bearer <token>, where <token> is your auth token.
Query Parameters
Target project for the request. Required when authenticating with a user session token (a user credential is only meaningful scoped to a project); for an API key it is optional and, if given, must match the key's project.
Body
Envelope that pairs a WidgetSpec with the time window to answer it for.
The window is either a range preset (the site picker's ids — how the
agent and the CLI describe one) or explicit start_time/end_time
(how the dashboard page and the card previews do). Neither means the
site's default window; both, or one bound alone, is rejected. The rules
live in rest.services.date_presets.resolve_window so every query
surface applies the same ones.
Full declarative specification of a single dashboard widget.
Mirrors the canonical zod WidgetSpecSchema
(frontend/ui/src/features/dashboards/types.ts); the frontend
widget-spec-parity test guards the two against structural drift.
Show child attributes
Show child attributes
1 <= x <= 86400A preset window ending now, by the site picker's id. Give this or explicit start_time/end_time; neither means the site's 24-hour default.
30m, 1h, 3h, 6h, 1d, 7d, 14d, 30d, 60d, 90d Response
Successful Response
Query result returned to the frontend; meta carries display hints (e.g. granularity for time-series displays).
The window a query was actually answered for.
range is the preset id the caller gave (or the default's, when they
gave nothing) and None for explicit bounds. clamped is True when the
plan's retention pulled start_time forward — the honest reason a
caller's window and the answered one differ.
Show child attributes
Show child attributes

