curl --request GET \
--url https://devtune.ai/api/v2/projects/{projectId}/traffic/search-rollups \
--header 'Authorization: Bearer <token>'import requests
url = "https://devtune.ai/api/v2/projects/{projectId}/traffic/search-rollups"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://devtune.ai/api/v2/projects/{projectId}/traffic/search-rollups', 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://devtune.ai/api/v2/projects/{projectId}/traffic/search-rollups",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://devtune.ai/api/v2/projects/{projectId}/traffic/search-rollups"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://devtune.ai/api/v2/projects/{projectId}/traffic/search-rollups")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://devtune.ai/api/v2/projects/{projectId}/traffic/search-rollups")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"data": {
"source": "gsc",
"aggregates": {
"avgPosition": 123,
"clicks": 123,
"ctr": 123,
"impressions": 123,
"measurement": {
"availability": "unavailable",
"status": "unmeasured",
"isCurrent": true,
"asOfDate": "2023-11-07T05:31:56Z",
"explanation": "<string>",
"sourceDateFrom": "2023-12-25",
"sourceDateTo": "2023-12-25",
"finalityBoundary": "2023-12-25",
"contributors": [
{}
],
"coveredRanges": [
{
"connectionId": "<string>",
"dateFrom": "2023-12-25",
"dateTo": "2023-12-25"
}
],
"storedEvidence": [
{}
],
"coverageFrom": "2023-12-25",
"coverageThrough": "2023-12-25"
}
},
"window": {
"days": 30,
"dateFrom": "2023-12-25",
"dateTo": "2023-12-25"
}
},
"meta": {
"timestamp": "2023-11-07T05:31:56Z",
"projectId": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
}
}{
"error": "<string>",
"message": "<string>",
"status": 123
}{
"error": "<string>",
"message": "<string>",
"status": 123
}{
"error": "<string>",
"message": "<string>",
"status": 123
}{
"error": "<string>",
"message": "<string>",
"status": 123
}{
"error": "<string>",
"message": "<string>",
"status": 123
}Get search rollup totals
Returns materialized fixed-window Google Search Console or GA4 rollup totals. Missing or stale freshness pointers serve the last published rollup with its own dates. Retained evidence has availability partial, isCurrent false and compatibility status unmeasured; asOfDate identifies its publication. Never-published projects return unavailable coverage and null totals. GSC uses Pacific source days ending three days before today, with coverage capped by the age of days at the last successful sync. Current totals require every non-paused, non-disconnected current contributor to cover the full requested window. Stale published totals remain visible but are not current evidence or verified comparisons. Coverage is reported per contributor. measurement.availability and explanation distinguish unavailable verification, partial evidence, verified zero, and fully measured totals. Use the returned source window dates; storedData bounds are row-presence evidence, not proof of continuous coverage.
curl --request GET \
--url https://devtune.ai/api/v2/projects/{projectId}/traffic/search-rollups \
--header 'Authorization: Bearer <token>'import requests
url = "https://devtune.ai/api/v2/projects/{projectId}/traffic/search-rollups"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://devtune.ai/api/v2/projects/{projectId}/traffic/search-rollups', 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://devtune.ai/api/v2/projects/{projectId}/traffic/search-rollups",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://devtune.ai/api/v2/projects/{projectId}/traffic/search-rollups"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://devtune.ai/api/v2/projects/{projectId}/traffic/search-rollups")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://devtune.ai/api/v2/projects/{projectId}/traffic/search-rollups")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"data": {
"source": "gsc",
"aggregates": {
"avgPosition": 123,
"clicks": 123,
"ctr": 123,
"impressions": 123,
"measurement": {
"availability": "unavailable",
"status": "unmeasured",
"isCurrent": true,
"asOfDate": "2023-11-07T05:31:56Z",
"explanation": "<string>",
"sourceDateFrom": "2023-12-25",
"sourceDateTo": "2023-12-25",
"finalityBoundary": "2023-12-25",
"contributors": [
{}
],
"coveredRanges": [
{
"connectionId": "<string>",
"dateFrom": "2023-12-25",
"dateTo": "2023-12-25"
}
],
"storedEvidence": [
{}
],
"coverageFrom": "2023-12-25",
"coverageThrough": "2023-12-25"
}
},
"window": {
"days": 30,
"dateFrom": "2023-12-25",
"dateTo": "2023-12-25"
}
},
"meta": {
"timestamp": "2023-11-07T05:31:56Z",
"projectId": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
}
}{
"error": "<string>",
"message": "<string>",
"status": 123
}{
"error": "<string>",
"message": "<string>",
"status": 123
}{
"error": "<string>",
"message": "<string>",
"status": 123
}{
"error": "<string>",
"message": "<string>",
"status": 123
}{
"error": "<string>",
"message": "<string>",
"status": 123
}Authorizations
API key with dtk_live_ prefix. Obtain it from API Keys in the account sidebar. New keys start with all supported scopes selected for the chosen project, and you can narrow them to specific read/write scopes as needed.
Path Parameters
Query Parameters
gsc, ga4 Fixed rolling window in days. Supported values are 30 and 90. Defaults to 30.
30, 90