geondex
Docs

check_visibility

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

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

A bare agent can ask Perplexity, ChatGPT, Claude and Gemini itself, but it would have to reconcile four different citation formats by hand and has no memory between calls. This tool returns one normalized answer across all four — cited yes/no, your position, and who is cited instead — plus a stored delta against the last identical check. Costs 3 credits per engine that answers, so 12 for all four (timeouts are free). Takes up to 25 s. 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")[] · optional — Subset of engines. Default: all four. 3 credits per engine that answers. 1–4 items. Each one of perplexity, openai, claude, gemini

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"}'

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"
  • engines[].status · "ok" | "timeout" | "error"
  • 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
  • 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"
  • delta.perEngine[].citedBefore · boolean | null
  • delta.perEngine[].citedNow · boolean
  • delta.perEngine[].positionBefore · number | null
  • delta.perEngine[].positionNow · number | null

Example response

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

{
  "summary": "ttsensei.com cited by 2 of 4 engines that answered (perplexity #2, openai #3). Not cited by claude, gemini. Since 7 days ago: openai #5 → #3; claude dropped you.",
  "data": {
    "domain": "ttsensei.com",
    "prompt": "best table tennis blade for beginners",
    "batchId": "5f0c9e2a-8d4b-4c1e-9a7f-2b6d3e8c1f40",
    "checkedAt": 1790258712000,
    "engines": [
      {
        "engine": "perplexity",
        "status": "ok",
        "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": 6100,
        "durationMs": 7420
      },
      {
        "engine": "openai",
        "status": "ok",
        "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": 11800,
        "durationMs": 12950
      },
      {
        "engine": "claude",
        "status": "ok",
        "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": 14300,
        "durationMs": 15210
      },
      {
        "engine": "gemini",
        "status": "ok",
        "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": 3900,
        "durationMs": 6880
      }
    ],
    "citedInstead": [
      {
        "host": "www.tabletennisdaily.com",
        "engines": [
          "perplexity",
          "openai",
          "gemini"
        ]
      },
      {
        "host": "www.megaspin.net",
        "engines": [
          "openai",
          "claude"
        ]
      }
    ],
    "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
        }
      ]
    }
  },
  "credits": {
    "charged": 12,
    "remaining": 188
  }
}

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