curl --request POST \
--url https://app.goosybear.ai/api/v1/tools/seo.aeo_presence \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"queries": [
"<string>"
],
"domain": "<string>",
"location_name": "<string>",
"language_name": "<string>",
"surfaces": [],
"confirmation_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"workspace": "<string>"
}
'import requests
url = "https://app.goosybear.ai/api/v1/tools/seo.aeo_presence"
payload = {
"queries": ["<string>"],
"domain": "<string>",
"location_name": "<string>",
"language_name": "<string>",
"surfaces": [],
"confirmation_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"workspace": "<string>"
}
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({
queries: ['<string>'],
domain: '<string>',
location_name: '<string>',
language_name: '<string>',
surfaces: [],
confirmation_id: '3c90c3cc-0d44-4b50-8888-8dd25736052a',
workspace: '<string>'
})
};
fetch('https://app.goosybear.ai/api/v1/tools/seo.aeo_presence', 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.goosybear.ai/api/v1/tools/seo.aeo_presence",
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([
'queries' => [
'<string>'
],
'domain' => '<string>',
'location_name' => '<string>',
'language_name' => '<string>',
'surfaces' => [
],
'confirmation_id' => '3c90c3cc-0d44-4b50-8888-8dd25736052a',
'workspace' => '<string>'
]),
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.goosybear.ai/api/v1/tools/seo.aeo_presence"
payload := strings.NewReader("{\n \"queries\": [\n \"<string>\"\n ],\n \"domain\": \"<string>\",\n \"location_name\": \"<string>\",\n \"language_name\": \"<string>\",\n \"surfaces\": [],\n \"confirmation_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"workspace\": \"<string>\"\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.goosybear.ai/api/v1/tools/seo.aeo_presence")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"queries\": [\n \"<string>\"\n ],\n \"domain\": \"<string>\",\n \"location_name\": \"<string>\",\n \"language_name\": \"<string>\",\n \"surfaces\": [],\n \"confirmation_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"workspace\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.goosybear.ai/api/v1/tools/seo.aeo_presence")
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 \"queries\": [\n \"<string>\"\n ],\n \"domain\": \"<string>\",\n \"location_name\": \"<string>\",\n \"language_name\": \"<string>\",\n \"surfaces\": [],\n \"confirmation_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"workspace\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"ok": true,
"workspace": "<string>",
"working_in": {
"label": "<string>",
"note": "<string>",
"workspace": "<string>",
"source": "call-override"
},
"state": "confirmation_required",
"confirmation_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"expires_in_seconds": 123,
"request_summary": "<string>",
"domain": "<string>",
"location_name": "<string>",
"language_name": "<string>",
"rows": [
{
"query": "<string>",
"source": "ai_overview",
"ai_overview_present": true,
"ai_overview_resolved": true,
"cited": true,
"citation_rank": 1,
"cited_urls": [
"<string>"
],
"competitor_domains": [
"<string>"
],
"organic_rank": 1,
"holds_answer_block": true
}
],
"queries_requested": 1,
"queries_answered": 1,
"queries_not_read": [
{
"query": "<string>",
"surface": "ai_overview",
"reason": "<string>"
}
],
"queries_with_ai_overview": 1,
"queries_citing_domain": 1,
"by_surface": [
{
"surface": "ai_overview",
"queries_with_answer": 1,
"queries_citing_domain": 1
}
],
"credits_consumed_thousandths": 1
}{
"ok": false,
"code": "<string>",
"message": "<string>",
"error": {
"code": "<string>",
"message": "<string>",
"retry_after_seconds": 123
},
"retry_after_seconds": 123
}{
"ok": false,
"code": "<string>",
"message": "<string>",
"error": {
"code": "<string>",
"message": "<string>",
"retry_after_seconds": 123
},
"retry_after_seconds": 123
}{
"ok": false,
"code": "<string>",
"message": "<string>",
"error": {
"code": "<string>",
"message": "<string>",
"retry_after_seconds": 123
},
"retry_after_seconds": 123
}{
"ok": false,
"code": "<string>",
"message": "<string>",
"error": {
"code": "<string>",
"message": "<string>",
"retry_after_seconds": 123
},
"retry_after_seconds": 123
}{
"ok": false,
"code": "<string>",
"message": "<string>",
"error": {
"code": "<string>",
"message": "<string>",
"retry_after_seconds": 123
},
"retry_after_seconds": 123
}Call seo.aeo_presence
Answer ‘am I in the AI answer for this?’ and ‘does Google AI Mode cite us for this search?’ — for each search, whether Google wrote an AI answer, whether this workspace’s site is cited in it, which of our URLs it used and WHO ELSE it cited; on the AI Overview also where we rank organically on the same page and whether we hold the featured snippet. surfaces picks the answers read: ‘ai_overview’ (the AI summary on the results page, the default) and ‘ai_mode’ (Google’s AI Mode); each row’s source names its answer, and by_surface tallies each. Omit domain to use this workspace’s own site. EACH SEARCH IS A SEPARATE PAID READ ON EACH SURFACE and charges credits, so pass only the searches the operator named — at most 5. ai_overview_present: true with ai_overview_resolved: false means there IS an answer and it could not be read: say that, never ‘you are not cited’. rows may be SHORTER than queries_requested: each entry of queries_not_read is a search you COULD NOT CHECK on that surface — never report it as not cited. Over the API it answers in two calls: without confirmation_id it proposes — says what would happen, returns a confirmation_id and changes, spends and sends nothing; the same arguments again with that confirmation_id, on a member’s own API key, do it.
Every result names the workspace it ran in. Say which workspace the answer is about. When the account has more than one workspace and none is selected, this tool refuses with workspace_ambiguous and lists the choices — offer them, never pick one.
curl --request POST \
--url https://app.goosybear.ai/api/v1/tools/seo.aeo_presence \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"queries": [
"<string>"
],
"domain": "<string>",
"location_name": "<string>",
"language_name": "<string>",
"surfaces": [],
"confirmation_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"workspace": "<string>"
}
'import requests
url = "https://app.goosybear.ai/api/v1/tools/seo.aeo_presence"
payload = {
"queries": ["<string>"],
"domain": "<string>",
"location_name": "<string>",
"language_name": "<string>",
"surfaces": [],
"confirmation_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"workspace": "<string>"
}
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({
queries: ['<string>'],
domain: '<string>',
location_name: '<string>',
language_name: '<string>',
surfaces: [],
confirmation_id: '3c90c3cc-0d44-4b50-8888-8dd25736052a',
workspace: '<string>'
})
};
fetch('https://app.goosybear.ai/api/v1/tools/seo.aeo_presence', 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.goosybear.ai/api/v1/tools/seo.aeo_presence",
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([
'queries' => [
'<string>'
],
'domain' => '<string>',
'location_name' => '<string>',
'language_name' => '<string>',
'surfaces' => [
],
'confirmation_id' => '3c90c3cc-0d44-4b50-8888-8dd25736052a',
'workspace' => '<string>'
]),
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.goosybear.ai/api/v1/tools/seo.aeo_presence"
payload := strings.NewReader("{\n \"queries\": [\n \"<string>\"\n ],\n \"domain\": \"<string>\",\n \"location_name\": \"<string>\",\n \"language_name\": \"<string>\",\n \"surfaces\": [],\n \"confirmation_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"workspace\": \"<string>\"\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.goosybear.ai/api/v1/tools/seo.aeo_presence")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"queries\": [\n \"<string>\"\n ],\n \"domain\": \"<string>\",\n \"location_name\": \"<string>\",\n \"language_name\": \"<string>\",\n \"surfaces\": [],\n \"confirmation_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"workspace\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.goosybear.ai/api/v1/tools/seo.aeo_presence")
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 \"queries\": [\n \"<string>\"\n ],\n \"domain\": \"<string>\",\n \"location_name\": \"<string>\",\n \"language_name\": \"<string>\",\n \"surfaces\": [],\n \"confirmation_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"workspace\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"ok": true,
"workspace": "<string>",
"working_in": {
"label": "<string>",
"note": "<string>",
"workspace": "<string>",
"source": "call-override"
},
"state": "confirmation_required",
"confirmation_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"expires_in_seconds": 123,
"request_summary": "<string>",
"domain": "<string>",
"location_name": "<string>",
"language_name": "<string>",
"rows": [
{
"query": "<string>",
"source": "ai_overview",
"ai_overview_present": true,
"ai_overview_resolved": true,
"cited": true,
"citation_rank": 1,
"cited_urls": [
"<string>"
],
"competitor_domains": [
"<string>"
],
"organic_rank": 1,
"holds_answer_block": true
}
],
"queries_requested": 1,
"queries_answered": 1,
"queries_not_read": [
{
"query": "<string>",
"surface": "ai_overview",
"reason": "<string>"
}
],
"queries_with_ai_overview": 1,
"queries_citing_domain": 1,
"by_surface": [
{
"surface": "ai_overview",
"queries_with_answer": 1,
"queries_citing_domain": 1
}
],
"credits_consumed_thousandths": 1
}{
"ok": false,
"code": "<string>",
"message": "<string>",
"error": {
"code": "<string>",
"message": "<string>",
"retry_after_seconds": 123
},
"retry_after_seconds": 123
}{
"ok": false,
"code": "<string>",
"message": "<string>",
"error": {
"code": "<string>",
"message": "<string>",
"retry_after_seconds": 123
},
"retry_after_seconds": 123
}{
"ok": false,
"code": "<string>",
"message": "<string>",
"error": {
"code": "<string>",
"message": "<string>",
"retry_after_seconds": 123
},
"retry_after_seconds": 123
}{
"ok": false,
"code": "<string>",
"message": "<string>",
"error": {
"code": "<string>",
"message": "<string>",
"retry_after_seconds": 123
},
"retry_after_seconds": 123
}{
"ok": false,
"code": "<string>",
"message": "<string>",
"error": {
"code": "<string>",
"message": "<string>",
"retry_after_seconds": 123
},
"retry_after_seconds": 123
}Authorizations
An API key minted at Settings › API & MCP. Send it as Authorization: Bearer <key>. A key carries its holder's own permissions, resolved on every call — revoking a membership closes the key's reach immediately. Keep it in an environment variable (GOOSY_API_KEY), never in a committed file.
Headers
Body
Which Google AI answers to check: 'ai_overview' (the AI summary on the results page) and 'ai_mode' (Google's AI Mode chat). Leave it out for the AI Overview only; pass both when the operator asks about AI search or AI Mode. Each surface is a separate paid read per search.
1 - 2 elementsai_overview, ai_mode Omit to propose: the first call says what would happen, returns a confirmation_id and changes nothing. To go ahead, send the same arguments again with that confirmation_id, on a member's own API key; a service account's key can propose but never confirm.
^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$Response
The call was admitted and dispatched. ok says whether the tool succeeded — a refusal the tool itself produced is still a 200, exactly as it is a successful JSON-RPC result over MCP.
- Option 1
- Option 2
The tool ran and answered.