# check_visibility

Source: https://geondex.com/docs/api/check-visibility

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



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

* **Cost:** 3 credits / engine
* **MCP tool:** `check_visibility`
* **Auth:** `Authorization: Bearer gx_…` (see [Authentication](/docs/authentication))
* **Try it:** [Open check\_visibility in the playground](/playground?tool=check_visibility)

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

```bash
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.

```json
{
  "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.

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

Every `error.code` and what to do about it: [Errors & rate limits](/docs/errors).
