v1 API

GeoCites API

Check AI citation visibility programmatically. API scans are BYOK-only so public community traffic cannot drain the shared pool.

Quick Start

Run a BYOK scan with a single request. GeoCites requires your OpenRouter key for API scans so public traffic cannot drain the community pool.

bash
curl -X POST https://geo-cites.com/api/v1/scan \
  -H "Authorization: Bearer gc_sk_your_key" \
  -H "X-Openrouter-Key: sk-or-v1-..." \
  -H "Content-Type: application/json" \
  -d '{
    "domain": "progevita.com",
    "keyword": "longevity clinic",
    "location": "Valencia, Spain"
  }'

Response includes overall score, per-model citation data, geographic radius analysis, and competitor rankings.

X-Openrouter-Key is preferred over the legacy openRouterApiKey body field — most logging and tracing middlewares redact *-key headers by default. The body form still works but the server emits a byok.deprecated_body_key warn on each call.

Authentication

The hosted v1 API is private-access today. Scan and query endpoints require a GeoCites bearer token sent via the Authorization header.

http
Authorization: Bearer gc_sk_your_key

The current hosted deployment validates one server-configured key, not per-user keys. Contact contact@geo-cites.com if you need hosted API access. If you self-host GeoCites, set your own GEOCITES_API_KEY and keep it out of client-side code.

For BYOK scans, send your OpenRouter key in the X-Openrouter-Key header (preferred — request headers are redacted by default in most logging/tracing middleware). The legacy openRouterApiKey body field still works but the server emits a byok.deprecated_body_key warn on each call. Either way, send it only from trusted server or agent runtime — GeoCites uses it to execute the scan and does not include it in result payloads.

Responses are plain JSON. Persist them, discard them, or forward them according to your own workflow.

Endpoints

POST/api/v1/scan

Run a new AI citation scan. Returns full results synchronously (v1 -- async polling coming in v2).

Request Headers

http
Authorization: Bearer gc_sk_your_key
X-Openrouter-Key: sk-or-v1-...
Content-Type: application/json

Request Body

json
{
  "domain": "progevita.com",
  "keyword": "longevity clinic",
  "location": "Valencia, Spain",
  "tier": "byok",
  "models": ["openai-latest", "anthropic-opus-latest", "google-gemini-pro-latest"],
  "rings": [1, 2],
  "questionsPerModel": 3,
  "keywordsPerRing": 5,
  "queriesPerKeyword": 1
}

Response 200

json
{
  "scanId": "a1b2c3d4-...",
  "status": "complete",
  "cost": "$0.00 to GeoCites (OpenRouter BYOK)",
  "result": {
    "domain": "progevita.com",
    "keyword": "longevity clinic",
    "overallScore": 42,
    "models": [
      {
        "model": "openai-latest",
        "modelLabel": "OpenAI Latest",
        "cited": true,
        "score": 72,
        "prominence": "secondary"
      }
    ],
    "radius": {
      "rings": [...],
      "topCompetitors": [...]
    }
  }
}
GET/api/v1/scan/:id

Retrieve a previously completed scan by ID. Production results are served from Cloudflare KV.

Response 200

json
{
  "scanId": "a1b2c3d4-...",
  "status": "complete",
  "result": { ... }
}
Note: Local development falls back to SQLite or in-memory storage when Cloudflare KV is not bound.
GET/api/v1/models

List BYOK model aliases with resolved OpenRouter model IDs and estimated per-question costs. No authentication required.

Response 200

json
{
  "byok": [
    {
      "id": "openai-latest",
      "name": "OpenAI Latest",
      "model": "openai/gpt-5.4",
      "costPerQuery": 0.019
    },
    {
      "id": "anthropic-opus-latest",
      "name": "Claude Opus Latest",
      "model": "~anthropic/claude-opus-latest",
      "costPerQuery": 0.03
    }
  ]
}

Scan Parameters

ParameterTypeRequiredDescription
domainstringYesWebsite domain to check (e.g. progevita.com)
keywordstringYesTarget keyword or topic
locationstringNoLocation for geographic radius (e.g. Valencia, Spain)
tierbyokNoAPI scans are BYOK-only. Defaults to byok
openRouterApiKeystringNo (header preferred)Legacy OpenRouter key transport via JSON body — accepted but emits a `byok.deprecated_body_key` warn. Prefer the `X-Openrouter-Key` request header (redacted by default in most logging/tracing middleware). Send only from trusted server or agent runtime; not returned in result payloads.
modelsstring[]NoBYOK model aliases. Defaults to OpenAI, Claude Opus, and Gemini latest
questionsPerModelnumberNoCore recommendation questions per model (1-10, default: 3)
keywordsPerRingnumberNoKeywords per selected market (1-50, default: 5)
queriesPerKeywordnumberNoPrompt variations per keyword (1-10, default: 1)

Available Models

BYOK Model Aliases (resolved from OpenRouter)

OpenAI latest flagship
autoopenai-latest
Claude Opus latest
autoanthropic-opus-latest
Gemini Pro latest
autogoogle-gemini-pro-latest
Perplexity Sonar latest
autoperplexity-latest
Grok latest
autoxai-latest
GLM latest
autozai-latest

Code Examples

bash
curl -X POST https://geo-cites.com/api/v1/scan \
  -H "Authorization: Bearer gc_sk_your_key" \
  -H "X-Openrouter-Key: sk-or-v1-..." \
  -H "Content-Type: application/json" \
  -d '{
    "domain": "progevita.com",
    "keyword": "longevity clinic",
    "location": "Valencia, Spain",
    "tier": "byok",
    "models": ["openai-latest", "anthropic-opus-latest", "google-gemini-pro-latest"],
    "questionsPerModel": 3
  }'

Rate Limits

BYOK scans

60 / hour

Per API key

Burst

5 concurrent

Max parallel requests

Rate limiting is planned but not yet enforced. The limits above are targets for the v1 release.

Pricing

PlanPriceIncludes
BYOK scans$0 to GeoCitesChoose OpenRouter models, up to 15 keywords/ring, OpenRouter bills you directly

API access is BYOK-only. The web UI still has a constrained free models demo, but API traffic must use the caller's OpenRouter key. Agents can also read /llms.txt for a compact product and endpoint summary.

Error Codes

StatusMeaning
200Success
400Bad request -- missing or invalid parameters
401Unauthorized -- invalid or missing API key
404Not found -- scan ID does not exist
429Rate limited -- too many requests (planned, not yet enforced)
500Server error -- something went wrong

Questions? Need hosted API access?

Try GeoCites