---
title: "Test whether ChatGPT, Perplexity and Google AI Overview cite a website for one question (free tool)"
method: POST
path: "/api/v1/tools/citation-check"
tags: ["v1", "Free tools"]
---

# Test whether ChatGPT, Perplexity and Google AI Overview cite a website for one question (free tool)

`POST /api/v1/tools/citation-check`

## Request

- Base URL: `https://app.serpmantics.com` (the document declares no server; this is the origin it was published from)
- URL: `https://app.serpmantics.com/api/v1/tools/citation-check`
- Auth: one of:
  - none
  - HTTP bearer

Asks one question to three AI answer engines (ChatGPT with web search, Perplexity, Google AI
Overview) in the chosen market, and reports for each engine whether your domain is cited as a
source (`cited`, a citation on your registrable domain or one of its subdomains), whether your
brand is named in the answer (`mentioned`, which is NOT a citation), which of your pages are cited,
an excerpt of the answer, its sources, and the domains cited instead of yours.

**One answer, on one day.** This is a snapshot, not a lasting measure: AI answers change from one week
to the next, and between two calls. Run the test again to compare.

**Asynchronous, poll the result.** This call only starts the test and answers HTTP 202 with a
`checkId` and a `pollUrl`. Call `GET /api/v1/tools/citation-check?checkId=...` every 3 seconds
until `status` is `done` or `failed`; a test usually takes less than 2 minutes. MCP clients must
call the `get_citation_check` tool again until the status is terminal.

**Identical questions are reused for 24 hours.** The same question (case and spaces ignored) in
the same market, asked less than 24 hours ago, returns the engine answers already collected,
recomputed for your domain: HTTP 200 with `reused` true and `status` already `done`. Nothing is
paid for again, and your daily quota is given back.

**Domain.** Send a domain name or any URL of the site: it is reduced to its registrable domain
(`https://www.example.co.uk/blog/` becomes `example.co.uk`). IP addresses, local names and unknown
suffixes return 400 INVALID_DOMAIN.

**Tiers, per UTC day.**
- Without an API key, free anonymous tier: 1 test per day per IP address.
- Signed-in account, or API key of an account whose plan includes API access: 10 tests per day.

The API key of an account whose plan does NOT include API access does not authenticate, and the
call returns 401. Remove the `Authorization` header to use the free anonymous tier instead.

Quota headers: `X-RateLimit-Limit`, `X-RateLimit-Used`, `X-RateLimit-Remaining`,
`X-RateLimit-Reset` (Unix time of the next UTC midnight). `Retry-After` is set on 429 and 503.
A 502 or 503 answer gives the consumed quota back, and so does a 429 FREE_CAPACITY_REACHED
and a 200 reused answer; SERVICE_UNAVAILABLE consumes none.

**Request format.** Send the body as JSON with `Content-Type: application/json`: any other
content type returns 415. Without an `Authorization` header, a request sent by a web page of
another site (an `Origin` other than the SERPmantics app, or `Sec-Fetch-Site: cross-site`)
returns 403. Server-to-server calls send no `Origin` header and are not affected.

## Request body

- object
  - `domain` string, required: Domain to look for in the answers, or any URL of the site. Reduced to the registrable domain.
  - `question` string, required: The question a prospect would ask an AI assistant, 10 to 200 characters once spaces are collapsed.
  - `market` 'fr-FR' | 'en-US' | 'es-ES' | 'de-DE' | 'it-IT', required: Language and country in which the engines are asked.

## Response `200`

The same question in the same market was answered less than 24 hours ago: the answers are
reused and recomputed for your domain. Nothing was paid for again, the daily quota is given
back, and the test is already done: read it at pollUrl, no polling loop needed.

- object
  - `success` boolean
  - `data` object
    - `checkId` string
    - `status` 'done'
    - `reused` boolean
    - `pollUrl` string

## Other responses

- `202`: Test accepted. Poll pollUrl until status is done or failed.
- `400`: Invalid body, codes INVALID_BODY, INVALID_DOMAIN, INVALID_QUESTION, INVALID_MARKET, INVALID_INPUT. No quota is consumed. details.field names the faulty field; INVALID_QUESTION gives details.reason (TOO_SHORT, TOO_LONG, EMPTY, CONTROL_CHARACTERS) with details.min and details.max. INVALID_INPUT means the test service itself rejected the request, and the quota is given back.
- `401`: UNAUTHORIZED, the Authorization header does not authenticate (unknown key, or key of a plan without API access). Remove the header to use the free anonymous tier.
- `403`: CROSS_SITE_FORBIDDEN, request without an Authorization header sent by a web page of another site (Origin other than the SERPmantics app, or Sec-Fetch-Site cross-site). Refused before any quota is consumed. Server-to-server calls send no Origin header and are not affected.
- `405`: METHOD_NOT_ALLOWED
- `415`: UNSUPPORTED_MEDIA_TYPE, the body is not sent with Content-Type application/json (a charset parameter is accepted). Refused before authentication and before any quota is consumed.
- `429`: RATE_LIMITED (daily limit of your tier, see details.reset_at and details.signup_url or details.pricing_url) or FREE_CAPACITY_REACHED (shared capacity of the day used up, see details.tier and details.reset_at). There is one shared daily capacity for all anonymous visitors together and another for all accounts together, so signing in or upgrading does not lift it for an account; details.signup_url is only sent to the anonymous tier. Retry-After is set. FREE_CAPACITY_REACHED gives your quota back. RATE_LIMITED means your own quota is already spent, and the refusal itself consumes nothing more.
- `502`: UPSTREAM_ERROR, the test service did not answer. The quota is given back.
- `503`: SERVICE_BUSY, too many tests in progress: retry after Retry-After seconds, the quota is given back. SERVICE_UNAVAILABLE, the daily counter itself is unavailable: the request is refused before anything is created, no quota is consumed, and Retry-After says when to try again. Reading a test is not affected.

---

[API](https://skmtc.dev/serpmantics/apis/api-serpmantics.md) · [All operations](https://skmtc.dev/serpmantics/apis/api-serpmantics/llms.txt) · [OpenAPI document](https://skmtc.dev/serpmantics/apis/api-serpmantics/revisions/885ab1bdaa96?raw)
