curl --request POST \
--url https://management.scanova.io/analytics/qr/ \
--header 'Authorization: <api-key>' \
--header 'Content-Type: application/json' \
--data '
{
"q": [
"Q07afe81aa0034c01"
],
"filter_by": "qrid"
}
'import requests
url = "https://management.scanova.io/analytics/qr/"
payload = {
"q": ["Q07afe81aa0034c01"],
"filter_by": "qrid"
}
headers = {
"Authorization": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({q: ['Q07afe81aa0034c01'], filter_by: 'qrid'})
};
fetch('https://management.scanova.io/analytics/qr/', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://management.scanova.io/analytics/qr/",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'q' => [
'Q07afe81aa0034c01'
],
'filter_by' => 'qrid'
]),
CURLOPT_HTTPHEADER => [
"Authorization: <api-key>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://management.scanova.io/analytics/qr/"
payload := strings.NewReader("{\n \"q\": [\n \"Q07afe81aa0034c01\"\n ],\n \"filter_by\": \"qrid\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://management.scanova.io/analytics/qr/")
.header("Authorization", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"q\": [\n \"Q07afe81aa0034c01\"\n ],\n \"filter_by\": \"qrid\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://management.scanova.io/analytics/qr/")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"q\": [\n \"Q07afe81aa0034c01\"\n ],\n \"filter_by\": \"qrid\"\n}"
response = http.request(request)
puts response.read_body{
"qr": [],
"qr_meta": {
"docs-v2-first-qr-code": {
"qrid": "Q07afe81aa0034c01",
"category": "Website URL",
"category_slug": "url"
}
}
}QR Code Analytics
Retrieve in-depth QR Code performance analytics including scan counts, devices, operating systems, browsers, geographic insights, and time-based metrics. Supports filtering, grouping, and multiple analytic types in a single request. Authentication required.
curl --request POST \
--url https://management.scanova.io/analytics/qr/ \
--header 'Authorization: <api-key>' \
--header 'Content-Type: application/json' \
--data '
{
"q": [
"Q07afe81aa0034c01"
],
"filter_by": "qrid"
}
'import requests
url = "https://management.scanova.io/analytics/qr/"
payload = {
"q": ["Q07afe81aa0034c01"],
"filter_by": "qrid"
}
headers = {
"Authorization": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({q: ['Q07afe81aa0034c01'], filter_by: 'qrid'})
};
fetch('https://management.scanova.io/analytics/qr/', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://management.scanova.io/analytics/qr/",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'q' => [
'Q07afe81aa0034c01'
],
'filter_by' => 'qrid'
]),
CURLOPT_HTTPHEADER => [
"Authorization: <api-key>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://management.scanova.io/analytics/qr/"
payload := strings.NewReader("{\n \"q\": [\n \"Q07afe81aa0034c01\"\n ],\n \"filter_by\": \"qrid\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://management.scanova.io/analytics/qr/")
.header("Authorization", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"q\": [\n \"Q07afe81aa0034c01\"\n ],\n \"filter_by\": \"qrid\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://management.scanova.io/analytics/qr/")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"q\": [\n \"Q07afe81aa0034c01\"\n ],\n \"filter_by\": \"qrid\"\n}"
response = http.request(request)
puts response.read_body{
"qr": [],
"qr_meta": {
"docs-v2-first-qr-code": {
"qrid": "Q07afe81aa0034c01",
"category": "Website URL",
"category_slug": "url"
}
}
}Description
This endpoint provides comprehensive analytics for one or more QR codes in your account.You can query by:
- QR IDs (specific QR codes), or
- Tags (group of QR codes with the same tag).
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
type | string | No | Comma-separated list of analytics types to include in the response. Defaults to all. |
from | string (YYYY-MM-DD) | Yes | Start date for analytics data (inclusive). |
to | string (YYYY-MM-DD) | Yes | End date for analytics data (inclusive). Defaults to current date. |
exclude_bot_scan | boolean | No | When true, bot scans are excluded from all aggregations and returned separately under the bot_scans key in the response. Defaults to false. |
Supported type Values
| Type | Description |
|---|---|
count | Scan count overview (total, unique, trends) |
qr | QR code-level summary |
device | Breakdown by device type (e.g., Mobile, PC) |
os | Breakdown by operating system |
browser | Breakdown by browser type |
date | Time-series data by date |
handset | Breakdown by handset or device model |
geography | Country/region-level distribution |
geo_location | Detailed city-level location data |
day_time | Hourly and day-based scan distribution |
age | Age group data (if enabled in analytics settings) |
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
filter_by | string | Yes | Specify filter type — either qrid or tags or folder. |
q | array | Yes | List of QR IDs or tags or folder ids to filter analytics for. |
Examples
Get QR Code Analytics by QR ID
curl -X POST "https://management.scanova.io/analytics/qr/?from=2025-02-01&to=2025-02-25&type=count,device,os" \
-H "Authorization: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"filter_by": "qrid",
"q": ["Qf94b25d768294148"]
}'
Get Analytics by Tags
curl -X POST "https://management.scanova.io/analytics/qr/?from=2025-02-01&to=2025-02-25&type=count,geography" \
-H "Authorization: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"filter_by": "tags",
"q": ["marketing", "campaign"]
}'
Get Multiple QR Codes Analytics
curl -X POST "https://management.scanova.io/analytics/qr/?from=2025-01-01&to=2025-01-31&type=count,device,os,browser,date" \
-H "Authorization: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"filter_by": "qrid",
"q": ["Qf94b25d768294148", "Qf94b25d768294149", "Qf94b25d768294150"]
}'
Get All Analytics Types
curl -X POST "https://management.scanova.io/analytics/qr/?from=2025-02-01&to=2025-02-25&type=count,qr,device,os,browser,date,handset,geography,geo_location" \
-H "Authorization: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"filter_by": "qrid",
"q": ["Qf94b25d768294148"]
}'
Exclude Bot Scans
curl -X POST "https://management.scanova.io/analytics/qr/?from=2025-02-01&to=2025-02-25&type=count,device&exclude_bot_scan=true" \
-H "Authorization: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"filter_by": "qrid",
"q": ["Qf94b25d768294148"]
}'
Response Structure
Success Response (200 OK)
The response structure varies based on thetype query parameter. Response keys depend on the requested analytics types.
Complete Analytics Response (all types requested)
{
"qr": [
["QR Code", 1]
],
"count": {
"total": 1,
"elevation": {
"percent": 100,
"previous": 2,
"type": "-",
"period": {
"start": "2025-10-11T18:07:00Z",
"end": "2025-10-18T18:07:00Z"
}
},
"unique": 1,
"unique_elevation": {
"percent": 100,
"previous": 2,
"type": "-",
"period": {
"start": "2025-10-11T18:07:00Z",
"end": "2025-10-18T18:07:00Z"
}
},
"scan_qr": 0,
"scan_url": 1
},
"device": [
["PC", 1]
],
"os": [
["Mac OS X", 1]
],
"date": {
"all": [
["2025-10-18", 0],
["2025-10-19", 0],
["2025-10-20", 0],
["2025-10-21", 0],
["2025-10-22", 0],
["2025-10-23", 0],
["2025-10-24", 0],
["2025-10-25", 1],
["2025-10-26", 0]
],
"qr": [
["2025-10-18", 0],
["2025-10-19", 0],
["2025-10-20", 0],
["2025-10-21", 0],
["2025-10-22", 0],
["2025-10-23", 0],
["2025-10-24", 0],
["2025-10-25", 0],
["2025-10-26", 0]
],
"url": [
["2025-10-18", 0],
["2025-10-19", 0],
["2025-10-20", 0],
["2025-10-21", 0],
["2025-10-22", 0],
["2025-10-23", 0],
["2025-10-24", 0],
["2025-10-25", 1],
["2025-10-26", 0]
]
},
"handset": [
["Mac", 1]
],
"browser": [
["Chrome", 1]
],
"geography": [
{
"country_code": "Unknown",
"country_name": "Unknown",
"region": "Unknown",
"city": "Unknown",
"count": 1
}
],
"geo_location": [],
"age": [],
"day_time": [
["Sun", "00", 0],
["Sun", "01", 1],
["Sun", "02", 0],
["Mon", "09", 2],
["Mon", "14", 3],
["Tue", "18", 1],
["Wed", "12", 2],
["Thu", "16", 1],
["Fri", "11", 2],
["Sat", "20", 1]
]
}
Count Analytics Only
{
"count": {
"total": 1,
"elevation": {
"percent": 100,
"previous": 2,
"type": "-",
"period": {
"start": "2025-10-11T18:07:00Z",
"end": "2025-10-18T18:07:00Z"
}
},
"unique": 1,
"unique_elevation": {
"percent": 100,
"previous": 2,
"type": "-",
"period": {
"start": "2025-10-11T18:07:00Z",
"end": "2025-10-18T18:07:00Z"
}
},
"scan_qr": 0,
"scan_url": 1
}
}
Device, OS, and Browser Analytics
{
"device": [
["PC", 1]
],
"os": [
["Mac OS X", 1]
],
"browser": [
["Chrome", 1]
]
}
Analytics with Bot Scans Excluded (exclude_bot_scan=true)
When exclude_bot_scan=true is passed, all aggregations reflect human traffic only and the response includes a bot_scans summary:
{
"count": {
"total": 85,
"unique": 72
},
"device": [
["Mobile", 60],
["PC", 25]
],
"bot_scans": {
"total": 12,
"unique": 5,
"by_type": [
["Googlebot", 7],
["AhrefsBot", 5]
],
"by_qr": [
["My Campaign QR", 10],
["Landing Page QR", 2]
]
}
}
Response Schema
Each analytics type returns a separate structure.| Key | Description | Example Format |
|---|---|---|
count | Summary metrics for scans | { "total": 150, "unique": 120 } |
device | Device type counts | [["Mobile", 100], ["Desktop", 50]] |
os | Operating systems | [["Android", 80], ["iOS", 40]] |
browser | Browser breakdown | [["Chrome", 60], ["Safari", 30]] |
date | Daily scan counts | { "all": [["2025-10-25", 5], ["2025-10-26", 2]] } |
geography | Country/region breakdown | [{"country_name": "India", "count": 30}] |
geo_location | City-level data | [{"city": "Delhi", "count": 10}] |
day_time | Hourly scan distribution | [["Mon", "09", 2], ["Tue", "14", 1]] |
bot_scans | Bot scan summary — only present when exclude_bot_scan=true is requested | {"total": 12, "unique": 5, "by_type": [...], "by_qr": [...]} |
Use Cases
- 📈 Build custom QR code analytics dashboards
- 🗺️ Analyze user scan geography and device trends
- ⏰ Study time-based scan activity
- 🧭 Track campaign performance by tags or QR IDs
- 🧮 Export scan data summaries for internal BI systems
Integration Examples
JavaScript - Get QR Code Analytics
async function getQRAnalytics(filterBy, q, fromDate, toDate, types = 'count,device,os') {
try {
const response = await fetch(
`https://management.scanova.io/analytics/qr/?from=${fromDate}&to=${toDate}&type=${types}`,
{
method: 'POST',
headers: {
'Authorization': 'YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
filter_by: filterBy,
q: q
})
}
);
if (response.ok) {
const analytics = await response.json();
return analytics;
} else {
throw new Error('Failed to fetch analytics');
}
} catch (error) {
console.error('Error fetching analytics:', error);
return null;
}
}
// Usage - Get analytics by QR ID
const analytics = await getQRAnalytics('qrid', ['Qf94b25d768294148'], '2025-02-01', '2025-02-25');
console.log('Analytics data:', analytics);
// Usage - Get analytics by tags
const tagAnalytics = await getQRAnalytics('tags', ['marketing', 'campaign'], '2025-02-01', '2025-02-25', 'count,geography');
// Usage - Get multiple QR codes analytics
const multiAnalytics = await getQRAnalytics('qrid', ['Qf94b25d768294148', 'Qf94b25d768294149'], '2025-02-01', '2025-02-25', 'count,device,os,browser');
Python - Get QR Code Analytics
import requests
from datetime import datetime, timedelta
def get_qr_analytics(filter_by, q, from_date, to_date, types='count,device,os'):
url = "https://management.scanova.io/analytics/qr/"
headers = {
"Authorization": "YOUR_API_KEY",
"Content-Type": "application/json"
}
params = {
'from': from_date,
'to': to_date,
'type': types
}
data = {
'filter_by': filter_by,
'q': q
}
try:
response = requests.post(url, headers=headers, params=params, json=data)
response.raise_for_status()
return response.json()
except requests.exceptions.RequestException as e:
print(f"Error fetching analytics: {e}")
return None
def analyze_qr_performance(qr_ids, days=30, types='count,device,os,geography'):
"""Get analytics for the last N days"""
to_date = datetime.now().strftime('%Y-%m-%d')
from_date = (datetime.now() - timedelta(days=days)).strftime('%Y-%m-%d')
analytics = get_qr_analytics('qrid', qr_ids, from_date, to_date, types)
if analytics:
print(f"Analytics for QR Codes: {qr_ids}")
print(f"Date Range: {from_date} to {to_date}")
# Display analytics based on requested types
if 'count' in types:
print(f"\nScan Counts: {analytics.get('count', 'N/A')}")
if 'device' in types:
print(f"\nDevice Analytics: {analytics.get('device', 'N/A')}")
if 'geography' in types:
print(f"\nGeographic Analytics: {analytics.get('geography', 'N/A')}")
return analytics
def get_analytics_by_tags(tags, from_date, to_date, types='count,geography'):
"""Get analytics for QR codes with specific tags"""
return get_qr_analytics('tags', tags, from_date, to_date, types)
# Usage - Get analytics by QR ID
analytics = get_qr_analytics('qrid', ['Qf94b25d768294148'], '2025-02-01', '2025-02-25')
print("Analytics:", analytics)
# Usage - Get analytics by tags
tag_analytics = get_analytics_by_tags(['marketing', 'campaign'], '2025-02-01', '2025-02-25')
# Usage - Analyze performance for multiple QR codes
analyze_qr_performance(['Qf94b25d768294148', 'Qf94b25d768294149'], 30, 'count,device,os,browser,geography')
PHP - Get QR Code Analytics
<?php
function getQRAnalytics($filterBy, $q, $fromDate, $toDate, $types = 'count,device,os') {
$url = "https://management.scanova.io/analytics/qr/";
$headers = [
"Authorization: YOUR_API_KEY",
"Content-Type: application/json"
];
$params = http_build_query([
'from' => $fromDate,
'to' => $toDate,
'type' => $types
]);
$data = json_encode([
'filter_by' => $filterBy,
'q' => $q
]);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url . '?' . $params);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode === 200) {
return json_decode($response, true);
} else {
echo "Error fetching analytics: " . $response;
return null;
}
}
function analyzeQRPerformance($qrIds, $days = 30, $types = 'count,device,os,geography') {
$toDate = date('Y-m-d');
$fromDate = date('Y-m-d', strtotime("-{$days} days"));
$analytics = getQRAnalytics('qrid', $qrIds, $fromDate, $toDate, $types);
if ($analytics) {
echo "Analytics for QR Codes: " . implode(', ', $qrIds) . "\n";
echo "Date Range: {$fromDate} to {$toDate}\n";
// Display analytics based on requested types
if (strpos($types, 'count') !== false) {
echo "\nScan Counts: " . json_encode($analytics['count'] ?? 'N/A') . "\n";
}
if (strpos($types, 'device') !== false) {
echo "\nDevice Analytics: " . json_encode($analytics['device'] ?? 'N/A') . "\n";
}
if (strpos($types, 'geography') !== false) {
echo "\nGeographic Analytics: " . json_encode($analytics['geography'] ?? 'N/A') . "\n";
}
}
return $analytics;
}
function getAnalyticsByTags($tags, $fromDate, $toDate, $types = 'count,geography') {
return getQRAnalytics('tags', $tags, $fromDate, $toDate, $types);
}
// Usage - Get analytics by QR ID
$analytics = getQRAnalytics('qrid', ['Qf94b25d768294148'], '2025-02-01', '2025-02-25');
echo "Analytics: " . json_encode($analytics) . "\n";
// Usage - Get analytics by tags
$tagAnalytics = getAnalyticsByTags(['marketing', 'campaign'], '2025-02-01', '2025-02-25');
// Usage - Analyze performance for multiple QR codes
analyzeQRPerformance(['Qf94b25d768294148', 'Qf94b25d768294149'], 30, 'count,device,os,browser,geography');
?>
Authorizations
Send your Management API key as the raw value of the Authorization header — no "Bearer " or "Token " prefix, and no other characters. Example: Authorization: 401f7ac837da42b97f613d789819ff93537bee6a. A header containing more than one space-separated part is rejected outright. Requests also require the request's Host header to be the management API host (e.g. management.scanova.io) — the same key sent to the regular API host will not authenticate.
Query Parameters
Comma-separated metric types, e.g. qr.
Grouping for time-series metric types, e.g. date/week/month.
Bypasses the volume cap; used by dashboard overview widgets.
Body
Response
Analytics data, grouped by the requested type(s). A qr_meta name->{qrid, category, category_slug} map is attached whenever qr is among the requested types.
Was this page helpful?