Citality API

A REST API for your AI search visibility data. Read your brands, prompts, results, citations and visibility metrics, and run prompt tests programmatically. Available on the Agency plan.

All requests are made over HTTPS to:

https://citality.ai/api/v1

Responses are JSON. Successful responses wrap the payload in a data field; list responses add a pagination object. Everything is scoped to the account that owns the API key, so you never pass an account id.

Authentication

Create a key in Settings → API access. Keys look like ctl_live_… and are shown only once, so store the value securely. Pass it as a Bearer token on every request:

curl https://citality.ai/api/v1/clients \
  -H "Authorization: Bearer ctl_live_your_key_here"

Scopes

Each key carries one or both scopes:

ScopeGrants
readAll GET endpoints.
writeRunning tests (POST /tests), which debits plan checks.

Keys are revocable at any time (revocation is immediate) and stop working if the plan lapses. A missing or revoked key returns 401; a key without the required scope returns 403.

Rate limits

Requests are limited to 60 per minute per key. Every response includes standard headers so you can back off gracefully:

RateLimit-Limit: 60
RateLimit-Remaining: 58
RateLimit-Reset: 60

Exceeding the limit returns 429 with a rate_limited error.

Errors

Errors use standard HTTP status codes and a consistent JSON body:

{ "error": { "code": "not_found", "message": "Client not found." } }
StatusCodeMeaning
400invalid_requestMissing or malformed parameters.
401unauthorizedMissing, invalid or revoked key.
402insufficient_checksNot enough checks left this period.
403insufficient_scope / feature_unavailableKey lacks the scope, or plan lacks API access.
404not_foundNo such resource or endpoint.
429rate_limitedToo many requests.
502upstream_errorAll model runs failed upstream.

Pagination

List endpoints that can return many rows (currently results) accept limit (1–200, default 50) and an opaque cursor. Each response's pagination.next is the cursor for the following page, or null at the end.

curl "https://citality.ai/api/v1/clients/CLIENT_ID/results?limit=50&cursor=NEXT_CURSOR" \
  -H "Authorization: Bearer ctl_live_…"

Endpoints

GET/clients

List the brands/clients in the account.

Response

{
  "data": [
    {
      "clientId": "01KNN…",
      "name": "Acme Training Company",
      "industry": "Online Training",
      "url": "https://acmetrainingcompany.com",
      "description": "…",
      "createdAt": "2026-04-08T06:31:21.180Z"
    }
  ]
}
GET/clients/{clientId}

Retrieve a single client by id. Returns 404 if it isn't in your account.

Response

{ "data": { "clientId": "01KNN…", "name": "Acme Training Company", … } }
GET/clients/{clientId}/prompts

List the tracked prompts for a client.

Response

{
  "data": [
    { "promptId": "01KNN…", "clientId": "01KNN…",
      "prompt": "best online training courses australia",
      "intent": "Commercial", "location": "", "createdAt": "…" }
  ]
}
GET/clients/{clientId}/results

List a client's results, most recent first. Paginated.

Query parameters

ParamDescription
fromOnly results on/after this date (YYYY-MM-DD).
toOnly results on/before this date (YYYY-MM-DD).
platformChatGPT, Claude, Gemini or Perplexity.
promptIdRestrict to one prompt.
limit, cursorPagination (see above).

Response

{
  "data": [
    { "resultId": "01KNN…", "clientId": "01KNN…", "promptId": "01KNN…",
      "date": "2026-09-11", "platform": "Perplexity",
      "brandMentioned": true, "position": "Cited",
      "competitors": "Coursera, Udemy",
      "yourUrl": "https://acmetrainingcompany.com",
      "competitorUrls": "https://…, https://…",
      "confidence": null, "needsReview": false, "createdAt": "…" }
  ],
  "pagination": { "limit": 50, "cursor": null, "next": "Mg==" }
}
GET/clients/{clientId}/metrics

Visibility metrics for a client, matching the figures that power the dashboard and reports. Accepts optional from / to dates to scope the window.

Response

{
  "data": {
    "totalPrompts": 3, "brandPercentage": 100, "totalResults": 46,
    "topPlatform": "Perplexity", "topCompetitor": "Coursera",
    "byPlatform": [ { "platform": "ChatGPT", "total": 12, "mentioned": 4, "percentage": 33 } ],
    "byIntent":   [ { "intent": "Commercial", "total": 40, "mentioned": 38, "percentage": 95 } ],
    "topCompetitors": [ { "name": "Coursera", "count": 21 } ],
    "topUrls":        [ { "url": "https://…", "count": 9 } ]
  },
  "meta": { "from": null, "to": null }
}
GET/prompts/{promptId}

Retrieve a single prompt by id.

GET/results/{resultId}

Retrieve a single result by id.

POST/tests

Run a prompt against the AI models and log the results. Requires the write scope and debits plan checks (one check per model; Perplexity counts as three; the high-accuracy judge doubles the cost). Failed model runs aren't charged.

Body

FieldDescription
promptId requiredThe prompt to test.
modelsArray of model ids. Defaults to all enabled models, capped to the plan's models-per-test.
opusJudgeUse the high-accuracy judge (Growth+; doubles checks).

Request

curl -X POST https://citality.ai/api/v1/tests \
  -H "Authorization: Bearer ctl_live_…" \
  -H "Content-Type: application/json" \
  -d '{ "promptId": "01KNN…" }'

Response 201

{
  "data": {
    "testGroupId": "01M29…",
    "logged": 4,
    "billedChecks": 6,
    "results": [ { "resultId": "…", "platform": "ChatGPT", "brandMentioned": false,
                   "position": "Not Present", "confidence": 0.95, … } ],
    "notices": [],
    "errors": []
  },
  "meta": { "checksRemaining": 6959 }
}

If you're out of checks the call returns 402 insufficient_checks. If every model fails upstream it returns 502 upstream_error with details.

Objects

Client

clientId, name, industry, url, description, createdAt.

Prompt

promptId, clientId, prompt, intent (Commercial / Informational), location, createdAt.

Result

resultId, clientId, promptId, date, platform, brandMentioned (boolean), position (Cited / Mentioned / Not Present), competitors, yourUrl, competitorUrls, confidence (0–1, or null for citation/manual results), needsReview, createdAt.

Metrics

totalPrompts, brandPercentage, totalResults, topPlatform, topCompetitor, and the arrays byPlatform, byIntent, topCompetitors, topUrls.

MCP server

Citality hosts a Model Context Protocol server so AI assistants (Claude and others) can query your data and run tests directly. It uses the same API keys, and every tool is enforced server-side.

Connect by URL (recommended)

{
  "mcpServers": {
    "citality": {
      "type": "http",
      "url": "https://citality.ai/mcp",
      "headers": { "Authorization": "Bearer ctl_live_…" }
    }
  }
}

Tools

ToolScopeDescription
list_clientsreadList brands/clients.
get_clientreadGet one client.
list_promptsreadList a client's prompts.
list_resultsreadList results with filters.
get_visibilityreadVisibility metrics for a client.
run_prompt_testwriteRun a prompt and log results.
export_resultsreadExport a client's results as CSV.

OpenAPI

A machine-readable OpenAPI 3.1 description is available for client generation and tooling:

Get API access See pricing