geondex
Documentation

check_visibility

Ask five AI engines whether your domain is cited, right now.

POST https://geondex.com/api/v1/check

A bare agent can ask Perplexity, ChatGPT, Claude, Gemini and Grok itself, but it would have to reconcile five different citation formats by hand and has no memory between calls. This tool returns one normalized answer across all five — cited yes/no, your position, and who is cited instead — plus a stored delta against the last identical check. Credits depend on the model (see models); timeouts are free. Takes up to 30 s (45 s with a premium model). Call history first if you only need past results.

Not available on every deployment: returns 404 not_found when this server is not configured for it. GET /me lists what is configured.

Request

Request body (JSON)

  • domain · string · required — Your site, e.g. ttsensei.com (no scheme). 3–253 characters
  • prompt · string · required — The question a buyer would ask an AI engine, e.g. 'best table tennis blade for beginners'. 3–300 characters
  • engines · ("perplexity" | "openai" | "claude" | "gemini" | "grok")[] · optional — Subset of engines. Default: all five. Each engine that answers costs its model's credits (see models). 1–5 items. Each one of perplexity, openai, claude, gemini, grok
  • models · object · optional — Model per engine. Default = the model the engine's free consumer app uses, or a fast model from the same provider where that one is too slow. perplexity: sonar (Perplexity default, 2 credits); openai: gpt-5.6-luna (ChatGPT Free default, 8 credits); openai: gpt-5.6-sol (ChatGPT Plus default, 64 credits); claude: claude-sonnet-5-5 (Claude Sonnet 5.5, current Sonnet, 15 credits, default); claude: claude-opus-5-5 (Claude Opus 5.5, 27 credits); gemini: gemini-3.5-flash (Gemini 3.5 Flash, low thinking, 16 credits, default); grok: grok-4.3 (Grok 4.3, fast, 16 credits, default)
  • brand · string · optional — Your brand name as people write it, e.g. TTSensei. Adds mentioned yes/no per engine: an answer can name you without linking you. 1–100 characters
  • competitors · string[] · optional — Up to 10 competitor names or domains. Adds whether each is mentioned or cited, plus share of voice. At most 10 items

Example request

curl -s https://geondex.com/api/v1/check -H "Authorization: Bearer gx_YOUR_KEY" -H "content-type: application/json" -d '{"domain":"ttsensei.com","prompt":"best table tennis blade for beginners","brand":"TTSensei","competitors":["Butterfly"]}'

Response

200 with the envelope every tool returns: a one-line summary, the full data, and credits: { charged, remaining }. On a free call charged is 0 and remaining is null.

Fields of data

  • domain · string
  • prompt · string
  • batchId · string
  • checkedAt · number
  • engines · object[]
  • engines[].engine · "perplexity" | "openai" | "claude" | "gemini" | "grok"
  • engines[].status · "ok" | "timeout" | "error"
  • engines[].model · string
  • engines[].cited · boolean — Whether your domain is cited in this engine's answer
  • engines[].position · number | null — 1-based rank among this engine's own citations; null when not cited
  • engines[].citations · object[]
  • engines[].citations[].url · string
  • engines[].citations[].host · string
  • engines[].citations[].title · string | null
  • engines[].citations[].position · number
  • engines[].answerExcerpt · string | null
  • engines[].costUsdMicro · number
  • engines[].durationMs · number
  • engines[].error · string · optional
  • engines[].mentioned · boolean | null · optional — Whether BRAND appears in this engine's answer text; null when no brand was given or the engine returned no text
  • engines[].competitors · object[] · optional
  • engines[].competitors[].name · string
  • engines[].competitors[].mentioned · boolean
  • engines[].competitors[].cited · boolean | null — Only for domain-like names; null for plain names
  • citedInstead · object[]
  • citedInstead[].host · string
  • citedInstead[].engines · string[]
  • delta · object — What changed since the previous identical check for this domain+prompt
  • delta.firstCheck · boolean — true when there is no earlier check to compare against
  • delta.checkedAt · number | null
  • delta.perEngine · object[]
  • delta.perEngine[].engine · "perplexity" | "openai" | "claude" | "gemini" | "grok"
  • delta.perEngine[].citedBefore · boolean | null
  • delta.perEngine[].citedNow · boolean
  • delta.perEngine[].positionBefore · number | null
  • delta.perEngine[].positionNow · number | null
  • mentions · object · optional — Present when brand or competitors was given. Share of voice counts engines that mention or cite each name.
  • mentions.brand · object | null
  • mentions.brand.name · string
  • mentions.brand.engines · ("perplexity" | "openai" | "claude" | "gemini" | "grok")[]
  • mentions.shareOfVoice · object[]
  • mentions.shareOfVoice[].name · string
  • mentions.shareOfVoice[].pct · number

Example response

Real-shaped, checked against the output schema by a test. Long lists are shortened.

{
  "summary": "ttsensei.com cited by 2 of 5 engines that answered (perplexity #2, openai #3). Not cited by claude, gemini, grok. Since 7 days ago: openai #5 → #3; claude dropped you. TTSensei mentioned or cited by 2 of 5.",
  "data": {
    "domain": "ttsensei.com",
    "prompt": "best table tennis blade for beginners",
    "batchId": "5f0c9e2a-8d4b-4c1e-9a7f-2b6d3e8c1f40",
    "checkedAt": 1790258712000,
    "engines": [
      {
        "engine": "perplexity",
        "status": "ok",
        "model": "sonar",
        "mentioned": true,
        "competitors": [
          {
            "name": "Butterfly",
            "mentioned": true,
            "cited": null
          }
        ],
        "cited": true,
        "position": 2,
        "citations": [
          {
            "url": "https://www.tabletennisdaily.com/best-beginner-blades",
            "host": "www.tabletennisdaily.com",
            "title": "Best Table Tennis Blades for Beginners",
            "position": 1
          },
          {
            "url": "https://ttsensei.com/blades/beginner",
            "host": "ttsensei.com",
            "title": "Beginner blades compared",
            "position": 2
          }
        ],
        "answerExcerpt": "For a first blade, pick an all-wood ALL or ALL+ blade. It gives more control than a carbon blade…",
        "costUsdMicro": 5400,
        "durationMs": 7420
      },
      {
        "engine": "openai",
        "status": "ok",
        "model": "gpt-5.6-luna",
        "mentioned": true,
        "competitors": [
          {
            "name": "Butterfly",
            "mentioned": true,
            "cited": null
          }
        ],
        "cited": true,
        "position": 3,
        "citations": [
          {
            "url": "https://www.tabletennisdaily.com/best-beginner-blades",
            "host": "www.tabletennisdaily.com",
            "title": "Best Table Tennis Blades for Beginners",
            "position": 1
          },
          {
            "url": "https://www.megaspin.net/blades/",
            "host": "www.megaspin.net",
            "title": "Table Tennis Blades",
            "position": 2
          },
          {
            "url": "https://ttsensei.com/blades/beginner",
            "host": "ttsensei.com",
            "title": "Beginner blades compared",
            "position": 3
          }
        ],
        "answerExcerpt": "Good beginner blades are slower and softer, so you can learn strokes…",
        "costUsdMicro": 24200,
        "durationMs": 12950
      },
      {
        "engine": "claude",
        "status": "ok",
        "model": "claude-sonnet-5-5",
        "mentioned": false,
        "competitors": [
          {
            "name": "Butterfly",
            "mentioned": true,
            "cited": null
          }
        ],
        "cited": false,
        "position": null,
        "citations": [
          {
            "url": "https://www.megaspin.net/blades/",
            "host": "www.megaspin.net",
            "title": "Table Tennis Blades",
            "position": 1
          }
        ],
        "answerExcerpt": "Most coaches suggest an all-round wooden blade for the first year…",
        "costUsdMicro": 47700,
        "durationMs": 15210
      },
      {
        "engine": "gemini",
        "status": "ok",
        "model": "gemini-3.5-flash",
        "mentioned": false,
        "competitors": [
          {
            "name": "Butterfly",
            "mentioned": false,
            "cited": null
          }
        ],
        "cited": false,
        "position": null,
        "citations": [
          {
            "url": "https://www.tabletennisdaily.com/best-beginner-blades",
            "host": "www.tabletennisdaily.com",
            "title": null,
            "position": 1
          }
        ],
        "answerExcerpt": "A beginner should start with a control-oriented blade such as…",
        "costUsdMicro": 50000,
        "durationMs": 14120
      },
      {
        "engine": "grok",
        "status": "ok",
        "model": "grok-4.3",
        "mentioned": false,
        "competitors": [
          {
            "name": "Butterfly",
            "mentioned": false,
            "cited": null
          }
        ],
        "cited": false,
        "position": null,
        "citations": [
          {
            "url": "https://revspin.net/blade/",
            "host": "revspin.net",
            "title": "Blade ratings",
            "position": 1
          }
        ],
        "answerExcerpt": "A beginner blade should prioritize control over speed…",
        "costUsdMicro": 50000,
        "durationMs": 16840
      }
    ],
    "citedInstead": [
      {
        "host": "www.tabletennisdaily.com",
        "engines": [
          "perplexity",
          "openai",
          "gemini"
        ]
      },
      {
        "host": "www.megaspin.net",
        "engines": [
          "openai",
          "claude"
        ]
      },
      {
        "host": "revspin.net",
        "engines": [
          "grok"
        ]
      }
    ],
    "mentions": {
      "brand": {
        "name": "TTSensei",
        "engines": [
          "perplexity",
          "openai"
        ]
      },
      "shareOfVoice": [
        {
          "name": "TTSensei",
          "pct": 40
        },
        {
          "name": "Butterfly",
          "pct": 60
        }
      ]
    },
    "delta": {
      "firstCheck": false,
      "checkedAt": 1789638063000,
      "perEngine": [
        {
          "engine": "perplexity",
          "citedBefore": true,
          "citedNow": true,
          "positionBefore": 2,
          "positionNow": 2
        },
        {
          "engine": "openai",
          "citedBefore": true,
          "citedNow": true,
          "positionBefore": 5,
          "positionNow": 3
        },
        {
          "engine": "claude",
          "citedBefore": true,
          "citedNow": false,
          "positionBefore": 4,
          "positionNow": null
        },
        {
          "engine": "gemini",
          "citedBefore": false,
          "citedNow": false,
          "positionBefore": null,
          "positionNow": null
        },
        {
          "engine": "grok",
          "citedBefore": null,
          "citedNow": false,
          "positionBefore": null,
          "positionNow": null
        }
      ]
    }
  },
  "credits": {
    "charged": 57,
    "remaining": 443
  }
}

Errors

Every error has the body {"error":{"code":"…","message":"…"}} and is not charged.

HTTPWhen
400Bad input
401Missing or invalid key
402Out of credits
404Tool not available on this server
429Rate limited
502Upstream failure

Every error.code and what to do about it: Errors & rate limits.

On this page