curl --request GET \
--url https://api.geoptie.com/v1/brands/{id}/ads/creatives \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.geoptie.com/v1/brands/{id}/ads/creatives"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.geoptie.com/v1/brands/{id}/ads/creatives', 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://api.geoptie.com/v1/brands/{id}/ads/creatives",
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://api.geoptie.com/v1/brands/{id}/ads/creatives"
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://api.geoptie.com/v1/brands/{id}/ads/creatives")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.geoptie.com/v1/brands/{id}/ads/creatives")
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": [
{
"creative_id": "3f2a9c1e7b4d4e0f9a8b6c5d4e3f2a1b",
"advertiser_key": "globex.com",
"advertiser_name": "Globex",
"headline": "Project planning your team will actually use",
"body": "Plan sprints, track work and ship on time. Free for teams up to 10.",
"image_url": "https://images.openai.com/static-rsc-5/globex-planning.png",
"landing_url": "https://globex.com/lp/project-planning?utm_source=chatgpt&utm_medium=paid&utm_campaign=pm_nonbrand",
"appearances": 31,
"prompts": 12,
"first_seen": "2026-10-15",
"last_seen": "2026-11-13",
"is_competitor": true,
"is_own": false
}
],
"has_more": true,
"next_cursor": "WyJvIiwxXQ",
"total_count": 96
}{
"error": {
"code": "invalid_date",
"message": "Dates must be ISO 8601, e.g. 2026-08-01."
}
}{
"error": {
"code": "invalid_api_key",
"message": "This API key is not valid or has been revoked."
}
}{
"error": {
"code": "subscription_required",
"message": "This workspace does not have an active subscription. API access requires an active or trialing plan."
}
}{
"error": {
"code": "forbidden",
"message": "This workspace cannot perform that action."
}
}{
"error": {
"code": "not_found",
"message": "No such brand in this workspace."
}
}{
"error": {
"code": "rate_limited",
"message": "Rate limit of 120 requests per minute exceeded."
}
}{
"error": {
"code": "internal_error",
"message": "Something went wrong on our side."
}
}Ad creatives
The ads themselves: headline, text, image and landing link, with how often each appeared, most first. Narrow to one advertiser or prompt.
curl --request GET \
--url https://api.geoptie.com/v1/brands/{id}/ads/creatives \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.geoptie.com/v1/brands/{id}/ads/creatives"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.geoptie.com/v1/brands/{id}/ads/creatives', 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://api.geoptie.com/v1/brands/{id}/ads/creatives",
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://api.geoptie.com/v1/brands/{id}/ads/creatives"
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://api.geoptie.com/v1/brands/{id}/ads/creatives")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.geoptie.com/v1/brands/{id}/ads/creatives")
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": [
{
"creative_id": "3f2a9c1e7b4d4e0f9a8b6c5d4e3f2a1b",
"advertiser_key": "globex.com",
"advertiser_name": "Globex",
"headline": "Project planning your team will actually use",
"body": "Plan sprints, track work and ship on time. Free for teams up to 10.",
"image_url": "https://images.openai.com/static-rsc-5/globex-planning.png",
"landing_url": "https://globex.com/lp/project-planning?utm_source=chatgpt&utm_medium=paid&utm_campaign=pm_nonbrand",
"appearances": 31,
"prompts": 12,
"first_seen": "2026-10-15",
"last_seen": "2026-11-13",
"is_competitor": true,
"is_own": false
}
],
"has_more": true,
"next_cursor": "WyJvIiwxXQ",
"total_count": 96
}{
"error": {
"code": "invalid_date",
"message": "Dates must be ISO 8601, e.g. 2026-08-01."
}
}{
"error": {
"code": "invalid_api_key",
"message": "This API key is not valid or has been revoked."
}
}{
"error": {
"code": "subscription_required",
"message": "This workspace does not have an active subscription. API access requires an active or trialing plan."
}
}{
"error": {
"code": "forbidden",
"message": "This workspace cannot perform that action."
}
}{
"error": {
"code": "not_found",
"message": "No such brand in this workspace."
}
}{
"error": {
"code": "rate_limited",
"message": "Rate limit of 120 requests per minute exceeded."
}
}{
"error": {
"code": "internal_error",
"message": "Something went wrong on our side."
}
}Authorizations
Your API key, e.g. Authorization: Bearer gp_live_....
Path Parameters
Brand id.
Query Parameters
Ads are tracked on ChatGPT only, so this is chatgpt or omitted.
chatgpt Inclusive start date. Defaults to 30 days before to.
Exclusive end date. Defaults to tomorrow.
Restrict to one market: a two-letter code, or global for checks run without a market. The summary's markets lists the values this brand has.
Repeatable. Restrict to prompts in these topics.
Restrict to prompts that name this brand (branded) or to those that do not (non_branded). Omit, or all, for every prompt.
all, branded, non_branded Restrict to one advertiser, by the advertiser_key other ads endpoints return.
Restrict to one prompt this brand tracks. Cannot be combined with topic_id.
Match headline, body or advertiser name.
200Rows per page. Max 500.
x <= 500Opaque cursor from the previous page's next_cursor. Use it with the same other parameters.