Data Export API - CiteMetrix

Data Export API

Pull your CiteMetrix data - citations, ModelScore trends, competitors, hallucinations, and more - into Looker Studio, Tableau, or any BI tool via a read-only REST API.

A read-only REST interface for pulling your account’s AI-visibility data — citations, ModelScore™ trends, per-platform breakdowns, competitors, hallucinations, and annotations — into Looker Studio, Tableau, a data warehouse, or any tool that speaks HTTP. Every response is available as JSON or CSV.

Before you begin

Create an API key

  1. Sign in to your CiteMetrix dashboard.
  2. Open the account menu (top right) and choose Data Export API.
  3. Enter a label describing where the key will be used (e.g. “Looker Studio”) and click Create key.
  4. Copy the key immediately — for security it is shown only once. It looks like cmx_live_…. Store it in your secrets manager.
  5. To retire a key, click Revoke. Revocation takes effect immediately; any integration using that key stops working.

One key per integration. Create a separate key for each tool and label it clearly, so you can revoke one integration without disrupting the others.

Authentication

Send your key as a Bearer token in the Authorization header on every request:

Authorization: Bearer cmx_live_your_key_here

A missing, malformed, or revoked token returns 401 Unauthorized. A valid key on a plan without API access returns 403 Forbidden.

Base URL

https://citemetrix.com/wp-json/citemetrix/v1/export/

All endpoints below are relative to this base. Every request is GET over HTTPS.

Common request parameters

Every data endpoint accepts the same pagination, filtering, and format controls.

Parameter Type Description
page integer 1-based page number. Default 1.
per_page integer Rows per page. Default 100, maximum 1000.
domain integer Restrict to one of your domain IDs (see /export/whoami). A domain not in your account returns 403 domain_out_of_scope. Omit to include all your domains.
from, to date YYYY-MM-DD range on each endpoint’s primary date column. to is inclusive to end-of-day.
format string json (default) or csv.

Response format

JSON responses use a consistent envelope:

{
  "data": [ { …row objects… } ],
  "meta": { "page": 1, "per_page": 100, "total": 9273, "total_pages": 93 }
}

These headers accompany every list response, so a connector can paginate without parsing the body:

Header Meaning
X-Total-Count Total matching rows across all pages.
X-Page Current page.
X-Per-Page Rows per page.

CSV (?format=csv) returns the current page as a downloadable text/csv file with a header row; X-Total-Count is still sent so you can loop through pages. JSON object columns (in /export/scores) are emitted as embedded JSON strings in CSV.

Rate limits

Each key may make up to 120 requests per minute. Exceeding this returns 429 Too Many Requests — wait a few seconds and retry. For large extracts, page through with per_page=1000 rather than issuing many small requests.

Endpoints

GET/export/whoami

Returns the account the key belongs to and the domain IDs it can access. Call this first to discover your domain IDs for the domain filter.

curl -H "Authorization: Bearer cmx_live_…" \
  https://citemetrix.com/wp-json/citemetrix/v1/export/whoami

{
  "api_version": "v1",
  "account": { "user_id": 42, "email": "you@example.com", "tier": "agency" },
  "domains": { "count": 3, "ids": [15, 22, 27] }
}

GET/export/citations

The citation fact table: one row per (query × AI platform) result. Date filter applies to checked_at. Extra filters: platform, is_cited (0/1).

Columns: id, domain_id, keyword_id, platform, query_text, is_cited, is_recommended, is_compared, is_only_option, citation_url, citation_type, has_link, position_in_response, total_sources, mention_count, sentiment, sentiment_score, intent_category, business_driver, brand_position, total_brands_mentioned, checked_at.

GET /export/citations?domain=15&platform=chatgpt&is_cited=1&from=2026-05-01&to=2026-05-31&per_page=1000

GET/export/scores

Daily ModelScore™ and sub-scores per domain. Date filter applies to score_date.

Columns: id, domain_id, score_date, model_score, citation_score, brand_demand_score, authority_score, technical_score, total_citations, total_queries, citation_rate, plus JSON objects platform_breakdown, sentiment_breakdown, gsc_data, ga4_data, and created_at. The four breakdown fields are nested objects in JSON, JSON strings in CSV.

GET/export/platforms

Per-platform breakdown, aggregated across your citations by domain and platform. Date filter applies to checked_at. Extra filter: platform.

Columns: domain_id, platform, total_queries, total_citations, citation_rate (percent), recommended, avg_sentiment_score.

GET/export/competitors

Competitors you track per domain. Extra filter: status (active, paused, deleted).

Columns: id, domain_id, competitor_domain, competitor_name, status, created_at, updated_at.

GET/export/hallucinations

Detected AI hallucinations about your brand. Date filter applies to detected_at. Extra filters: platform, severity (minor, moderate, critical), status, hallucination_type.

Columns: id, domain_id, citation_id, fact_id, platform, severity, hallucination_type, status, claim_text, fact_text, ai_explanation, query_text, remediation_actions, cluster_id, cluster_label, reviewed_at, detected_at, created_at.

GET/export/annotations

Timeline annotations your team has added. Date filter applies to annotation_date. Extra filter: annotation_type (content_update, competitor, algorithm, campaign, other).

Columns: id, domain_id, user_id, annotation_date, note, annotation_type, created_at.

Platform slugs

The platform field and filter use these lowercase slugs:

chatgpt   gemini   perplexity   claude   copilot   grok   google_aio   mistral   deepseek

Error responses

HTTP code Meaning
401 missing_token / bad_token / invalid_token No, malformed, or revoked key.
403 api_not_entitled Valid key, but the plan doesn’t include API access.
403 domain_out_of_scope The requested domain is not in your account.
429 rate_limited More than 120 requests in a minute.

Errors use the standard WordPress REST shape: { "code": "…", "message": "…", "data": { "status": 403 } }.

Connect your BI tool

Looker Studio

Use a JSON/REST community connector. Set the request URL to an endpoint such as …/export/citations?per_page=1000, add the request header Authorization: Bearer cmx_live_…, and point the connector at the data array. Paginate by incrementing page until page > total_pages.

Tableau (Web Data Connector)

Point a Web Data Connector at the endpoint, add the Authorization: Bearer header, and map the JSON data array to your table schema using the column lists above. Drive pagination from X-Total-Count / meta.total_pages in the connector’s getData loop.

Google Sheets (Apps Script)

Because IMPORTDATA can’t send headers, use Apps Script’s UrlFetchApp:

function loadCitations() {
  var res = UrlFetchApp.fetch(
    'https://citemetrix.com/wp-json/citemetrix/v1/export/citations?format=csv&per_page=1000',
    { headers: { Authorization: 'Bearer cmx_live_…' } });
  var rows = Utilities.parseCsv(res.getContentText());
  SpreadsheetApp.getActiveSheet()
    .getRange(1, 1, rows.length, rows[0].length).setValues(rows);
}

Python

import requests

BASE = "https://citemetrix.com/wp-json/citemetrix/v1/export"
HEADERS = {"Authorization": "Bearer cmx_live_…"}

def fetch_all(endpoint, **params):
    params.setdefault("per_page", 1000)
    page, rows = 1, []
    while True:
        params["page"] = page
        r = requests.get(f"{BASE}/{endpoint}", headers=HEADERS,
                         params=params, timeout=60)
        r.raise_for_status()
        body = r.json()
        rows += body["data"]
        if page >= body["meta"]["total_pages"]:
            break
        page += 1
    return rows

citations = fetch_all("citations", domain=15, is_cited=1)
print(len(citations), "rows")

Good practices