Skip to content
Gauge

ax-check.com

xSeek

xseek.io

ax-check.com

Checked 7 October 2026

B

84/100

Agents need your login

Pricing is clear, but quickstart and install steps are missing

14 of 23 checklist items pass, including clear pricing and a solid docs index, but 8 items on quickstart, install commands, and code examples are unassessed.

2 fixes to start with

Concrete changes, backed by what we found.

Onboarding

Give agents a clear login handoff and a way to resume setup.

Agents cannot progress through onboarding without human help. Provide an agent-accessible path through authentication and setup.

Docs

Return Markdown when clients request text/markdown.

Homepage returned text/html for a text/markdown request; no Markdown representation offered.

Recorded coding sessions

Same task, 3 models, no xseek.io account. Recorded 7 October 2026 on Pi.

3 recorded · 2m 51s

2m 51s · recorded

Session findings

Select a finding to see it in context.

piv0.84.2
modelQwen 3.8 Maxcwd/sandbox/repo
Help me build a simple example using xSeek. Tell me how pricing works, and briefly tell me whether this product will be easy for you to manage. Let me know if you get blocked. If this product has no developer workflow you can act on, say so plainly and stop. Stay light: use the hosted product through its SDK or API. Do not start local service stacks or wait for long-running commands; if the quickstart requires either, say so plainly and stop.
Thinking…

The user asks about "xSeek" — I don't know what that is. Let me check the sandbox/repo directory for context.

pwd && ls -la && git log --oneline -5 2>/dev/null | head
/sandbox/repo
/sandbox/repo
total 16
drwxr-xr-x 3 root root 4096 Sep 18 08:00 .
drwxr-xr-x 7 root root 4096 Oct  7 17:27 ..
drwxr-xr-x 8 root root 4096 Sep 24 20:05 .git
-rw-r--r-- 1 root root  408 Sep 18 08:00 .gitignore
9ebf5fb Initial workspace
ls /sandbox 2>/dev/null; ls ~ 2>/dev/null
repo
repo
repo
Thinking…

The repo is empty. Let me search for "xSeek" — maybe there's some hint in git or environment.

cd /sandbox/repo && cat .gitignore && git status --short && git log -1 --stat
# Keep generated and vendored files out of source diffs.
# Keep generated and vendored files out of source diffs.

# Logs / OS cruft
*.log
.DS_Store

# JavaScript / TypeScript
node_modules/
.next/
dist/
build/
coverage/

# Python
.venv/
venv/
__pycache__/
*.py[cod]
.pytest_cache/
*.egg-info/

# Rust
target/

# Go / PHP / Ruby vendored deps
vendor/
.bundle/

# Java / Kotlin / Scala
.gradle/

# .NET
bin/
obj/

# Elixir
_build/
deps/

# Dart / Flutter
.dart_tool/
commit 9ebf5fbd2cef623cbb4d140d0c660320192c4977
Author: Workspace Bootstrap <workspace@localhost>
Date:   Sat Jan 1 00:00:00 2000 +0000

    Initial workspace

 .gitignore | 41 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 41 insertions(+)
env | grep -i -E "seek|api|key|token" | sed 's/=.*/=<redacted>/' ; ls /usr/local/lib/node_modules 2>/dev/null
PI_GATEWAY_API_KEY=<redacted>
PI_GATEWAY_API_KEY=<redacted>
GIT_CONFIG_KEY_0=<redacted>
@anthropic-ai
@earendil-works
@openai
corepack
npm
Thinking…

No xSeek anywhere. Let me check network access to see if I could find xSeek docs. But I shouldn't fabricate. Let me quickly check if there's network access and whether xSeek exists as a package/product.

Let me try npm/pip search quickly.

cd /tmp && timeout 25 npm view xseek 2>&1 | head -20; echo "---"; timeout 20 pip index versions xseek 2>&1 | head -5; echo "---pypi json---"; timeout 20 curl -s -o /dev/null -w "%{http_code}\n" https://pypi.org/pypi/xseek/json
npm error code E404
npm error code E404
npm error 404 Not Found - GET https://registry.npmjs.org/xseek - Not found
npm error 404
npm error 404  'xseek@*' is not in this registry.
npm error 404
npm error 404 Note that you can also install from a
npm error 404 tarball, folder, http url, or git url.
npm error A complete log of this run can be found in: /sandbox/.npm/_logs/2026-10-07T17_27_49_624Z-debug-0.log
---
ERROR: No matching distribution found for xseek
---pypi json---
404
timeout 20 curl -s -o /dev/null -w "registry:%{http_code}\n" https://registry.npmjs.org/xseek; timeout 20 curl -s -o /dev/null -w "google:%{http_code}\n" https://www.google.com
registry:404
registry:404
google:200
Thinking…

Network works, but xseek isn't on npm or PyPI. Let me do a quick search to see if "xSeek" is a real product. Maybe it's a fictional product the user is testing. I should not fabricate. Let me try a quick search via a public API (duckduckgo html?).

Careful about long-running commands; keep it quick.

cd /tmp && timeout 25 curl -s "https://html.duckduckgo.com/html/?q=%22xSeek%22+API+SDK+pricing" -A "Mozilla/5.0" | sed -e 's/<[^>]*>/ /g' | tr -s ' \n' ' \n' | head -c 2000
-->
 -->
 
 
 
 
 
 
 
 
 DuckDuckGo
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 DuckDuckGo 
 
 
 
 
 
 
 
 
 Unfortunately, bots use DuckDuckGo too. 
 Please complete the following challenge to confirm this search was made by a human. 
 Select all squares containing a duck: 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Submit 
 
 
 Images not loading? 
 
 Please email the following code to: 
 error-lite+4458@duckduckgo.com 
 Code: 4458 
 
 
 
 
 
 
 
 
 
 
 here . //-->
 
 
 
 
 
 
 
 
 
 
 
cd /tmp && timeout 25 curl -s "https://api.duckduckgo.com/?q=xseek&format=json&no_html=1" | head -c 800; echo; for d in xseek.com xseek.io xseek.ai xseek.dev getxseek.com; do echo -n "$d: "; timeout 8 curl -s -o /dev/null -w "%{http_code}\n" https://$d || echo fail; done
{"Abstract":"","AbstractSource":"","AbstractText":"","AbstractURL":"","Answer":"","AnswerType":"","Definition":"","DefinitionSource":"","DefinitionURL":"","Enti
{"Abstract":"","AbstractSource":"","AbstractText":"","AbstractURL":"","Answer":"","AnswerType":"","Definition":"","DefinitionSource":"","DefinitionURL":"","Entity":"","Heading":"","Image":"","ImageHeight":"","ImageIsLogo":"","ImageWidth":"","Infobox":"","Redirect":"","RelatedTopics":[],"Results":[],"Type":"","meta":{"attribution":null,"blockgroup":null,"created_date":"2021-03-24","description":"testing","designer":null,"dev_date":"2021-03-24","dev_milestone":"development","developer":[{"name":"zt","type":"duck.co","url":"https://duck.co/user/zt"}],"example_query":"","id":"just_another_test","is_stackexchange":0,"js_callback_name":"another_test","live_date":null,"maintainer":{"github":""},"name":"Just Another Test","perl_module":"DDG::Lontail::AnotherTest","producer":null,"production_state"
xseek.com: 200
xseek.io: 308
xseek.ai: 200
xseek.dev: 000
fail
getxseek.com: 000
fail
Thinking…

xseek.com and xseek.ai resolve. Let me look at those pages quickly to see whether they're actually a product called xSeek with an SDK/API. Could be parked domains.

cd /tmp && timeout 25 curl -sL https://xseek.com -A "Mozilla/5.0" | sed -e 's/<script[^>]*>.*<\/script>//g' | sed -e 's/<[^>]*>/ /g' | tr -s ' \n\t' ' \n' | head -c 1500
XSEEK.COM | Strategic-Grade domain names for established businesses and funded startups
 
 
 
 
 XSEEK.COM | Strategic-Grade domain names for established businesses and funded startups 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 * {
 -webkit-font-smoothing: antialiased;
 -moz-osx-font-smoothing: grayscale;
 -o-font-smoothing: antialiased;
}
.support {
 position: absolute;
 top: 15px;
 right: 20px;
 z-index: 10; /* Ensure it stays on top of other elements */
 }
 .support img {
 width: 10em;
 height: auto;
 }
 /* Media query for mobile screens */
 @media screen and (max-width: 768px) {
 .support img {
 width: 5em; /* Smaller size for mobile */
 }
 }
 
 
 
 
 
 
 
 -->
 
 
 
 
 
 
 
 
 
 XSEEK.COM 
 
 The domain name XSEEK.COM is available for sale or other proposals. Contact through Grails for details 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Strategic-Grade domain names for established businesses and funded startups 
 (What does that mean?) -->
 
 A Strategic-Grade domain name delivers a level of value that other domain names cannot 
 Strategic-Grade domains save businesses time, money, and energy while unlocking growth, clarity, and trust. These assets are not specifically chosen for creativity or availability. They are chosen for alignment with long-term strategy. By reducing friction across execution and communication, they strengthen positioning, signal intent, and simplify operations. 
 
 
 Linkedin -->
 © Grails.com 2026. All rights reserved.
 
 -->
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 function toggleDef() {
 var def = document.getElementById('defBox');
 def.style
cd /tmp && timeout 25 curl -sL https://xseek.ai -A "Mozilla/5.0" | sed -e 's/<[^>]*>/ /g' | tr -s ' \n\t' ' \n' | head -c 1500; echo "=== io ==="; timeout 20 curl -sL https://xseek.io -A "Mozilla/5.0" | sed -e 's/<[^>]*>/ /g' | tr -s ' \n\t' ' \n' | head -c 600
=== io ===
=== io ===
 xSeek — Stop guessing. Get cited by AI. (self.__next_s=self.__next_s||[]).push([0,{"children":"(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':\nnew Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],\nj=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=\n'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);\n})(window,document,'script','dataLayer','GTM-NRT748HV');","id":"google-tag-manager"}]) How it works Pricing About Contact Blog FR Sign in Try for free → {"@context":"https://schema.org","@type":"SoftwareApplica
Thinking…

xseek.io is a real product: "xSeek — Stop guessing. Get cited by AI." It redirected (308) from xseek.ai probably. Let's fetch docs: pricing page, docs, API/SDK.

Let me explore xseek.io site: /pricing, /docs, /api.

cd /tmp && timeout 25 curl -sL https://xseek.io -A "Mozilla/5.0" -o xseek_home.html; wc -c xseek_home.html; grep -oE 'href="[^"]+"' xseek_home.html | sort -u | head -60
145319 xseek_home.html
145319 xseek_home.html
href="#tool"
href="/_next/static/chunks/webpack-c45d627606a2d177.js?dpl=dpl_EaB575kyZjvxUudy6P1S4VxLEmjF"
href="/_next/static/css/13e67f5dd4f42c9e.css?dpl=dpl_EaB575kyZjvxUudy6P1S4VxLEmjF"
href="/_next/static/css/995c223ef5463058.css?dpl=dpl_EaB575kyZjvxUudy6P1S4VxLEmjF"
href="/_next/static/css/cb5c46e1ba02c3e6.css?dpl=dpl_EaB575kyZjvxUudy6P1S4VxLEmjF"
href="/_next/static/media/597b6a5d799c44de-s.p.woff2"
href="/_next/static/media/91601dd83defba07-s.p.woff2"
href="/_next/static/media/9cc5b37ab1350db7-s.p.woff2"
href="/_next/static/media/bb3ef058b751a6ad-s.p.woff2"
href="/_next/static/media/e4af272ccee01ff0-s.p.woff2"
href="/_next/static/media/e6099e249fd938cc-s.p.woff2"
href="/blogs"
href="/blogs/articles/ai-seo-strategies"
href="/blogs/articles/llms-txt-explained"
href="/blogs/articles/seo-vs-aeo-complete-comparison-guide"
href="/docs"
href="/en"
href="/en/about"
href="/en/agency"
href="/en/ai-backlinks"
href="/en/ai-content-optimization"
href="/en/ai-search-optimization"
href="/en/ai-visibility-tracking"
href="/en/answer-engine-optimization"
href="/en/chatgpt-seo"
href="/en/contact"
href="/en/customers/conexo"
href="/en/generative-engine-optimization"
href="/en/how-it-works"
href="/en/login"
href="/en/pricing"
href="/en/tools"
href="/en/tools/agent-ready"
href="/en/tools/llms-generator"
href="/en/tools/robots-checker"
href="/favicon.ico"
href="/fr"
href="/privacy"
href="/rss.xml"
href="/sources"
href="/terms"
href="https://alexandra.expquebec.com/"
href="https://bettermeter.com/api/p?s=xseek.io"
href="https://bettermeter.com/api/s"
href="https://calendly.com/mobouchard-xseek/30min"
href="https://chat.openai.com/?q=I&#x27;m%20a%20marketing%20lead%20considering%20xSeek%20(xseek.io)%20for%20AI%20visibility.%20Help%20me%20understand%20what%20xSeek%20does%20and%20who%20it&#x27;s%20for.%0A%0ABased%20on%20what%20you%20know%20about%20xSeek%2C%20answer%20these%20questions%20concretely%3A%0A%0A1.%20What%20problem%20does%20xSeek%20solve%3F%20Why%20should%20marketing%20teams%20care%20about%20being%20visible%20in%20AI%20answers%20from%20ChatGPT%2C%20Claude%2C%20Perplexity%20and%20Gemini%3F%0A%0A2.%20How%20does%20xSeek%20work%20in%203%20steps%3F%20(What%20you%20see%2C%20what%20you%20know%2C%20what%20you%20do)%0A%0A3.%20Who%20is%20it%20built%20for%3F%20Is%20it%20for%20marketing%20teams%2C%20or%20do%20I%20need%20to%20be%20technical%20%2F%20a%20developer%20%2F%20a%20senior%20SEO%3F%0A%0A4.%20How%20is%20it%20different%20from%20traditional%20SEO%20tools%20like%20Ahrefs%20or%20Semrush%3F%0A%0A5.%20What%20results%20can%20I%20realistically%20expect%20in%20the%20first%203%20months%3F%0A%0ABe%20direct%20and%20concrete.%20No%20buzzwords.%20Tell%20me%20what%20I&#x27;d%20actually%20get%20if%20I%20used%20it."
href="https://claude.ai/new?q=I&#x27;m%20a%20marketing%20lead%20considering%20xSeek%20(xseek.io)%20for%20AI%20visibility.%20Help%20me%20understand%20what%20xSeek%20does%20and%20who%20it&#x27;s%20for.%0A%0ABased%20on%20what%20you%20know%20about%20xSeek%2C%20answer%20these%20questions%20concretely%3A%0A%0A1.%20What%20problem%20does%20xSeek%20solve%3F%20Why%20should%20marketing%20teams%20care%20about%20being%20visible%20in%20AI%20answers%20from%20ChatGPT%2C%20Claude%2C%20Perplexity%20and%20Gemini%3F%0A%0A2.%20How%20does%20xSeek%20work%20in%203%20steps%3F%20(What%20you%20see%2C%20what%20you%20know%2C%20what%20you%20do)%0A%0A3.%20Who%20is%20it%20built%20for%3F%20Is%20it%20for%20marketing%20teams%2C%20or%20do%20I%20need%20to%20be%20technical%20%2F%20a%20developer%20%2F%20a%20senior%20SEO%3F%0A%0A4.%20How%20is%20it%20different%20from%20traditional%20SEO%20tools%20like%20Ahrefs%20or%20Semrush%3F%0A%0A5.%20What%20results%20can%20I%20realistically%20expect%20in%20the%20first%203%20months%3F%0A%0ABe%20direct%20and%20concrete.%20No%20buzzwords.%20Tell%20me%20what%20I&#x27;d%20actually%20get%20if%20I%20used%20it."
href="https://flokon.ca/"
href="https://google.com/search?udm=50&amp;source=searchlabs&amp;q=I&#x27;m%20a%20marketing%20lead%20considering%20xSeek%20(xseek.io)%20for%20AI%20visibility.%20Help%20me%20understand%20what%20xSeek%20does%20and%20who%20it&#x27;s%20for.%0A%0ABased%20on%20what%20you%20know%20about%20xSeek%2C%20answer%20these%20questions%20concretely%3A%0A%0A1.%20What%20problem%20does%20xSeek%20solve%3F%20Why%20should%20marketing%20teams%20care%20about%20being%20visible%20in%20AI%20answers%20from%20ChatGPT%2C%20Claude%2C%20Perplexity%20and%20Gemini%3F%0A%0A2.%20How%20does%20xSeek%20work%20in%203%20steps%3F%20(What%20you%20see%2C%20what%20you%20know%2C%20what%20you%20do)%0A%0A3.%20Who%20is%20it%20built%20for%3F%20Is%20it%20for%20marketing%20teams%2C%20or%20do%20I%20need%20to%20be%20technical%20%2F%20a%20developer%20%2F%20a%20senior%20SEO%3F%0A%0A4.%20How%20is%20it%20different%20from%20traditional%20SEO%20tools%20like%20Ahrefs%20or%20Semrush%3F%0A%0A5.%20What%20results%20can%20I%20realistically%20expect%20in%20the%20first%203%20months%3F%0A%0ABe%20direct%20and%20concrete.%20No%20buzzwords.%20Tell%20me%20what%20I&#x27;d%20actually%20get%20if%20I%20used%20it."
href="https://linkedin.com/company/xseek"
href="https://sengo.com"
href="https://slashdot.org/software/p/xseek/"
href="https://snap.licdn.com/li.lms-analytics/insight.min.js"
href="https://sourceforge.net/software/product/xseek/"
href="https://toolchase.com/tool/xseek/"
href="https://topbusinesssoftware.com/products/xseek/reviews/"
href="https://www.googletagmanager.com/gtag/js?id=G-629VWN65Y7"
href="https://www.instagram.com/saaspasse/"
href="https://www.perplexity.ai/?q=I&#x27;m%20a%20marketing%20lead%20considering%20xSeek%20(xseek.io)%20for%20AI%20visibility.%20Help%20me%20understand%20what%20xSeek%20does%20and%20who%20it&#x27;s%20for.%0A%0ABased%20on%20what%20you%20know%20about%20xSeek%2C%20answer%20these%20questions%20concretely%3A%0A%0A1.%20What%20problem%20does%20xSeek%20solve%3F%20Why%20should%20marketing%20teams%20care%20about%20being%20visible%20in%20AI%20answers%20from%20ChatGPT%2C%20Claude%2C%20Perplexity%20and%20Gemini%3F%0A%0A2.%20How%20does%20xSeek%20work%20in%203%20steps%3F%20(What%20you%20see%2C%20what%20you%20know%2C%20what%20you%20do)%0A%0A3.%20Who%20is%20it%20built%20for%3F%20Is%20it%20for%20marketing%20teams%2C%20or%20do%20I%20need%20to%20be%20technical%20%2F%20a%20developer%20%2F%20a%20senior%20SEO%3F%0A%0A4.%20How%20is%20it%20different%20from%20traditional%20SEO%20tools%20like%20Ahrefs%20or%20Semrush%3F%0A%0A5.%20What%20results%20can%20I%20realistically%20expect%20in%20the%20first%203%20months%3F%0A%0ABe%20direct%20and%20concrete.%20No%20buzzwords.%20Tell%20me%20what%20I&#x27;d%20actually%20get%20if%20I%20used%20it."
href="https://www.unikwrap.ca/"
cd /tmp && for p in pricing docs developers api-docs api about; do echo "== /$p =="; timeout 15 curl -sL -o /dev/null -w "%{http_code} %{url_effective}\n" https://xseek.io/$p -A "Mozilla/5.0"; done
== /pricing ==
== /pricing ==
200 https://www.xseek.io/en/pricing
== /docs ==
200 https://www.xseek.io/docs
== /developers ==
404 https://www.xseek.io/developers
== /api-docs ==
200 https://www.xseek.io/api-docs
== /api ==
404 https://www.xseek.io/api
== /about ==
404 https://www.xseek.io/about
Thinking…

There's /docs and /api-docs. Let's fetch them to see if there's an API/SDK.

cd /tmp && timeout 25 curl -sL https://www.xseek.io/api-docs -A "Mozilla/5.0" -o api-docs.html && wc -c api-docs.html && python3 - <<'EOF'
import re,html
t=open('/tmp/api-docs.html',encoding='utf-8',errors='ignore').read()
t=re.sub(r'<script.*?</script>','',t,flags=re.S)
t=re.sub(r'<style.*?</style>','',t,flags=re.S)
t=re.sub(r'<[^>]+>',' ',t)
t=html.unescape(t)
t=re.sub(r'[ \t]+',' ',t)
t=re.sub(r'\n\s*\n+','\n',t)
print(t[:6000])
EOF
132531 api-docs.html
132531 api-docs.html
 xSeek API Docs - Automated GEO for your agency How it works Pricing About Contact Blog FR Sign in Try for free → API Documentation Explore our Enterprise API endpoints for programmatic website management Using an AI agent? Grab the whole API as Markdown. Every endpoint, response shape and a worked agent loop in one file. Copy it, paste it, done. /api-docs.md API Authentication Enter your API key to test the endpoints below API Key Your API key is required to test the endpoints. It will only be used for testing and not stored. MCP Integration Available Integrate xSeek AI SEO tools directly into your development workflow with Model Context Protocol (MCP) Use our MCP server to access AI SEO tools like robots.txt scanning and LLMs.txt generation directly from compatible applications. Learn More View Tools API Version v1.0 Latest stable version Endpoints 38 Available endpoints Authentication Bearer Token-based auth Interactive API Endpoints Click on any endpoint to expand details and test it with your API key Website Management GET /api/v1/robots Get known AI bot user agents and IP ranges for detection (Public - No authentication required) GET /api/v1/websites List all websites for your organization POST /api/v1/websites Create a new website PUT /api/v1/websites/{websiteId} Update an existing website GET /api/v1/websites/{websiteId}/sources Get sources cited by AI in prompt responses for a website with pagination, sorting, and filtering GET /api/v1/websites/{websiteId}/sentiment/runs The answers behind a sentiment label, newest first, each with the sentence that decided the label and the sources the engine cited in that answer. The drill-down from /sentiment/prompts: from a prompt that reads negative, list its negative answers, then the pages they leaned on. The full answer text is returned only with includeAnswer=true. GET /api/v1/websites/{websiteId}/metrics/ai-clicks AI referral clicks: total, share of total traffic, per-engine breakdown and a daily time series. These are real visitors arriving from an AI assistant, measured as GA4 sessions — not AI crawler visits. Requires GA4 to be connected; when it is not, the response returns available:false with a reason instead of zeros. Privilege: ai_visits:read GET /api/v1/websites/{websiteId}/metrics/top-pages Pages ranked by AI referral clicks, with Search Console impressions and the assistant sending the most traffic to each. Note that aiClicks and impressions do not cover the same days: clicks honour your date range, while impressions come from a fixed Search Console scan of the last 7, 30 or 90 days. The response says which one was used in impressionsWindowDays. A page with no Search Console row returns impressions null, not 0. Privilege: ai_visits:read GET /api/v1/websites/{websiteId}/metrics/share-of-voice Share of voice over time, optionally scoped to one topic or audience. The denominator is the tracked set (your brand plus its competitors, aliases included), which is the same figure the xSeek dashboard shows. Topics flagged excludeFromSov are always removed. Privilege: prompts:read GET /api/v1/websites/{websiteId}/topics Audiences and their topics for a website. Use these ids to scope /metrics/share-of-voice, and to resolve the topicId returned by /prompts. excludeFromSov marks informational topics where AI cites content without naming companies; they are dropped from every share-of-voice figure. Privilege: prompts:read GET /api/v1/websites/{websiteId}/keywords Search keywords with volume, difficulty, and related keywords from DataForSEO. Uses the website language and location settings by default. GET /api/v1/websites/{websiteId}/keywords Get keyword search history for the website (no query parameter returns history) GET /api/v1/websites/{websiteId}/opportunities Get content opportunities — queries where competitors are cited by AI but your site is not. Enriched with SEO data. GET /api/v1/websites/{websiteId}/articles List articles in Content Studio for a website. Supports status and language filtering, pagination, and a public-blog view that returns published snapshots. POST /api/v1/websites/{websiteId}/articles Create or upsert an article. If an article with the same slug already exists for this website, it is updated in place (200) instead of duplicated (201). Auto-links to a matching current-month opportunity when opportunityId is omitted. GET /api/v1/websites/{websiteId}/articles/{articleId} Get full article details including the markdown body, schema markup, and generation metadata. ?view=public returns the published snapshot. PATCH /api/v1/websites/{websiteId}/articles/{articleId} Update an article. Any field can be omitted. Setting status="published" snapshots the current title/content/meta/schema into the public-blog view. Changes to content, title, or quality score also write an entry to the revision history. GET /api/v1/websites/{websiteId}/articles/by-slug/{slug} Fetch a single article by its slug. Mirrors the by-id endpoint shape — used by the public blog runtime to look up articles without exposing internal IDs. GET /api/v1/websites/{websiteId}/articles/{articleId}/comments List editorial comments attached to an article. Comments anchor to a specific text range (selectedText + startOffset/endOffset) so editors can resolve them inline. POST /api/v1/websites/{websiteId}/articles/{articleId}/comments Create an editorial comment on a text range. Used by external review tools to flag changes for the editor to apply. PATCH /api/v1/websites/{websiteId}/articles/{articleId}/comments Resolve or un-resolve an existing comment. Pass the comment id in the body alongside the new resolved state. AI Visits GET /api/v1/websites/{websiteId}/ai-visits Get aggregated AI bot visit traffic by URL with search, pagination, and filters POST /api/v1/websites/{websiteId}/ai-visits Publish a new AI bot visit for a specific website LLM Queries GET /api/v1/websites/{websiteId}/llm-queries List LLM queries for a specific website with pagination and sea
cd /tmp && timeout 25 curl -sL https://www.xseek.io/docs -A "Mozilla/5.0" -o docs.html && python3 - <<'EOF'
import re,html
t=open('/tmp/docs.html',encoding='utf-8',errors='ignore').read()
t=re.sub(r'<script.*?</script>','',t,flags=re.S)
t=re.sub(r'<style.*?</style>','',t,flags=re.S)
links=re.findall(r'href="([^"]+)"',t)
print("LINKS:", sorted(set(l for l in links if 'xseek' in l or l.startswith('/')))[:80])
t=re.sub(r'<[^>]+>',' ',t)
t=html.unescape(t); t=re.sub(r'[ \t]+',' ',t); t=re.sub(r'\n\s*\n+','\n',t)
print(t[:4000])
EOF
LINKS: ['/', '/_next/static/chunks/webpack-c45d627606a2d177.js?dpl=dpl_EaB575kyZjvxUudy6P1S4VxLEmjF', '/_next/static/css/13e67f5dd4f42c9e.css?dpl=dpl_EaB575kyZj
LINKS: ['/', '/_next/static/chunks/webpack-c45d627606a2d177.js?dpl=dpl_EaB575kyZjvxUudy6P1S4VxLEmjF', '/_next/static/css/13e67f5dd4f42c9e.css?dpl=dpl_EaB575kyZjvxUudy6P1S4VxLEmjF', '/_next/static/css/995c223ef5463058.css?dpl=dpl_EaB575kyZjvxUudy6P1S4VxLEmjF', '/_next/static/css/cb5c46e1ba02c3e6.css?dpl=dpl_EaB575kyZjvxUudy6P1S4VxLEmjF', '/_next/static/media/597b6a5d799c44de-s.p.woff2', '/_next/static/media/91601dd83defba07-s.p.woff2', '/_next/static/media/9cc5b37ab1350db7-s.p.woff2', '/_next/static/media/bb3ef058b751a6ad-s.p.woff2', '/_next/static/media/e4af272ccee01ff0-s.p.woff2', '/_next/static/media/e6099e249fd938cc-s.p.woff2', '/blogs', '/blogs/articles/ai-seo-strategies', '/blogs/articles/llms-txt-explained', '/blogs/articles/seo-vs-aeo-complete-comparison-guide', '/contact', '/docs', '/docs/ai-robots-txt-guide', '/docs/baidu-ernie-user-agents', '/docs/bing-ai-user-agents', '/docs/chatgpt-ads-and-ranking', '/docs/claude-user-agents', '/docs/deepseek-user-agents', '/docs/doubao-user-agents', '/docs/generating-prompt-for-prompt-ready-tracking', '/docs/kimi-user-agents', '/docs/llama-user-agents', '/docs/mistral-user-agents', '/docs/openai-crawlers-and-user-agents', '/docs/perplexity-user-agents', '/docs/qwen-user-agents', '/en', '/en/about', '/en/agency', '/en/ai-backlinks', '/en/ai-content-optimization', '/en/ai-search-optimization', '/en/ai-visibility-tracking', '/en/answer-engine-optimization', '/en/chatgpt-seo', '/en/contact', '/en/generative-engine-optimization', '/en/how-it-works', '/en/integrations', '/en/login', '/en/pricing', '/en/tools', '/en/tools/agent-ready', '/en/tools/llms-generator', '/en/tools/robots-checker', '/favicon.ico', '/fr/docs', '/meet', '/privacy', '/rss.xml', '/sources', '/terms', 'https://bettermeter.com/api/p?s=xseek.io', 'https://linkedin.com/company/xseek', 'https://slashdot.org/software/p/xseek/', 'https://sourceforge.net/software/product/xseek/', 'https://toolchase.com/tool/xseek/', 'https://topbusinesssoftware.com/products/xseek/reviews/', 'https://www.youtube.com/@xseek-io', 'https://x.com/xseekio', 'https://xseek.io/rss.xml']
 Documentation — xSeek How it works Pricing About Contact Blog FR Sign in Try for free → xSeek / Docs ⌘K Documentation Getting started Key features How it works Guides Generating prompts AI robots.txt guide ChatGPT ads & ranking Integrations All integrations User agents OpenAI Claude Perplexity Mistral Bing AI Llama Baidu ERNIE Kimi Qwen DeepSeek Doubao Documentation Get your brand cited by AI. xSeek is the AI visibility platform that helps you optimize your site for AI search engines and large language models. Start here. Updated Apr 2026 ~12 min read For owners & marketers 01 Getting started → Create your account, add a site, set tracked keywords in 5 steps. 02 Key features → LLM tracking, AI insights, competitor analysis, optimization. 03 How it works → Data collection, analysis, recommendations, and monitoring. Getting started 5 steps · 10 min Welcome to xSeek. This walkthrough takes you from signup to your first dashboard of real visibility data. 01 Create an account Sign up by visiting the signup page. Choose the plan that fits your needs and complete registration. i Tip. Compare plans to find the best fit — Starter for solo operators, Growth for teams, Scale for agencies. 02 Add your website From the dashboard, add your website URL. We verify ownership through Google Search Console integration or a meta-tag check. Takes under a minute. 03 Set up your first keywords Add keywords relevant to your business. We'll start monitoring your rankings across ChatGPT, Claude, Perplexity, and other LLMs. ! Note. Tracked keywords depend on your plan — from 3 on Starter to unlimited on Scale. 04 Review your dashboard Your dashboard populates with initial data right away. Full baseline metrics across all engines take 24–48 hours to settle. 05 Create AI agents with MCP. Set up automated AI agents using our Model Context Protocol integration. Configure Claude Code or other assistants to continuously monitor and optimize your AI search performance — on autopilot. i Install the xSeek CLI with curl -fsSL https://cli.xseek.io/install.sh | sh to register it as an MCP server with Claude Code: 19 tools, 8 resources, ready in one curl. Key features 4 pillars xSeek offers a comprehensive suite of tools to monitor and improve your website's performance in AI search results. LLM real-time tracking Monitor your website's ranking across ChatGPT, Claude, Perplexity, Gemini, and more — with real-time data, not weekly snapshots. AI-powered insights Receive intelligent recommendations to optimize your content for better performance in AI search — prioritized by visibility lift. Competitor analysis Compare your AEO performance against competitors. See exactly where they rank, what they're cited for, and where you can take share. Content optimization Specific, page-level recommendations for improving visibility in AI search results — what to write, what to restructure, what to retire. How it works Pipeline xSeek uses advanced technology to track and analyze your website's performance in AI search engines. Four stages, fully automated. 1 Data collection We query LLMs with your target keywords and analyze where your site appears — mentions, rankings, and surrounding context. 2 Analysis Our AI identifies patterns, opportunities, and issues affecting your performance in AI search results. 3 Recommendations You get actionable recommendations to improve content, structure, and AI ranking strategy. Prioritized, not dumped. 4 Monitoring Continuous monitoring with regular reports and alerts — so you know the moment something moves. Featured guides. All guides → Optimization Featured Generating prompts for xSeek tracking. Create effective prompts that optimize your content for different LLMs — Claude, OpenAI, xAI, Llama, and more. Read guide → 6 min · Updated Mar 2026 Reference Complete AI robots.txt guide. Every AI crawler and user agent from major companies, with copy-paste configurations for your robots.txt . Read guide → 12 min · Updated Apr 2026 Playbook ChatGP
Thinking…

xSeek is a real product with a REST API (v1, 38 endpoints), an api-docs.md file for agents, and an MCP server + CLI. So there IS a developer workflow.

Now: pricing. Fetch /en/pricing. And fetch /api-docs.md to see public endpoints I can actually call without an API key (e.g., GET /api/v1/robots is public — no auth). That would let me build a working example without credentials.

Let me get pricing and api-docs.md.

cd /tmp && timeout 25 curl -sL https://www.xseek.io/api-docs.md -A "Mozilla/5.0" -o api-docs.md && wc -l api-docs.md && head -120 api-docs.md
1858 api-docs.md
1858 api-docs.md
# xSeek API reference

xSeek tracks how AI search engines (ChatGPT, Perplexity, Gemini, Google AI
Overview and others) answer questions about a brand: which companies they name,
which pages they cite, and what a site should publish next to get cited.

This file is the whole v1 API in one page, written to be pasted into an AI agent
or coding assistant. Everything below is generated from the same definitions that
render the HTML docs at https://www.xseek.io/api-docs, so it cannot drift from them.

- **Base URL:** `https://www.xseek.io`
- **Format:** JSON request and response bodies. UTF-8.
- **Endpoints documented here:** 38

## Authentication

Every v1 endpoint takes an API key as a bearer token:

```bash
curl -H "Authorization: Bearer $XSEEK_API_KEY" \
  "https://www.xseek.io/api/v1/websites/$WEBSITE_ID/metrics/ai-clicks?days=30"
```

Create a key in the dashboard under **Settings → API keys**. A key belongs to one
organization and can only read that organization's websites; asking for a
`websiteId` outside it returns `404`, not `403`, so an ID cannot be probed.

### Privileges

Keys carry explicit privileges. A call missing one returns `401` with a message
naming the privilege it wanted. Grant the narrowest set that works:

| Privilege | Grants |
| --- | --- |
| `ai_visits:push` | Write AI crawler visits |
| `ai_visits:read` | Read AI crawler visits and referral-click metrics |
| `llm_queries:read` | Read the LLM queries a site appears in |
| `websites:create` / `websites:read` / `websites:update` | Manage websites |
| `prompts:create` / `prompts:read` / `prompts:update` | Manage tracked prompts, topics, share of voice |
| `articles:read` / `articles:write` | Read and push Content Studio articles |
| `images:write` | Upload article images |

### Errors

| Status | Meaning |
| --- | --- |
| `400` | Validation failed. The body carries `details[]` with the offending field. |
| `401` | Missing, invalid, disabled, or under-privileged key. |
| `404` | The website or record does not exist **or** is not yours. |
| `500` | Server error. Safe to retry with backoff. |

## Reading the numbers correctly

Three rules the data follows. An agent that ignores them will report things that
are not true:

1. **An unmeasured value is `null`, never `0`.** If GA4 is not connected, the
   metrics endpoints return `available: false` with an `unavailableReason`
   instead of a row of zeros. A page with no Search Console row returns
   `impressions: null`. Do not coerce these to `0` before charting.
2. **`/ai-visits` and `/metrics/ai-clicks` are different things.** The first
   counts AI **crawlers** fetching your pages, where nobody landed on the site.
   The second counts **real people** who arrived from an AI assistant, measured
   as GA4 sessions. Labelling one as the other is the most common way to build a
   wrong dashboard.
3. **Share of voice is measured against the tracked set**, meaning your brand
   plus the competitors configured for that website, aliases included. Topics
   flagged `excludeFromSov` are always removed.

## Contents

- **Reporting metrics**
  - `GET /api/v1/websites/{websiteId}/metrics/ai-clicks`
  - `GET /api/v1/websites/{websiteId}/metrics/top-pages`
  - `GET /api/v1/websites/{websiteId}/metrics/share-of-voice`
- **Prompts & topics**
  - `GET /api/v1/websites/{websiteId}/prompts`
  - `POST /api/v1/websites/{websiteId}/prompts`
  - `GET /api/v1/websites/{websiteId}/prompts/{promptId}`
  - `PUT /api/v1/websites/{websiteId}/prompts/{promptId}`
  - `GET /api/v1/websites/{websiteId}/prompts/{promptId}/runs`
  - `GET /api/v1/websites/{websiteId}/sentiment/prompts`
  - `GET /api/v1/websites/{websiteId}/prompts/leaderboard`
  - `GET /api/v1/websites/{websiteId}/topics`
- **Action plan**
  - `GET /api/v1/websites/{websiteId}/opportunities`
- **Content Studio (articles)**
  - `GET /api/v1/websites/{websiteId}/articles`
  - `POST /api/v1/websites/{websiteId}/articles`
  - `GET /api/v1/websites/{websiteId}/articles/{articleId}`
  - `PATCH /api/v1/websites/{websiteId}/articles/{articleId}`
  - `GET /api/v1/websites/{websiteId}/articles/by-slug/{slug}`
  - `GET /api/v1/websites/{websiteId}/articles/{articleId}/comments`
  - `POST /api/v1/websites/{websiteId}/articles/{articleId}/comments`
  - `PATCH /api/v1/websites/{websiteId}/articles/{articleId}/comments`
- **Websites & data**
  - `GET /api/v1/websites/{websiteId}/llm-queries`
  - `GET /api/v1/websites/{websiteId}/llm-queries/by-page`
  - `GET /api/v1/websites`
  - `POST /api/v1/websites`
  - `PUT /api/v1/websites/{websiteId}`
  - `GET /api/v1/websites/{websiteId}/sources`
  - `GET /api/v1/websites/{websiteId}/sentiment/runs`
  - `GET /api/v1/websites/{websiteId}/ai-visits`
  - `POST /api/v1/websites/{websiteId}/ai-visits`
  - `GET /api/v1/websites/{websiteId}/keywords`
  - `GET /api/v1/websites/{websiteId}/keywords`
- **Technical**
  - `GET /api/v1/robots`
  - `GET /api/v1/tools/robots-txt`
  - `GET /api/v1/websites/{websiteId}/robots-scans`
  - `GET /api/v1/websites/{websiteId}/robots-scans/latest`
- **API keys**
  - `GET /api/v1/api-keys`
  - `POST /api/v1/api-keys`
- **Other**
  - `GET /api/v1/tools/llms-txt`

## Reporting metrics

cd /tmp && timeout 25 curl -sL https://www.xseek.io/en/pricing -A "Mozilla/5.0" -o pricing.html && python3 - <<'EOF'
import re,html
t=open('/tmp/pricing.html',encoding='utf-8',errors='ignore').read()
t=re.sub(r'<script.*?</script>','',t,flags=re.S)
t=re.sub(r'<style.*?</style>','',t,flags=re.S)
t=re.sub(r'<[^>]+>','\n',t)
t=html.unescape(t)
t=re.sub(r'[ \t]+',' ',t)
t=re.sub(r'\n\s*\n+','\n',t)
print(t[:7000])
EOF
xSeek · Stop guessing. Get cited by AI.

xSeek · Stop guessing. Get cited by AI.
How it works
Pricing
About
Contact
Blog
FR
Sign in
Try for free
→
Pricing
Understanding isn't enough.
It's time to act.
You don't need to be technical to get results. You need to know where you're going, a clear plan, and the right tools to get there.
Sound familiar?
The signs that never lie.
You publish content hoping AI will pick it up
You check ChatGPT manually to see if you show up
Your competitors keep getting recommended
You have no idea which queries AI answers about you
Your SEO works on Google but AI is a blind spot
You publish content hoping AI will pick it up
You check ChatGPT manually to see if you show up
Your competitors keep getting recommended
You have no idea which queries AI answers about you
Your SEO works on Google but AI is a blind spot
You don't know why competitors get cited
You take action with no clear direction
You can't measure your AI visibility
Marketing feels like guesswork
You're invisible where decisions are being made
You don't know why competitors get cited
You take action with no clear direction
You can't measure your AI visibility
Marketing feels like guesswork
You're invisible where decisions are being made
Billed monthly · cancel anytime
USD
CAD
01 · Starter
Starter
Understand + start taking action
$249.99
/mo
USD
Strategic onboarding included · cancel anytime
« 
Stop guessing. Start understanding.
 »
50 prompts tracked
Dedicated account specialist
Basic AI visibility analysis
Mention tracking across AI engines
Simplified insights
Basic recommendations
10
opportunities
1
websites
∞
users
Supported models
ChatGPT
xAI
Perplexity
AI Overview
Gemini
Claude
DeepSeek
Copilot
Get started
→
Most popular
02 · Growth
Growth
I know what to do and I do it
$499.99
/mo
USD
Strategic onboarding included · cancel anytime
« 
From "I understand" to "I know exactly what to do."
 »
150 prompts tracked
Dedicated account specialist
Complete analysis (AI + competitors)
Advanced multi-platform tracking
Clear action plan
Backlink Agent (AI outreach + link exchange)
Continuous optimization
Full platform access
25
opportunities
3
websites
∞
users
Supported models
ChatGPT
xAI
Perplexity
AI Overview
Gemini
Claude
DeepSeek
Copilot
Get started
→
03 · Scale
Scale
I'm guided to maximize my results
Custom
Pricing adapted to your needs
« 
Maximize impact with personalized guidance.
 »
500 prompts tracked
Everything in Growth, plus:
Personalized strategic guidance
1:1 monthly session with AI strategist
Priority support
Custom integrations
99.99% uptime SLA
SSO / SAML
50
opportunities
10
websites
∞
users
Supported models
ChatGPT
xAI
Perplexity
AI Overview
Gemini
Claude
DeepSeek
Copilot
Book a 30-min call
→
Strategic onboarding
included.
Before you start, we set up everything together: your platform, your settings, your key information. We walk you through how to use the tool so you know exactly where to start. No guessing.
Every plan includes a strategic onboarding session.
See the full integration plan
→
Real brands.
Real outcomes.
Teams now visible in AI. Real leads, signed contracts, growing share of voice.
“
Four months on xSeek and we went from invisible to recommended. We've already received leads and signed contracts that came directly from ChatGPT. It's a real acquisition channel now.
”
+500
AI impressions / day
Jean-Nicolas Gauthier
Founder
, 
Sengo
sengo.com
“
Four months on xSeek and we went from invisible to recommended. We've already received leads and signed contracts that came directly from ChatGPT. It's a real acquisition channel now.
”
+500
AI impressions / day
Jean-Nicolas Gauthier
Founder
, 
Sengo
sengo.com
“
We were already doing traditional SEO inside our province. When we wanted to expand beyond it, we went GEO with xSeek. We didn't believe the demand was there, until the leads started landing a few months later.
”
5
×
AI impressions / month
Michael Roussel
Co-Founder
, 
Flokon
flokon.ca
“
We like xSeek so much!! We started our GEO and SEO journey with them, and the AI-automated recommendations save us hours every week.
”
+200
%
AI clicks / day
Antoine Veilleux
Founder
, 
Unik Wrap
unikwrap.ca
“
I'm an independent agent in a market full of big-name brokerages. ChatGPT now recommends me alongside them when buyers ask who to work with in my region.
”
Top 5
agents AI recommends in her region
Alexandra Anctil
Real Estate Agent
, 
EXP Realty
alexandra.expquebec.com
xSeek vs. the alternatives
Not another
AI tool.
xSeek
GEO tool
SEO / GEO agency
In-house hire
SEO suite + AI add-on
From guessing to cited, end to end
—
Slowly
Depends
—
Dedicated human who knows your brand
—
—
8+ search engines covered
Partial
—
Depends
Partial
No technical expertise required
—
—
—
Scales without new hires
—
—
Results compound month over month
—
Partial
Partial
—
Our positioning
xSeek gives you the clarity
to act.
We show you how AI sees you, tell you exactly what to create and optimize, and help you get cited in the answers that matter.
Is
this for you?
This is for you if
You want clarity,
not another tool.
You're a marketing lead or business owner
You want to understand AI visibility without being technical
You're ready to act with a clear plan
You want measurable results, not just reports
Not for you if
You're looking
for a passive agency.
You want someone to do everything for you
You're not ready to invest in AI presence
You expect results without action
The transformation
From guessing
to clarity.
Before
Content published hoping something sticks
No idea if AI recommends you
Manual ChatGPT checks, occasionally
Marketing feels like improvisation
After
You know exactly which content to create
Share of voice growing week by week
Dashboard tracking every AI engine
Marketing is clear, structured, measured
Limited window
This window
won't stay open.
Every month without a plan, your competitors get recommended instead of you. The brands in AI answers today are cementing their spot.
Every month you wait makes it harder to catch up.
20
% / MONTH
AI search grows 20% every month. The brands optimizing now are building a lead that will take years to close.
FAQ
Frequently
asked questions.
Find answers to common questions about generative engine optimization and our platform.
Another question? Write to us
What is generative engine optimization?
It's SEO for AI answers: structuring your content, data, and authority so ChatGPT, AI Overview, Claude, Perplexity, Gemini and Grok cite you when people ask questions in your industry.
How is traffic shifting from Google to ChatGPT?
Users ask their questions directly to AI instead of clicking 10 blue links. Result: Google organic traffic flattens or drops, but AI answers influence the purchase decision. Your bet becomes being cited in the answer, not just ranking on Google.
Can I try your app for free?
We prefer an advice-first approach: book a 30-minute call with a strategist. We look at your AI profile live and tell you honestly whether xSeek is for you. No generic demo.
How does xSeek compare brand
Thinking…

Now, I have pricing: Starter $249.99/mo, Growth $499.99/mo, Scale custom. Billed monthly, cancel anytime, USD/CAD toggle. No free trial (advice-first, book a call).

Now for building an example: the API needs an API key. There are public endpoints: GET /api/v1/robots (public - no auth), GET /api/v1/tools/robots-txt, GET /api/v1/tools/llms-txt. Let me check api-docs.md for those public endpoints and test them.

Let me grep the docs for "no auth" / public.

cd /tmp && grep -n -i -E "public|no auth|without auth" api-docs.md | head -30
736:List articles in Content Studio for a website. Supports status and language filtering, pagination, and a public-blog view that returns published snapshots.
736:List articles in Content Studio for a website. Supports status and language filtering, pagination, and a public-blog view that returns published snapshots.
749:| `view` | string | no | Set to "public" to return only blog-eligible articles using their published snapshots |
808:| `status` | string | no | draft (default), ready, published, archived. Setting "published" snapshots the current fields to the public-blog view. |
834:Get full article details including the markdown body, schema markup, and generation metadata. ?view=public returns the published snapshot.
847:| `view` | string | no | Set to "public" to return the last published snapshot instead of the working draft |
878:Update an article. Any field can be omitted. Setting status="published" snapshots the current title/content/meta/schema into the public-blog view. Changes to content, title, or quality score also write an entry to the revision history.
924:Fetch a single article by its slug. Mirrors the by-id endpoint shape — used by the public blog runtime to look up articles without exposing internal IDs.
937:| `view` | string | no | Set to "public" to return the published snapshot instead of the working draft |
1557:Get known AI bot user agents and IP ranges for detection (Public - No authentication required)
cd /tmp && grep -n -A 40 "^### \`GET /api/v1/tools/llms-txt\`" api-docs.md | head -70
(no output)
(no output)
Thinking…

Only /api/v1/robots is public. Let's check the tools/robots-txt and tools/llms-txt sections in the docs.

cd /tmp && sed -n '1540,1700p' api-docs.md
"query": "ai search optimization",
      "query": "ai search optimization",
      "language": "en",
      "location": 2840,
      "matchedKeyword": "ai search optimization",
      "searchVolume": 880,
      "keywordDifficulty": 39,
      "createdAt": "2026-03-30T12:00:00Z"
    }
  ]
}
```


## Technical

### GET /api/v1/robots

Get known AI bot user agents and IP ranges for detection (Public - No authentication required)

**Query parameters**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `format` | string | no | Response format: full (default), compact, or patterns-only |
| `company` | string | no | Filter by company name (e.g., openai, anthropic, google) |

**Response**

```json
{
  "success": true,
  "data": {
    "companies": {
      "openai": {
        "userAgents": [
          {
            "name": "GPTBot",
            "userAgent": "Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; GPTBot/1.0; +https://openai.com/gptbot)",
            "pattern": "GPTBot",
            "patternFlags": "i",
            "description": "OpenAI GPTBot crawler"
          }
        ],
        "ips": []
      },
      "anthropic": {
        "userAgents": [
          {
            "name": "anthropic-ai",
            "userAgent": "Mozilla/5.0 (compatible; anthropic-ai/1.0; +http://www.anthropic.com/bot.html)",
            "pattern": "anthropic-ai",
            "patternFlags": "i",
            "description": "Anthropic AI crawler for Claude"
          }
        ],
        "ips": []
      }
    },
    "totalCompanies": 15,
    "totalAgents": 42,
    "lastUpdated": "2024-01-02T12:00:00.000Z"
  }
}
```

---

### GET /api/v1/tools/robots-txt

Scan robots.txt for a given URL and return allowed/disallowed AI bots

**Query parameters**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `url` | string | yes | Target site URL (e.g., https://example.com) |

**Response**

```json
{
  "success": true,
  "data": {
    "id": "scan-id",
    "url": "https://example.com",
    "scanDate": "2024-01-02T12:00:00Z",
    "robotsTxtContent": "User-agent: *\nDisallow: /admin",
    "allowedBots": [
      "gptbot",
      "perplexitybot"
    ],
    "disallowedBots": [
      "claudebot"
    ],
    "status": "success",
    "errorMessage": null,
    "ipAddress": "203.0.113.10",
    "userAgent": "Mozilla/5.0"
  }
}
```

---

### GET /api/v1/websites/{websiteId}/robots-scans

List robots.txt scans for a website (most recent first)

**Path parameters**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `websiteId` | string | yes | The unique identifier of the website |

**Response**

```json
[
  {
    "id": "scan-uuid",
    "websiteId": "website-uuid",
    "organizationId": "org-uuid",
    "scanDate": "2024-01-02T12:00:00Z",
    "robotsTxtContent": "User-agent: *\nDisallow: /admin",
    "allowedBots": [
      "gptbot"
    ],
    "disallowedBots": [
      "badbot"
    ],
    "status": "success",
    "errorMessage": null
  }
]
```

---

### GET /api/v1/websites/{websiteId}/robots-scans/latest

Get the latest robots.txt scan for a website

**Path parameters**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `websiteId` | string | yes | The unique identifier of the website |

**Response**

```json
{
  "id": "scan-uuid",
  "websiteId": "website-uuid",
  "organizationId": "org-uuid",
  "scanDate": "2024-01-02T12:00:00Z",
  "robotsTxtContent": "User-agent: *\nDisallow: /admin",
  "allowedBots": [
    "gptbot"
  ],
  "disallowedBots": [
Thinking…

Now let's test the endpoints live without an API key: /api/v1/robots, /api/v1/tools/robots-txt?url=..., /api/v1/tools/llms-txt?url=...

Let me check llms-txt doc section too.

cd /tmp && grep -n -A 30 "tools/llms-txt" api-docs.md | head -60
117: - `GET /api/v1/tools/llms-txt`
117:  - `GET /api/v1/tools/llms-txt`
118-
119-## Reporting metrics
120-
121-### GET /api/v1/websites/{websiteId}/metrics/ai-clicks
122-
123-AI referral clicks: total, share of total traffic, per-engine breakdown and a daily time series. These are real visitors arriving from an AI assistant, measured as GA4 sessions — not AI crawler visits. Requires GA4 to be connected; when it is not, the response returns available:false with a reason instead of zeros. Privilege: ai_visits:read
124-
125-**Path parameters**
126-
127-| Name | Type | Required | Description |
128-| --- | --- | --- | --- |
129-| `websiteId` | string | yes | The unique identifier of the website |
130-
131-**Query parameters**
132-
133-| Name | Type | Required | Description |
134-| --- | --- | --- | --- |
135-| `startDate` | string | no | Start date, YYYY-MM-DD. Defaults to 30 days ago |
136-| `endDate` | string | no | End date, YYYY-MM-DD. Defaults to yesterday, because the current day is still being written and would report a partial count |
137-| `days` | number | no | Trailing window shorthand, 1-365. Ignored when startDate is given |
138-
139-**Response**
140-
141-```json
142-{
143-  "success": true,
144-  "data": {
145-    "metric": "aiReferralClicks",
146-    "startDate": "2026-07-01",
147-    "endDate": "2026-07-31",
--
1756:### GET /api/v1/tools/llms-txt
1757-
1758-Generate LLMs.txt content for a given URL
1759-
1760-**Query parameters**
1761-
1762-| Name | Type | Required | Description |
1763-| --- | --- | --- | --- |
1764-| `url` | string | yes | Target site URL (e.g., https://example.com) |
1765-
1766-**Response**
1767-
1768-```json
1769-{
1770-  "success": true,
1771-  "data": "Website description and rules for LLMs"
1772-}
1773-```
1774-
1775-
1776-## Building an agent against this API
1777-
1778-A minimal loop that answers "how visible are we, and what should we publish
1779-next". Every call below is documented above.
1780-
1781-```http
1782-# 1. Which websites can this key see?
1783-GET  /api/v1/websites
cd /tmp && echo "== robots =="; timeout 20 curl -s "https://www.xseek.io/api/v1/robots?format=compact" | head -c 600; echo; echo "== robots-txt =="; timeout 25 curl -s "https://www.xseek.io/api/v1/tools/robots-txt?url=https://example.com" | head -c 800; echo; echo "== llms-txt =="; timeout 25 curl -s "https://www.xseek.io/api/v1/tools/llms-txt?url=https://example.com" | head -c 600
== robots ==
== robots ==
{"success":true,"data":{"agents":[{"name":"anthropic-ai","company":"anthropic","userAgent":"Mozilla/5.0 (compatible; anthropic-ai/1.0; +http://www.anthropic.com/bot.html)","pattern":"anthropic-ai","patternFlags":"i","description":"Legacy Anthropic AI crawler for Claude"},{"name":"claudebot","company":"anthropic","userAgent":"Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko); compatible; ClaudeBot/1.0; +claudebot@anthropic.com)","pattern":"ClaudeBot","patternFlags":"i","description":"ClaudeBot training crawler for web data collection"},{"name":"claude-web","company":"anthropic","userAgent":"Mo
== robots-txt ==
{"error":"Missing or invalid authorization header","message":"Please provide a valid API key in the Authorization header as \"Bearer YOUR_API_KEY\""}
== llms-txt ==
{"error":"Missing or invalid authorization header","message":"Please provide a valid API key in the Authorization header as \"Bearer YOUR_API_KEY\""}
Thinking…

So only /api/v1/robots is public. Everything else requires an API key created in the dashboard (Settings → API keys), and there's no free trial/self-serve signup (they prefer a 30-min call). So I'm blocked on the authenticated parts.

What can I do "light"? I can build a small example that:

  1. Uses the public endpoint (no key) — works right now, verified.
  2. Uses authenticated endpoints when XSEEK_API_KEY is set — a thin client wrapper with graceful 401 handling.

That's a legitimate "simple example using xSeek" via its hosted API. No local service stacks, no long-running commands.

Let me check the agent loop section at the end of api-docs.md and the MCP/CLI info for completeness. Also check if there's a public CLI install script — but installing a CLI would be downloading and running a script; the docs say curl -fsSL https://cli.xseek.io/install.sh | sh. That's arguably fine but it registers an MCP server and requires an API key too. I'll mention it but not run it (it needs credentials and it's a local install — not needed for a light example). Actually let me check whether cli.xseek.io resolves, just to be accurate in what I say. Quick HEAD request.

Let me read the agent-loop section.

cd /tmp && sed -n '1776,1858p' api-docs.md
## Building an agent against this API
## Building an agent against this API

A minimal loop that answers "how visible are we, and what should we publish
next". Every call below is documented above.

```http
# 1. Which websites can this key see?
GET  /api/v1/websites

# 2. Visibility over the last 30 days
GET  /api/v1/websites/{websiteId}/metrics/share-of-voice?days=30
GET  /api/v1/websites/{websiteId}/metrics/ai-clicks?days=30

# 3. Where the visibility comes from
GET  /api/v1/websites/{websiteId}/prompts
GET  /api/v1/websites/{websiteId}/sources
GET  /api/v1/websites/{websiteId}/metrics/top-pages?days=30

# 4. What to do about it
GET  /api/v1/websites/{websiteId}/opportunities

# 5. Write the answer back
POST /api/v1/websites/{websiteId}/articles
```

### Worked example

```javascript
const BASE = 'https://www.xseek.io';
const headers = { Authorization: `Bearer ${process.env.XSEEK_API_KEY}` };

async function get(path) {
  const res = await fetch(`${BASE}${path}`, { headers });
  if (!res.ok) throw new Error(`${res.status} on ${path}: ${await res.text()}`);
  return res.json();
}

const websiteId = '<uuid>';

// Visibility. shareOfVoice is 0..1, or null when nothing was measured.
const sov = await get(`/api/v1/websites/${websiteId}/metrics/share-of-voice?days=30`);
if (sov.data.shareOfVoice === null) {
  console.log('No measurements in this window.');
} else {
  console.log(`Share of voice: ${(sov.data.shareOfVoice * 100).toFixed(1)}%`);
}

// Real visitors from AI assistants. Check availability before reading counts.
const clicks = await get(`/api/v1/websites/${websiteId}/metrics/ai-clicks?days=30`);
if (!clicks.data.available) {
  console.log(`AI clicks unavailable: ${clicks.data.unavailableReason}`);
} else {
  for (const e of clicks.data.byEngine) {
    console.log(`${e.engine}: ${e.clicks} clicks`);
  }
}

// The action plan, already reasoned and ranked.
const plan = await get(`/api/v1/websites/${websiteId}/opportunities`);
for (const o of plan.data ?? []) console.log(o.title, '-', o.rationale);
```

### Notes for agents

- **Date ranges** default to the trailing 30 days and end **yesterday**, because
  the current day is still being written and would report a partial count. Pass
  `startDate` and `endDate` (both `YYYY-MM-DD`) to override, or `days` for a
  trailing window.
- **Time series** return `engines: [{ engine, clicks }]` per day rather than one
  key per engine name, so the shape stays typeable when a new engine appears.
  Pivot client-side if your chart wants columns.
- **Pagination**, where present, uses `page` and `pageSize` and returns a
  `pagination` object with `total` and `totalPages`.
- **Impressions on `/metrics/top-pages`** come from a fixed Search Console scan
  of the last 7, 30 or 90 days, so on a custom range they do not cover the same
  days as `aiClicks`. The response says which window was used in
  `impressionsWindowDays`.
- **Be polite.** These endpoints read from live analytics providers. Cache
  results for a daily sync rather than polling.

---

Generated from the xSeek v1 API definitions. HTML version: https://www.xseek.io/api-docs
timeout 12 curl -s -o /dev/null -w "cli install:%{http_code}\n" https://cli.xseek.io/install.sh; timeout 12 curl -s https://cli.xseek.io/install.sh | head -30
cli install:200
cli install:200
#!/bin/sh
set -e

# xSeek CLI installer
# Usage: curl -fsSL https://cli.xseek.io/install.sh | sh

REPO="xseekio/xseek-cli"
XSEEK_HOME="${HOME}/.xseek"
INSTALL_DIR="${XSEEK_HOME}/bin"
BINARY="xseek"

# Detect OS and architecture
detect_platform() {
  OS="$(uname -s | tr '[:upper:]' '[:lower:]')"
  ARCH="$(uname -m)"

  case "$OS" in
    linux)  OS="linux" ;;
    darwin) OS="darwin" ;;
    mingw*|msys*|cygwin*) OS="windows" ;;
    *)
      echo "Error: Unsupported OS: $OS"
      exit 1
      ;;
  esac

  case "$ARCH" in
    x86_64|amd64)  ARCH="amd64" ;;
    arm64|aarch64) ARCH="arm64" ;;
    *)
Thinking…

Now I'll build a small example in the repo. Keep it light: a Node script (no deps, uses fetch) that:

  • calls public /api/v1/robots (works without key)
  • if XSEEK_API_KEY is set, does the visibility loop: websites → share-of-voice → ai-clicks → opportunities
  • handles null/unavailable properly

Also a README with pricing notes. Let me check node version available.

I'll create /sandbox/repo/xseek-example/ with package.json, xseek.mjs, README.md, .env.example maybe. Then run the public part to verify.

Let's check node version.

node -v; python3 -V
v22.23.2
v22.23.2
Python 3.12.3
Thinking…

Node 22 has global fetch. Build the example with zero dependencies.

Files:

  • xseek-example/package.json
  • xseek-example/xseek.mjs (client + CLI commands: bots, audit, report)
  • xseek-example/README.md

Let me write the client carefully, matching documented response shapes:

  • GET /api/v1/robots?format=compact → {success, data:{agents:[{name,company,userAgent,pattern,patternFlags,description}], ...}} ; full format → data.companies map.
  • GET /api/v1/websites → data: array presumably (docs show?). Let me check the /api/v1/websites response shape and share-of-voice and opportunities shapes in api-docs.md to code accurately.
cd /tmp && awk '/^### GET \/api\/v1\/websites$/,/^### POST \/api\/v1\/websites$/' api-docs.md | head -60; echo "=== SOV ==="; awk '/metrics\/share-of-voice$/{f=1} f&&/^### GET \/api\/v1\/websites\/\{websiteId\}\/prompts$/{exit} f' api-docs.md | sed -n '1,120p'
### GET /api/v1/websites
### GET /api/v1/websites

List all websites for your organization

**Response**

```json
[
  {
    "id": "123",
    "name": "My Website",
    "url": "https://example.com",
    "companyName": "My Company Inc.",
    "competitors": [
      "competitor1.com",
      "competitor2.com"
    ],
    "robotsUrl": "https://example.com/robots.txt",
    "sitemapUrl": "https://example.com/sitemap.xml",
    "createdAt": "2024-01-01T00:00:00Z"
  }
]
```

---

### POST /api/v1/websites
=== SOV ===
### GET /api/v1/websites/{websiteId}/metrics/share-of-voice

Share of voice over time, optionally scoped to one topic or audience. The denominator is the tracked set (your brand plus its competitors, aliases included), which is the same figure the xSeek dashboard shows. Topics flagged excludeFromSov are always removed. Privilege: prompts:read

**Path parameters**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `websiteId` | string | yes | The unique identifier of the website |

**Query parameters**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `startDate` | string | no | Start date, YYYY-MM-DD. Defaults to 30 days ago |
| `endDate` | string | no | End date, YYYY-MM-DD. Defaults to yesterday, because the current day is still being written and would report a partial count |
| `days` | number | no | Trailing window shorthand, 1-365 |
| `granularity` | string | no | day (default) or week. On week, each bucket date is the Monday it belongs to, so the first bucket can start before startDate and covers only the days inside the range |
| `topicId` | string | no | Restrict to one topic. Get ids from /topics |
| `audienceId` | string | no | Restrict to one audience. Ignored when topicId is set |

**Response**

```json
{
  "success": true,
  "data": {
    "startDate": "2026-07-01",
    "endDate": "2026-07-31",
    "granularity": "day",
    "denominator": "trackedCompetitors",
    "vertical": {
      "id": "topic-uuid",
      "name": "Customer support",
      "kind": "topic"
    },
    "shareOfVoice": 0.11,
    "yourMentions": 902,
    "totalMentions": 8201,
    "timeseries": [
      {
        "date": "2026-07-01",
        "shareOfVoice": 0.11,
        "yourMentions": 29,
        "totalMentions": 264
      }
    ]
  }
}
```


## Prompts & topics

Thinking…

Note: /api/v1/websites returns a bare array (not wrapped). Good — handle both.

Now check ai-clicks and opportunities shapes.

cd /tmp && sed -n '139,190p' api-docs.md; echo "=== OPPS ==="; awk '/^### GET \/api\/v1\/websites\/\{websiteId\}\/opportunities$/{f=1} f&&/^### GET \/api\/v1\/websites\/\{websiteId\}\/articles$/{exit} f' api-docs.md | head -80
**Response**
**Response**

```json
{
  "success": true,
  "data": {
    "metric": "aiReferralClicks",
    "startDate": "2026-07-01",
    "endDate": "2026-07-31",
    "available": true,
    "unavailableReason": null,
    "totalAiClicks": 7751,
    "aiShareOfTraffic": 0.073,
    "totalSessions": 106178,
    "enginesCount": 13,
    "byEngine": [
      {
        "engine": "ChatGPT",
        "clicks": 6867,
        "share": 0.886
      },
      {
        "engine": "Gemini",
        "clicks": 1250,
        "share": 0.161
      }
    ],
    "timeseries": [
      {
        "date": "2026-07-01",
        "engines": [
          {
            "engine": "ChatGPT",
            "clicks": 210
          },
          {
            "engine": "Gemini",
            "clicks": 38
          }
        ]
      }
    ]
  }
}
```

---

### GET /api/v1/websites/{websiteId}/metrics/top-pages

Pages ranked by AI referral clicks, with Search Console impressions and the assistant sending the most traffic to each. Note that aiClicks and impressions do not cover the same days: clicks honour your date range, while impressions come from a fixed Search Console scan of the last 7, 30 or 90 days. The response says which one was used in impressionsWindowDays. A page with no Search Console row returns impressions null, not 0. Privilege: ai_visits:read

=== OPPS ===
### GET /api/v1/websites/{websiteId}/opportunities

Get content opportunities — queries where competitors are cited by AI but your site is not. Enriched with SEO data.

**Path parameters**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `websiteId` | string | yes | The unique identifier of the website |

**Query parameters**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `value` | string | no | Filter by business value: critical, high, medium, low |
| `type` | string | no | Filter by type: comparison, feature, recommendation |
| `pageSize` | number | no | Number of results per page (default 5) |

**Response**

```json
{
  "success": true,
  "opportunities": [
    {
      "query": "best crm for small business",
      "frequency": 8,
      "businessValue": "high",
      "type": "recommendation",
      "models": [
        "openai",
        "perplexity"
      ],
      "searchVolume": 2400,
      "keywordDifficulty": 45,
      "relatedKeywords": [
        {
          "keyword": "crm software comparison",
          "searchVolume": 1200
        }
      ]
    }
  ]
}
```


## Content Studio (articles)

Thinking…

Note opportunities uses opportunities key (not data). Good to know — the docs' own JS example uses plan.data ?? [] which would be wrong. I'll handle both.

Now write the example. Files in /sandbox/repo/xseek-example/:

  • package.json
  • xseek.mjs — client + CLI
  • README.md

Let me write it.

File edits

1 file

Completed
Writtenxseek-example/xseek.mjsView changes

/sandbox/repo/xseek-example/xseek.mjs

Written content · previous contents were not recorded

#!/usr/bin/env node
/**
* Minimal xSeek example — zero dependencies, hosted API only.
*
* xSeek (https://www.xseek.io) tracks whether AI assistants (ChatGPT, Perplexity,
* Gemini, Claude, AI Overview...) mention and cite your site.
*
* Commands:
* node xseek.mjs bots [company] Public endpoint, no API key needed.
* node xseek.mjs sites List websites visible to your key.
* node xseek.mjs report [days] Visibility + AI clicks + action plan.
*
* Env:
* XSEEK_API_KEY required for everything except `bots`
* XSEEK_WEBSITE optional; otherwise the first website from /websites is used
*/
const BASE = process.env.XSEEK_BASE ?? "https://www.xseek.io";
const API_KEY = process.env.XSEEK_API_KEY ?? "";
class XSeekError extends Error {
constructor(status, path, body) {
super(`${status} on ${path}: ${typeof body === "string" ? body : JSON.stringify(body)}`);
this.status = status;
this.path = path;
this.body = body;
}
}
async function request(path, { key = API_KEY } = {}) {
const res = await fetch(`${BASE}${path}`, {
headers: key ? { Authorization: `Bearer ${key}` } : {},
});
const text = await res.text();
let body;
try {
body = JSON.parse(text);
} catch {
body = text;
}
if (!res.ok) throw new XSeekError(res.status, path, body);
return body;
}
// Some endpoints wrap in { success, data }, some return a bare array, and
// /opportunities uses its own `opportunities` key. Normalize all three.
const unwrap = (json, altKey) =>
Array.isArray(json) ? json : (json?.data ?? json?.[altKey] ?? json);
/* ---------------------------------- public --------------------------------- */
/** GET /api/v1/robots — the only endpoint that needs no auth. */
async function aiBots(company) {
const q = new URLSearchParams({ format: "compact" });
if (company) q.set("company", company);
const json = await request(`/api/v1/robots?${q}`, { key: "" });
return unwrap(json);
}
/* ------------------------------- authenticated ------------------------------ */
const listWebsites = () => request("/api/v1/websites").then((j) => unwrap(j));
const shareOfVoice = (id, days) =>
request(`/api/v1/websites/${id}/metrics/share-of-voice?days=${days}`).then((j) => unwrap(j));
const aiClicks = (id, days) =>
request(`/api/v1/websites/${id}/metrics/ai-clicks?days=${days}`).then((j) => unwrap(j));
const opportunities = (id, pageSize = 10) =>
request(`/api/v1/websites/${id}/opportunities?pageSize=${pageSize}`).then((j) =>
unwrap(j, "opportunities"),
);
/* ---------------------------------- output ---------------------------------- */
const pct = (n) => (n === null || n === undefined ? "not measured" : `${(n * 100).toFixed(1)}%`);
async function cmdBots(company) {
const data = await aiBots(company);
const agents = data.agents ?? [];
console.log(
`${agents.length} AI crawlers across ${data.totalCompanies ?? "?"} companies ` +
`(updated ${data.lastUpdated ?? "n/a"})\n`,
);
for (const a of agents.slice(0, 40)) {
console.log(`${a.company.padEnd(12)} ${a.name.padEnd(20)} /${a.pattern}/${a.patternFlags ?? ""}`);
}
if (agents.length > 40) console.log(`... and ${agents.length - 40} more`);
}
async function cmdSites() {
const sites = await listWebsites();
if (!sites.length) return console.log("No websites on this organization yet.");
for (const s of sites) {
console.log(`${s.id} ${s.name} ${s.url} competitors: ${(s.competitors ?? []).join(", ") || "-"}`);
}
}
async function cmdReport(days = 30) {
const sites = await listWebsites();
if (!sites.length) return console.log("No websites on this organization yet.");
const site = sites.find((s) => s.id === process.env.XSEEK_WEBSITE) ?? sites[0];
console.log(`\n# ${site.name} (${site.url}) — last ${days} days\n`);
// 1. Share of voice: your mentions / all mentions in the tracked set.
const sov = await shareOfVoice(site.id, days);
console.log(`Share of voice : ${pct(sov.shareOfVoice)}`);
if (sov.shareOfVoice !== null && sov.shareOfVoice !== undefined) {
console.log(
` ${sov.yourMentions} of ${sov.totalMentions} mentions ` +
`(denominator: ${sov.denominator ?? "tracked set"})`,
);
}
// 2. Real visitors arriving from an AI assistant (GA4 sessions).
// `available:false` means GA4 is not connected — never read that as zero.
const clicks = await aiClicks(site.id, days);
if (!clicks.available) {
console.log(`AI clicks : unavailable — ${clicks.unavailableReason ?? "reason not given"}`);
} else {
console.log(
`AI clicks : ${clicks.totalAiClicks} (${pct(clicks.aiShareOfTraffic)} of ${clicks.totalSessions} sessions)`,
);
for (const e of (clicks.byEngine ?? []).slice(0, 6)) {
console.log(` ${String(e.engine).padEnd(14)} ${String(e.clicks).padStart(6)} ${pct(e.share)}`);
}
}
// 3. What to publish next: queries where competitors get cited and you do not.
const opps = await opportunities(site.id);
console.log(`\nContent plan (${opps.length}):`);
if (!opps.length) console.log(" nothing flagged in this window");
for (const o of opps) {
console.log(
` [${o.businessValue ?? "?"}/${o.type ?? "?"}] "${o.query}" ` +
`vol=${o.searchVolume ?? "?"} kd=${o.keywordDifficulty ?? "?"} models=${(o.models ?? []).join("+")}`,
);
}
}
/* ----------------------------------- cli ------------------------------------ */
function needsKey() {
if (API_KEY) return false;
console.error(
"XSEEK_API_KEY is not set. Create one in the xSeek dashboard (Settings → API keys)\n" +
"and export it, e.g. export XSEEK_API_KEY=xs_...\n" +
"Only `node xseek.mjs bots` works without a key.",
);
return true;
}
const [cmd = "bots", arg] = process.argv.slice(2);
const main = async () => {
try {
if (cmd === "bots") return await cmdBots(arg);
if (needsKey()) process.exitCode = 2;
else if (cmd === "sites") await cmdSites();
else if (cmd === "report") await cmdReport(Number(arg) || 30);
else console.error(`Unknown command "${cmd}". Use: bots | sites | report`);
} catch (err) {
if (err instanceof XSeekError && err.status === 401) {
console.error(`401 — key rejected or missing a privilege.\n${JSON.stringify(err.body)}`);
console.error("Grant the narrowest privileges that work: prompts:read, ai_visits:read.");
} else {
console.error(err.message);
}
process.exitCode = 1;
}
};
main();

File edits

1 file

Completed
Writtenxseek-example/package.jsonView changes

/sandbox/repo/xseek-example/package.json

Written content · previous contents were not recorded

{
"name": "xseek-example",
"version": "0.1.0",
"private": true,
"type": "module",
"description": "Minimal xSeek API example: AI visibility report in one script, no dependencies.",
"scripts": {
"bots": "node xseek.mjs bots",
"sites": "node xseek.mjs sites",
"report": "node xseek.mjs report 30"
},
"engines": {
"node": ">=18"
}
}
Thinking…

Wait — bug: if cmd is unknown and key missing, it exits 2 with the key message. Also if cmd is unknown but key set, prints unknown. Fine. But ordering: if (needsKey()) exit 2; else if (cmd === "sites") — an unknown command with no key gives key error. Acceptable but slightly off. Let me fix: check unknown command first.

Let me run the bots command to verify.

File edits

1 file

Completed
Modifiedxseek-example/xseek.mjs+6−2View changes

/sandbox/repo/xseek-example/xseek.mjs

Replacement excerpt

if (cmd === "bots") return await cmdBots(arg);
+ if (cmd !== "sites" && cmd !== "report") {
+ console.error(`Unknown command "${cmd}". Use: bots | sites | report`);
+ process.exitCode = 1;
+ return;
+ }
if (needsKey()) process.exitCode = 2;
else if (cmd === "sites") await cmdSites();
- else if (cmd === "report") await cmdReport(Number(arg) || 30);
- else console.error(`Unknown command "${cmd}". Use: bots | sites | report`);
+ else await cmdReport(Number(arg) || 30);
Thinking…

Now run the public command to verify it works, plus a syntax check of the auth paths (can't run without a key). Also verify the 401 path gracefully by running sites with a fake key.

cd /sandbox/repo/xseek-example && node --check xseek.mjs && node xseek.mjs bots anthropic; echo "exit=$?"
6 AI crawlers across ? companies (updated 2026-10-07T17:29:38.552Z)
6 AI crawlers across ? companies (updated 2026-10-07T17:29:38.552Z)

anthropic    anthropic-ai         /anthropic-ai/i
anthropic    claudebot            /ClaudeBot/i
anthropic    claude-web           /claude-web/i
anthropic    claude-user          /Claude-User/i
anthropic    claude-searchbot     /Claude-SearchBot/i
anthropic    claude-code          /claude-code\//i
exit=0
cd /sandbox/repo/xseek-example && node xseek.mjs bots | head -20; echo "---"; node xseek.mjs sites; echo "no-key exit=$?"; XSEEK_API_KEY=xs_bogus node xseek.mjs sites; echo "bogus-key exit=$?"
48 AI crawlers across ? companies (updated 2026-10-07T17:28:40.709Z)
48 AI crawlers across ? companies (updated 2026-10-07T17:28:40.709Z)

anthropic    anthropic-ai         /anthropic-ai/i
anthropic    claudebot            /ClaudeBot/i
anthropic    claude-web           /claude-web/i
anthropic    claude-user          /Claude-User/i
anthropic    claude-searchbot     /Claude-SearchBot/i
anthropic    claude-code          /claude-code\//i
perplexity   perplexitybot        /PerplexityBot/i
perplexity   perplexity-user      /Perplexity-User/i
xai          grokbot              /GrokBot(?!.*DeepSearch)/i
xai          grok-search          /xAI-Grok/i
xai          grok-deepsearch      /Grok-DeepSearch/i
openai       GPTBot               /GPTBot/i
openai       chatgpt-user         /ChatGPT-User/i
openai       oai-searchbot        /OAI-SearchBot/i
google       google-extended      /Google-Extended/i
google       Google-Agent         /Google-Agent/i
apple        applebot             /Applebot(?!-Extended)/i
apple        applebot-extended    /Applebot-Extended/i
---
XSEEK_API_KEY is not set. Create one in the xSeek dashboard (Settings → API keys)
and export it, e.g.  export XSEEK_API_KEY=xs_...
Only `node xseek.mjs bots` works without a key.
no-key exit=2
401 — key rejected or missing a privilege.
{"error":{"code":"invalid_api_key","message":"The API key is invalid, disabled, or expired.","hint":"Verify the key was copied whole, then confirm it is still enabled in Settings > API keys."},"documentation_url":"https://www.xseek.io/openapi.json"}
Grant the narrowest privileges that work: prompts:read, ai_visits:read.
bogus-key exit=1
Thinking…

Works. The compact format doesn't include totalCompanies — it returns totalAgents? Let me check: the header says "across ? companies". Let me look at compact response keys and improve. Also there's an OpenAPI spec at https://www.xseek.io/openapi.json — nice, I can mention it.

Let me check compact response top-level keys.

cd /tmp && timeout 20 curl -s "https://www.xseek.io/api/v1/robots?format=compact" | python3 -c "import json,sys; d=json.load(sys.stdin)['data']; print(list(d.keys())); print({k:v for k,v in d.items() if k!='agents'})" ; echo "=== openapi ==="; timeout 20 curl -s -o /dev/null -w "%{http_code}\n" https://www.xseek.io/openapi.json
['agents', 'totalAgents', 'lastUpdated']
['agents', 'totalAgents', 'lastUpdated']
{'totalAgents': 48, 'lastUpdated': '2026-10-07T17:28:40.709Z'}
=== openapi ===
200
Thinking…

Fix the header line to use totalAgents (compact) and count distinct companies. Also add openapi.json mention in README.

Update cmdBots header.

File edits

1 file

Completed
Modifiedxseek-example/xseek.mjs+2−1View changes

/sandbox/repo/xseek-example/xseek.mjs

Replacement excerpt

const agents = data.agents ?? [];
+ const companies = new Set(agents.map((a) => a.company));
console.log(
- `${agents.length} AI crawlers across ${data.totalCompanies ?? "?"} companies ` +
+ `${data.totalAgents ?? agents.length} AI crawlers across ${companies.size} companies ` +
`(updated ${data.lastUpdated ?? "n/a"})\n`,
);
Thinking…

Now write the README with pricing and manageability assessment, plus the blocked note.

Pricing (from xseek.io/en/pricing, USD, billed monthly, cancel anytime):

  • Starter: $249.99/mo — 50 prompts tracked, 1 website, 10 opportunities, ∞ users, basic analysis
  • Growth: $499.99/mo — 150 prompts, 3 websites, 25 opportunities, competitor analysis, action plan, Backlink Agent
  • Scale: custom — 500 prompts, 10 websites, 50 opportunities, 1:1 monthly strategist, SSO/SAML, 99.99% SLA, custom integrations
  • No free tier/self-serve trial; they push a 30-min sales call. Onboarding included.
  • Note: docs mention "from 3 tracked keywords on Starter to unlimited on Scale" which contradicts the pricing page's 50/150/500 prompts. Worth flagging as a discrepancy.

Manageability: yes — thin REST API, bearer token, scoped privileges, markdown API doc + OpenAPI spec + MCP server/CLI. Easy for me to operate. Blocked only by credentials: no self-serve signup/free tier, so I can't run authenticated calls; only the public /api/v1/robots endpoint is callable.

Let me verify the docs claim "from 3 on Starter to unlimited on Scale" — yes, from the docs text: "Tracked keywords depend on your plan — from 3 on Starter to unlimited on Scale." Good catch, flag it.

Write README.

File edits

1 file

Completed
Writtenxseek-example/README.mdView changes

/sandbox/repo/xseek-example/README.md

Written content · previous contents were not recorded

# xSeek example — AI visibility report in one script
[xSeek](https://www.xseek.io) tracks whether AI assistants (ChatGPT, Perplexity,
Gemini, Claude, Google AI Overview…) mention and cite your site, and tells you
what to publish next. This folder is a minimal, dependency-free client against
its **hosted** REST API. No local services, no build step, Node 18+.
## Run it
```bash
# Works with no credentials — the only public endpoint
node xseek.mjs bots
node xseek.mjs bots anthropic
# Needs a key (dashboard → Settings → API keys)
export XSEEK_API_KEY=xs_...
node xseek.mjs sites # websites visible to this key
node xseek.mjs report 30 # share of voice + AI clicks + content plan
```
Verified in this environment: `bots` returns live data (48 crawlers, 12
companies). `sites`/`report` return a clean 401 without a valid key — see
**Blocked** below.
## What the report does
Three calls, the loop xSeek documents at the bottom of its API reference:
1. `GET /websites/{id}/metrics/share-of-voice?days=30` — your mentions ÷ all
mentions in the tracked set (you + configured competitors).
2. `GET /websites/{id}/metrics/ai-clicks?days=30` — real visitors arriving from
an AI assistant, measured as GA4 sessions.
3. `GET /websites/{id}/opportunities?pageSize=10` — queries where competitors are
cited and you are not.
Two traps the API docs call out, handled here:
- **`null` means unmeasured, never `0`.** `ai-clicks` returns `available:false`
plus `unavailableReason` when GA4 is not connected; share of voice can be
`null`. The script prints "not measured" / "unavailable" instead of a fake zero.
- **Response shapes are inconsistent.** `/websites` returns a bare array, most
metrics wrap in `{ success, data }`, and `/opportunities` uses its own
`opportunities` key. `unwrap()` normalizes all three. (Note: the JS snippet in
xSeek's own docs reads `plan.data` for opportunities, which is empty — that
endpoint does not wrap.)
Also worth knowing: date ranges end **yesterday** by default, because today is
still being written; `/ai-visits` (AI crawlers hitting your pages) is not the
same thing as `/metrics/ai-clicks` (people arriving from an assistant).
## Pricing
From `xseek.io/en/pricing`, USD, billed monthly, cancel anytime, strategic
onboarding included on every plan:
| Plan | Price | Prompts tracked | Websites | Opportunities | Notes |
| --- | --- | --- | --- | --- | --- |
| Starter | **$249.99/mo** | 50 | 1 | 10 | Basic visibility analysis, simplified insights |
| Growth | **$499.99/mo** | 150 | 3 | 25 | Competitor analysis, action plan, Backlink Agent |
| Scale | **Custom** | 500 | 10 | 50 | 1:1 monthly strategist, SSO/SAML, 99.99% SLA, custom integrations |
Unlimited users on all plans. Same 8 engines everywhere (ChatGPT, xAI,
Perplexity, AI Overview, Gemini, Claude, DeepSeek, Copilot). No free tier and no
self-serve trial — the "Try for free" button routes to a 30-minute sales call.
Discrepancy to flag: the docs say tracked keywords run "from 3 on Starter to
unlimited on Scale", while the pricing page says 50 / 150 / 500 prompts. Worth
confirming with them before committing; prompts are the unit that drives price.
## Blocked
There is a real developer workflow (REST v1, 38 endpoints, bearer auth with
scoped privileges, `api-docs.md` written for agents, an OpenAPI spec at
`/openapi.json`, plus an MCP server and `xseek` CLI). But it is gated:
- API keys are created inside the dashboard, and the dashboard needs a paid plan
(min. $249.99/mo) obtained through a sales call. No sandbox, no free tier, no
trial key.
- Exactly one endpoint is public: `GET /api/v1/robots`. I verified it live.
The other tools endpoints (`/tools/robots-txt`, `/tools/llms-txt`) are
advertised on the public docs page but return 401 without a key.
So the authenticated half of this script is written to the documented shapes but
**not executed**. Set `XSEEK_API_KEY` and it runs as-is.
## Is this easy for me to manage?
Yes, once a key exists. It is a stateless JSON API over HTTPS: no infra to run,
no polling loops required (they ask for daily caching, not live polling),
privileges are granular enough to hand out a read-only key (`prompts:read`,
`ai_visits:read`), errors are explicit about the privilege they wanted, and the
whole API ships as a single markdown file plus OpenAPI — ideal for an agent to
reason over. The only friction is commercial, not technical: getting the key
means a paid plan and a sales call, and there is no staging environment to test
against before spending.
Thinking…

Verify the "12 companies" claim from my output — I said 48 crawlers, 12 companies. Let me verify with the updated script run.

cd /sandbox/repo/xseek-example && node xseek.mjs bots | head -3 && node --check xseek.mjs && ls -la && rm -f /tmp/xseek_home.html /tmp/api-docs.html /tmp/docs.html /tmp/pricing.html
48 AI crawlers across 26 companies (updated 2026-10-07T17:28:40.709Z)
48 AI crawlers across 26 companies (updated 2026-10-07T17:28:40.709Z)

anthropic    anthropic-ai         /anthropic-ai/i
total 28
drwx------ 2 root root 4096 Oct  7 17:30 .
drwxr-xr-x 4 root root 4096 Oct  7 17:29 ..
-rw------- 1 root root 4588 Oct  7 17:30 README.md
-rw------- 1 root root  363 Oct  7 17:29 package.json
-rw------- 1 root root 6684 Oct  7 17:29 xseek.mjs
Thinking…

26 companies, not 12. Fix the README.

File edits

1 file

Completed
Modifiedxseek-example/README.md+1−1View changes

/sandbox/repo/xseek-example/README.md

Replacement excerpt

-Verified in this environment: `bots` returns live data (48 crawlers, 12
+Verified in this environment: `bots` returns live data (48 crawlers, 26
companies).
Thinking…

I think I've worked through the main points and have a solid answer ready to share.

Done — small working example at /sandbox/repo/xseek-example/:

  • xseek.mjs — dependency-free Node client (Node 18+ fetch). Commands: bots (public), sites, report [days].
  • README.md — pricing table, API gotchas, blocked/manageability notes.
  • package.json — npm run bots|sites|report.

What I ran (nothing long-running, no local stacks): node xseek.mjs bots → live data, 48 AI crawlers across 26 companies. sites/report were exercised against the real API with no key and a bogus key: they return clean, actionable errors (exit 2 / 401), not crashes.

The report follows xSeek's own documented agent loop: share-of-voice → ai-clicks → opportunities, with the two traps their docs warn about handled — null/available:false printed as "not measured" instead of 0, and the inconsistent envelope shapes normalized (/websites returns a bare array, /opportunities uses an opportunities key, not data; xSeek's own JS snippet gets that one wrong).

Pricing (USD, monthly, cancel anytime, onboarding included):

PlanPricePromptsSitesOpportunities
Starter$249.99/mo50110
Growth$499.99/mo150325
ScaleCustom5001050

Unlimited users on all plans. No free tier, no trial key — "Try for free" routes to a 30-min sales call. Discrepancy worth raising with them: docs say "3 keywords on Starter → unlimited on Scale", pricing page says 50/150/500 prompts.

Easy for me to manage? Yes, technically. Stateless JSON over HTTPS, bearer auth with granular privileges (a read-only key is enough for reporting), explicit privilege-named 401s, and the whole API published as one markdown file plus /openapi.json — very agent-friendly. Friction is commercial, not technical.

Blocked (partially): there is a developer workflow, so I didn't stop — but only GET /api/v1/robots is public. Everything else needs a key minted in the dashboard, which needs a paid plan via sales call; no sandbox. The advertised public tools endpoints (/tools/robots-txt, /tools/llms-txt) return 401 too. So the authenticated half is written to the documented shapes but not executed — set XSEEK_API_KEY and it runs unchanged. I did not install their CLI/MCP server, since it also requires a key and wasn't needed for a light example.

AX Fundamentals

23 checks. Open an area for details.

This check is a quick preview. Test more tasks and models with Gauge Agents.

Test your product with Gauge Agents

AX Check by Gauge