curl --request GET \
--url https://devtune.ai/api/v2/projects/{projectId}/content-gaps/evidence \
--header 'Authorization: Bearer <token>'import requests
url = "https://devtune.ai/api/v2/projects/{projectId}/content-gaps/evidence"
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}/content-gaps/evidence', 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}/content-gaps/evidence",
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}/content-gaps/evidence"
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}/content-gaps/evidence")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://devtune.ai/api/v2/projects/{projectId}/content-gaps/evidence")
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": {
"gap": {
"gapType": "topic",
"targetKey": "<string>",
"targetLabel": "<string>",
"windowDays": 30,
"asOfDate": "2023-12-25",
"citationCount": 1,
"primaryCitations": 1,
"competitorCitations": 1,
"averagePosition": 123,
"share": 0.5
},
"evidence": [
{
"promptId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"promptText": "<string>",
"promptStatus": "active",
"promptCitationCount": 2,
"topicId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"topicName": "<string>",
"url": "<string>",
"domain": "<string>",
"sourceType": "primary",
"title": "<string>",
"platforms": [
"<string>"
],
"citationCount": 2,
"averagePosition": 123
}
],
"attribution": {
"attributedCitations": 1,
"promptCount": 1,
"pageCount": 1
},
"coverage": {
"status": "available",
"windowDays": 30,
"availableDays": 1,
"isPartial": true,
"asOfDate": "2023-12-25",
"reason": "window_not_measured",
"snapshotId": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
},
"pagination": {
"offset": 1,
"limit": 50,
"totalCount": 1
},
"window": {
"days": 123,
"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,
"reason": "<string>",
"details": {}
}{
"error": "<string>",
"message": "<string>",
"status": 123,
"reason": "<string>",
"details": {}
}{
"error": "<string>",
"message": "<string>",
"status": 123,
"reason": "<string>",
"details": {}
}{
"error": "<string>",
"message": "<string>",
"status": 123,
"reason": "<string>",
"details": {}
}{
"error": "<string>",
"message": "<string>",
"status": 123,
"reason": "<string>",
"details": {}
}{
"error": "<string>",
"message": "<string>",
"status": 123,
"reason": "<string>",
"details": {}
}Get content gap evidence
Returns the tracked prompts and cited pages behind one content gap from List content gaps. Pass its gapType and targetKey with the same windowDays. Evidence is published with the gap, so it covers the same fixed window and asOfDate. A source gap matches its URL, a brand gap the pages cited on its domain, and a topic gap every page cited in answers recorded under that topic. Each item groups one prompt, recorded topic, cited URL, recorded domain and sourceType. The same prompt and URL can appear in several items when those recorded attributes differ; pagination counts those groups, ordered by the prompt’s citations of the gap, then by the page’s citations. Counts are the gap’s own citations split by the tracked prompt that produced them, so attribution.attributedCitations falls short of gap.citationCount only by citations no tracked prompt produced. Prompt text and topic names are current values; promptStatus says whether the prompt is still tracked. Coverage is unavailable with reason window_not_measured before the window is rolled up, and evidence_not_published when the window was published without evidence, because it includes days measured before evidence was recorded, holds more evidence than one publish includes, or had its gaps last recalculated from current topic and competitor settings rather than from the recorded citations; neither is a measured zero. Pass coverage.snapshotId on later pages: if the window is republished meanwhile, the request returns 409 with reason snapshot_changed rather than mixing two windows. A gap that is not in the published window returns 404.
curl --request GET \
--url https://devtune.ai/api/v2/projects/{projectId}/content-gaps/evidence \
--header 'Authorization: Bearer <token>'import requests
url = "https://devtune.ai/api/v2/projects/{projectId}/content-gaps/evidence"
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}/content-gaps/evidence', 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}/content-gaps/evidence",
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}/content-gaps/evidence"
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}/content-gaps/evidence")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://devtune.ai/api/v2/projects/{projectId}/content-gaps/evidence")
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": {
"gap": {
"gapType": "topic",
"targetKey": "<string>",
"targetLabel": "<string>",
"windowDays": 30,
"asOfDate": "2023-12-25",
"citationCount": 1,
"primaryCitations": 1,
"competitorCitations": 1,
"averagePosition": 123,
"share": 0.5
},
"evidence": [
{
"promptId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"promptText": "<string>",
"promptStatus": "active",
"promptCitationCount": 2,
"topicId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"topicName": "<string>",
"url": "<string>",
"domain": "<string>",
"sourceType": "primary",
"title": "<string>",
"platforms": [
"<string>"
],
"citationCount": 2,
"averagePosition": 123
}
],
"attribution": {
"attributedCitations": 1,
"promptCount": 1,
"pageCount": 1
},
"coverage": {
"status": "available",
"windowDays": 30,
"availableDays": 1,
"isPartial": true,
"asOfDate": "2023-12-25",
"reason": "window_not_measured",
"snapshotId": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
},
"pagination": {
"offset": 1,
"limit": 50,
"totalCount": 1
},
"window": {
"days": 123,
"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,
"reason": "<string>",
"details": {}
}{
"error": "<string>",
"message": "<string>",
"status": 123,
"reason": "<string>",
"details": {}
}{
"error": "<string>",
"message": "<string>",
"status": 123,
"reason": "<string>",
"details": {}
}{
"error": "<string>",
"message": "<string>",
"status": 123,
"reason": "<string>",
"details": {}
}{
"error": "<string>",
"message": "<string>",
"status": 123,
"reason": "<string>",
"details": {}
}{
"error": "<string>",
"message": "<string>",
"status": 123,
"reason": "<string>",
"details": {}
}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
gapType of the listed content gap.
topic, source, brand targetKey of the listed content gap, exactly as listed: a topic id, a cited URL or a domain.
1 - 8192^[^\u0000]+$Fixed rolling window in days. Supported values are 30 and 90. Defaults to 30.
30, 90 0 <= x <= 21474836471 <= x <= 100coverage.snapshotId from the first page. The request returns 409 if the window was republished since.