Analytics
Read scan analytics for a single link or aggregated across your whole account. Analytics endpoints require a valid API key but no specific scope — any active key can call them.
Bot traffic is excluded by default (see exclude_bots below).
Endpoints
Per-link (:id is the link's dynamic_link_id):
GET /links/:id/analytics/general
GET /links/:id/analytics/activity
GET /links/:id/analytics/ops
GET /links/:id/analytics/country
GET /links/:id/analytics/region
GET /links/:id/analytics/browser
GET /links/:id/analytics/time
POST /links/:id/analytics/export
Account-wide (all links on your account):
GET /analytics/general
GET /analytics/activity
GET /analytics/ops
GET /analytics/country
GET /analytics/region
GET /analytics/browser
GET /analytics/qr-code
GET /analytics/time
POST /analytics/export
ops groups scans by operating system, country by country, region by city,
browser by browser, and qr-code (account-wide only) by link.
Requesting analytics for a link id that doesn't exist returns 200 with empty data,
not 404.
Query parameters
All GET endpoints accept:
| Param | Type | Default | Description |
|---|---|---|---|
duration | string | 48_hours | One of today, yesterday, 48_hours, 7_days, 30_days, 3_months, 1_year, custom. |
date_from | date | start of month | Start date (YYYY-MM-DD), used when duration is custom. |
date_to | date | today | End date (YYYY-MM-DD), used when duration is custom. |
exclude_bots | boolean | true | Exclude scans identified as bot traffic. |
limit | number | 20 | Max rows for the grouped endpoints (ops, country, region, browser, qr-code). Capped at 1000. |
curl "https://api.prolinksqr.com/links/summer-sale/analytics/country?duration=30_days&limit=10" \
-H "Authorization: Basic key-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
Response shapes
general — totals
{ "data": { "numberOfLinks": 12, "numberOfScans": 3542 } }
(For the per-link endpoint, numberOfScans is scoped to that link.)
Grouped endpoints (ops, country, region, browser, qr-code)
An array ranked by scans; percentage is a string with two decimals:
{
"data": [
{
"number": 1,
"name": "United States",
"scans": 1893,
"percentage": "53.44"
},
{ "number": 2, "name": "Germany", "scans": 771, "percentage": "21.77" }
]
}
activity — scans over time
Series grouped three ways, ready for charting (x labels, y counts):
{
"data": {
"Year": { "x": [2026], "y": [3542] },
"Month": { "x": ["May", "Jun"], "y": [1200, 2342] },
"Day": { "x": ["2026-06-23", "2026-06-24"], "y": [130, 98] }
}
}
time — day/hour heatmap
Scan counts keyed by <Day>-<hour> (hour is 0–23):
{ "data": { "Mon-9": 42, "Mon-10": 61, "Tue-14": 18 } }
Export scan logs
POST /links/:id/analytics/export
POST /analytics/export
Exports the raw scan log as a CSV file (Content-Type: text/csv, sent as an
attachment). Columns: link_id, browser_name, device_type, device_vendor,
os_name, created_at, country_name, region, city.
The export is scoped the same way as the GET endpoints above: the account-wide route
returns all of your account's links, and the per-link route returns only the specified
link's scans.
Body
| Field | Type | Required | Notes |
|---|---|---|---|
startDate | date | no | Only include scans on or after this date. |
endDate | date | no | Only include scans on or before this date. |
format | string | no | Defaults to csv (currently the only output format). |
filters | object | no | Reserved for future use; currently has no effect on the export. |
If you omit both startDate and endDate, the export defaults to the last 48 hours
(same default as the GET endpoints above). If you provide either one, the other
defaults to the start of the current month (startDate) or today (endDate).
curl -X POST https://api.prolinksqr.com/links/summer-sale/analytics/export \
-H "Authorization: Basic key-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{ "startDate": "2026-06-01", "endDate": "2026-06-30" }' \
-o export_summer-sale.csv