API reference

Access your analytics data programmatically with the Glyphex REST API.

Authentication

All API requests require a Bearer token. Create an API key in your site settings under API keys.

curl https://glyphex.io/api/v1/stats/overview?range=30d \
  -H "Authorization: Bearer glx_your_api_key_here"

Your full API key is shown only once when you create it. Store it securely.

Base URL

https://glyphex.io/api/v1

Rate limits

Rate limits are applied per API key on a sliding 1-hour window.

PlanRequests per hour
Free100
Pro1,000

Every response includes rate limit headers: X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset (Unix timestamp).

Response format

All successful responses return JSON with this structure:

{
  "data": { ... },
  "meta": {
    "site_id": "your-site-id",
    "range": "30d",
    "generated_at": "2026-02-18T12:00:00.000Z"
  }
}

Errors return a similar structure with an error object:

{
  "error": {
    "code": "unauthorized",
    "message": "Missing or invalid Authorization header. Use: Bearer glx_..."
  }
}

Query parameters

All endpoints accept these query parameters:

ParameterDefaultDescription
range30dTime range: 24h, 7d, 30d, 90d, or custom
start-Start date for custom range (ISO 8601)
end-End date for custom range (ISO 8601)
limit10Number of results (1-100). Applies to pages, referrers, devices, geo, events, utm
country-Filter by country code (e.g. US, DE)
device-Filter by device type (desktop, mobile, tablet)
browser-Filter by browser name
os-Filter by operating system
hostname-Filter by hostname
channel-Filter by traffic channel
utm_source-Filter by UTM source

Country exclusions

If you have configured excluded countries in your site settings, those exclusions are automatically applied to all API responses. You do not need to pass any additional parameters — the API uses the same exclusion list as the dashboard and email reports.

Endpoints

GET/api/v1/stats/overview

Aggregated stats for the selected period with comparison to the previous period.

Change values are percentages. A null change value means the previous period had zero.

{
  "data": {
    "current": {
      "visitors": 1240,
      "pageviews": 3891,
      "sessions": 1580,
      "bounce_rate": 42,
      "avg_duration": 127
    },
    "previous": {
      "visitors": 1100,
      "pageviews": 3200,
      "sessions": 1400,
      "bounce_rate": 45,
      "avg_duration": 115
    },
    "change": {
      "visitors": 13,
      "pageviews": 22,
      "sessions": 13,
      "bounce_rate": -7,
      "avg_duration": 10
    }
  },
  "meta": { "site_id": "...", "range": "30d", "generated_at": "..." }
}
GET/api/v1/stats/timeseries

Daily visitor and pageview counts for the selected period.

{
  "data": [
    { "date": "2026-02-01", "visitors": 42, "pageviews": 128 },
    { "date": "2026-02-02", "visitors": 38, "pageviews": 104 }
  ],
  "meta": { "site_id": "...", "range": "30d", "generated_at": "..." }
}
GET/api/v1/stats/pages

Most visited pages ranked by views.

{
  "data": [
    { "pathname": "/", "title": "Home", "views": 520, "visitors": 380 },
    { "pathname": "/pricing", "title": "Pricing", "views": 210, "visitors": 180 }
  ],
  "meta": { "site_id": "...", "range": "30d", "limit": 10, "generated_at": "..." }
}
GET/api/v1/stats/referrers

Top traffic sources by referrer domain.

{
  "data": [
    { "referrer": "google.com", "views": 320, "visitors": 280 },
    { "referrer": "twitter.com", "views": 85, "visitors": 72 }
  ],
  "meta": { "site_id": "...", "range": "30d", "limit": 10, "generated_at": "..." }
}
GET/api/v1/stats/channels

Visitor breakdown by traffic channel (direct, organic, social, referral, etc.).

{
  "data": [
    { "channel": "Organic", "visitors": 580, "percentage": 47 },
    { "channel": "Direct", "visitors": 340, "percentage": 27 },
    { "channel": "Social", "visitors": 200, "percentage": 16 }
  ],
  "meta": { "site_id": "...", "range": "30d", "generated_at": "..." }
}
GET/api/v1/stats/devices

Visitor breakdown by device type.

{
  "data": [
    { "name": "Desktop", "visitors": 820 },
    { "name": "Mobile", "visitors": 350 },
    { "name": "Tablet", "visitors": 70 }
  ],
  "meta": { "site_id": "...", "range": "30d", "limit": 10, "generated_at": "..." }
}
GET/api/v1/stats/geo

Visitor breakdown by country.

{
  "data": [
    { "name": "United States", "visitors": 480 },
    { "name": "Germany", "visitors": 220 },
    { "name": "United Kingdom", "visitors": 180 }
  ],
  "meta": { "site_id": "...", "range": "30d", "limit": 10, "generated_at": "..." }
}
GET/api/v1/stats/events

Custom event counts and unique visitors.

{
  "data": [
    { "name": "signup_click", "count": 142, "visitors": 130 },
    { "name": "download_pdf", "count": 87, "visitors": 65 }
  ],
  "meta": { "site_id": "...", "range": "30d", "limit": 10, "generated_at": "..." }
}
GET/api/v1/stats/utm

Visitor breakdown by UTM source.

{
  "data": [
    { "name": "google", "visitors": 320 },
    { "name": "newsletter", "visitors": 85 }
  ],
  "meta": { "site_id": "...", "range": "30d", "limit": 10, "generated_at": "..." }
}

Error codes

StatusCodeDescription
401unauthorizedMissing or invalid Authorization header
401invalid_keyAPI key not found or invalid format
401key_disabledAPI key has been disabled
401key_expiredAPI key has passed its expiry date
429rate_limit_exceededToo many requests. Check X-RateLimit-Reset header
500internal_errorServer error fetching data

CORS

All endpoints allow cross-origin requests. Responses include Access-Control-Allow-Origin: *. You can call the API from browser-side JavaScript, but be careful not to expose your API key in client-side code.

Example: fetch top pages from JavaScript

const response = await fetch(
  "https://glyphex.io/api/v1/stats/pages?range=7d&limit=5",
  {
    headers: {
      "Authorization": "Bearer glx_your_api_key_here"
    }
  }
);

const { data, meta } = await response.json();

// data = [{ pathname: "/", title: "Home", views: 520, visitors: 380 }, ...]

Need help?

If you have questions about the API, reach out at support@glyphex.io