Skip to content

REST API

KleoGEO data in your own tools

The same data you see in the dashboard: projects, brand mention share with a confidence interval, AI assistant answers, factual errors, sources and recommendations. Feed your BI, load data into your warehouse and start measurements from your own scripts.

Base URL

https://api.kleogeo.ru/v1

Prefer an AI agent? Connect via MCP

GET/v1/projects/{id}/metrics/visibility
{
  "analyzer_version": "0.4.0",
  "series": [
    {
      "brand_id": "0199e8a4-1f6b-7c2e-9a41-3d5b7f0c2a11",
      "brand_name": "Acme",
      "is_primary": true,
      "points": [
        {
          "t": "2026-10-06", "provider": "all",
          "n": 150, "mentioned": 63,
          "share": 0.42, "ci_low": 0.344, "ci_high": 0.5
        }
      ]
    }
  ]
}

Quick start

  1. Create a key

    Open API keys in your account and create a key with the permissions you need. The key is shown once — keep it in a secret manager, not in code.

  2. Authorize requests

    Send the key in the header of every request. Only API keys are accepted here: passwords and browser sign-in do not work.

    Authorization: Bearer geo_live_…
  3. Make the first call

    Check the key: GET /v1/me returns your organization, plan limits and the key’s permissions.

    curl https://api.kleogeo.ru/v1/me \
      -H "Authorization: Bearer $KLEOGEO_API_KEY"

Examples

List projects

GET/v1/projects

The project list is the starting point: it gives you the id for every other request. Long lists come in pages (see “Pagination”).

curl https://api.kleogeo.ru/v1/projects \
  -H "Authorization: Bearer $KLEOGEO_API_KEY"

Mention share with a confidence interval

GET/v1/projects/{id}/metrics/visibility

Share of AI answers that mention the brand, by day, week or run. Every share comes with the number of answers n and the 95% Wilson interval ci_low–ci_high.

curl "https://api.kleogeo.ru/v1/projects/$PROJECT_ID/metrics/visibility?granularity=week&from=2026-09-01" \
  -H "Authorization: Bearer $KLEOGEO_API_KEY"
Response
{
  "analyzer_version": "0.4.0",
  "series": [
    {
      "brand_id": "0199e8a4-1f6b-7c2e-9a41-3d5b7f0c2a11",
      "brand_name": "Acme",
      "is_primary": true,
      "points": [
        {
          "t": "2026-10-06", "provider": "all",
          "n": 150, "mentioned": 63,
          "share": 0.42, "ci_low": 0.344, "ci_high": 0.5
        }
      ]
    }
  ]
}

Show the interval next to the number: with few answers the share moves a lot, and a difference of a couple of points can be noise. provider: "all" is the total across assistants; the other points are per assistant.

Export to CSV

GET/v1/projects/{id}/exports/{dataset}.csv

Raw data in CSV or Parquet for your own warehouse. Datasets: visibility_daily, mentions, citations, fact_errors, measurements. The file is streamed — write it to disk in chunks instead of holding it in memory.

curl -fSL -o mentions.csv \
  "https://api.kleogeo.ru/v1/projects/$PROJECT_ID/exports/mentions.csv?from=2026-09-01" \
  -H "Authorization: Bearer $KLEOGEO_API_KEY"

Needs the “Exports” permission. At most two exports run at once per organization; the Start and trial plans get CSV for the last 90 days.

Start a measurement

POST/v1/projects/{id}/runs

Starts a new measurement over all active questions of the project. Needs the “Actions” permission (actions:write); the measurement uses AI answers from your plan. The Idempotency-Key header protects against starting twice when a request is retried.

curl -X POST "https://api.kleogeo.ru/v1/projects/$PROJECT_ID/runs" \
  -H "Authorization: Bearer $KLEOGEO_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)"

# then check the status
curl "https://api.kleogeo.ru/v1/runs/$RUN_ID" \
  -H "Authorization: Bearer $KLEOGEO_API_KEY"

While a measurement is running, a second start for the same project returns 409 run_already_active. Poll GET /v1/runs/{id} every 5–10 seconds at most; final statuses are succeeded, partial and failed.

Permissions

A key sees only its own organization’s data and only what its permissions allow. Grant the minimum you need and use a separate key per integration.

PermissionWhat it opens
projects:readProjects, brands, questions, runs and their status
metrics:readVisibility metrics, positions, sentiment, sources, factual errors, recommendations, alerts, site audit
evidence:readAI assistant answers behind the numbers and full-text search over them
exports:readCSV and Parquet exports (answer text in an export also needs evidence:read)
actions:writeStart measurements and site audits, add questions, mark recommendations and alerts

GET /v1/me works with any valid key. A missing permission returns 403 insufficient_scope.

Limits and retries

  • 10 requests per second per key (short bursts up to 20) and a shared limit of 20 per second per organization.
  • Every response shows the key’s limit: RateLimit-Policy: "api-key";q=20;w=2 and RateLimit: "api-key";r=17;t=1 — requests left right now (r) and seconds until the limit is fully restored (t).
  • Above the limit you get 429 rate_limited with a Retry-After header (seconds). Wait that long and retry.
  • 503 server_busy and 503 upstream_timeout carry Retry-After too: GET requests are safe to retry, POST requests with the same Idempotency-Key.
  • Request bodies are limited to 1 MB. Skip downloading unchanged GET responses: send If-None-Match with the ETag value and get 304.

Errors

Every error has the same shape. Rely on code — it never changes; message is an English explanation for your logs. Some errors add details such as limit and current.

{
  "error": {
    "code": "rate_limited",
    "message": "too many requests, slow down"
  }
}
StatusCodeWhen it happens
400validation_error

Invalid parameter or request body

Invalid parameter or request body
401unauthorized

No key, or the key is wrong, revoked or expired

No key, or the key is wrong, revoked or expired
402plan_limit_exceededsubscription_inactive

The action exceeds your plan, or the subscription is not active

The action exceeds your plan, or the subscription is not active
403insufficient_scopeemail_not_verified

The key lacks the permission; the key creator’s e-mail is not confirmed

The key lacks the permission; the key creator’s e-mail is not confirmed
404not_found

The object does not exist, belongs to another organization, or there is no such endpoint

The object does not exist, belongs to another organization, or there is no such endpoint
409run_already_activeidempotency_in_progress

A measurement of the project is already running; the first request with this Idempotency-Key is still in progress

A measurement of the project is already running; the first request with this Idempotency-Key is still in progress
413payload_too_large

The request body is larger than 1 MB

The request body is larger than 1 MB
422idempotency_key_reusedinvalid_region

The same Idempotency-Key with a different request; unknown region code

The same Idempotency-Key with a different request; unknown region code
428consent_required_update

The key creator must accept the updated terms in the dashboard

The key creator must accept the updated terms in the dashboard
429rate_limitedtoo_many_attemptstoo_many_active_runs

Too many requests or concurrent measurements — wait for Retry-After

Too many requests or concurrent measurements — wait for Retry-After
503server_busyupstream_timeout

Temporary overload — retry after Retry-After

Temporary overload — retry after Retry-After

Conventions

Pagination

Lists come in pages: ?limit= from 1 to 200 (default 50). The response is {"items": [...], "next_cursor": "…"}.

For the next page repeat the request with &cursor=<next_cursor>. next_cursor: null means the last page. Treat the cursor as opaque.

Safe retries

Add an Idempotency-Key header to POST and PATCH — a random UUID per action. Repeating the same request within 24 hours returns the stored successful response (with Idempotent-Replayed: true) and does not perform the action again; errors are not stored, so a retry after an error runs the request again.

Versions

The version is in the path: /v1. It only gets compatible changes: new endpoints, optional parameters, response fields, enum values and error codes. Ignore fields you do not know.

Breaking changes ship only in /v2; /v1 keeps working for at least 12 months after that, and deprecated endpoints announce it in advance with Deprecation and Sunset headers.

Evidence behind every number

Every number can be checked: measurement_id in factual errors, measurements, search and exports leads to GET /v1/measurements/{id} — the assistant’s original answer and its analysis.

API reference

Every endpoint with parameters, response schemas and examples. The OpenAPI 3.1 spec works for client generation and import into Postman or Insomnia.

Download OpenAPI
Loading the reference…