REST API

Search Console

Read organic Google Search keyword stats — clicks (as visitors), impressions, CTR, average position, and estimated revenue — for a site's connected Google Search Console property. A site is addressed by {siteKey} (UUID or domain). Requires Authorization: Bearer {token}. See Conventions for the base URL, headers, date-range, and filter conventions shared by every endpoint.

There is no API endpoint to connect Search Console — that OAuth flow is web-only (the team connects a property from the dashboard). This endpoint only reads keyword stats for a property that is already connected.

Search keywords

GET /api/sites/{siteKey}/stats/search-keywords

Route name: api.sites.stats.search-keywords.

Path parameters

Parameter Type Required Description
siteKey string Yes Site UUID or domain.

Query parameters

Parameter Type Required Description
range string No Preset date range (see Date ranges). Default today.
from string No Custom range start, Y-m-d. Requires to.
to string No Custom range end, Y-m-d. Requires from.
limit int No Rows per Search Console fetch, 1–500. Default 10.
page int No Zero-based page offset into the Search Console result set, 0–100. Default 0.
search string No Case-insensitive substring match against the keyword label, applied after the fetch. Max 255 chars.

Plus the shared dashboard filters as query parameters — see Filters.

Response — a flat object:

Field Type Description
rows array Keyword rows (see below). Empty when the site has no data or is not connected.
error string Present only when rows is empty for a reason other than "no data" — see below.

Each row in rows:

Field Type Description
label string The search query/keyword.
visitors int Clicks from this keyword (Search Console's clicks metric).
impressions int Impressions.
ctr float Click-through rate, as a percentage (e.g. 4.2 for 4.2%).
position float Average result position.
revenue int Estimated revenue attributed to the keyword, in minor units (cents), derived from the site's organic-Google revenue per visitor.

Status: 200 OKalways, even when Search Console is not connected. This endpoint never returns a 500 for a disconnected or misconfigured property; it returns the clean shape below instead.

error value Meaning
not_connected The site has no Google Search Console connection.
property_not_configured The connection exists but no property has been selected.
period_too_recent Search Console returned no rows and the range starts within the last 72 hours (GSC data lags).
(client/auth error message) The Search Console API call failed (token refresh or transport error) — the raw error message is surfaced, rows stays [].

Rate limit — this endpoint has its own throttle bucket, throttle:60,1,search-keywords (60 requests/minute, isolated from the general 60,1 bucket shared by the rest of the authenticated API), so Search Console reads and Google's own API quota can't be starved by other API traffic.

curl "https://clickbase.so/api/sites/example.com/stats/search-keywords?range=last_30_days&limit=25" \
  -H "Authorization: Bearer {token}" \
  -H "Accept: application/json"
const params = new URLSearchParams({ range: 'last_30_days', limit: '25' });
await fetch(`https://clickbase.so/api/sites/example.com/stats/search-keywords?${params}`, { headers: { Authorization: `Bearer ${token}`, Accept: 'application/json' } })
requests.get(
    'https://clickbase.so/api/sites/example.com/stats/search-keywords',
    params={'range': 'last_30_days', 'limit': 25},
    headers={'Authorization': f'Bearer {token}', 'Accept': 'application/json'},
)
{
    "rows": [
        {
            "label": "web analytics tool",
            "visitors": 142,
            "impressions": 3210,
            "ctr": 4.4,
            "position": 8.2,
            "revenue": 4200
        }
    ]
}

Not-connected response:

{
    "rows": [],
    "error": "not_connected"
}