curl --request GET \
--url https://jmpy.me/api/v1/qranalytics/export \
--header 'Authorization: Bearer <token>'{
"data": [
{
"scanned_at": "<string>",
"qr_name": "<string>",
"content_type": "<string>",
"device_type": "<string>",
"browser_name": "<string>",
"os_name": "<string>",
"country": "<string>",
"city": "<string>",
"is_unique": true
}
]
}Export QR analytics data as CSV or JSON
curl --request GET \
--url https://jmpy.me/api/v1/qranalytics/export \
--header 'Authorization: Bearer <token>'{
"data": [
{
"scanned_at": "<string>",
"qr_name": "<string>",
"content_type": "<string>",
"device_type": "<string>",
"browser_name": "<string>",
"os_name": "<string>",
"country": "<string>",
"city": "<string>",
"is_unique": true
}
]
}csv - Comma-separated values file (suitable for Excel, Google Sheets)json - JSON array of scan recordsformat=csv, the response is a downloadable CSV file with the following columns:
| Column | Description |
|---|---|
| Scanned At | ISO 8601 timestamp of the scan |
| QR Name | Name of the QR code |
| Content Type | Type of QR content (url, vcard, etc.) |
| Device | Device type (Mobile, Desktop, Tablet) |
| Browser | Browser name |
| OS | Operating system |
| Country | Country of origin |
| City | City of origin |
| Unique | Whether this was a unique visit (Yes/No) |
format=json, the response contains an array of scan records.
Show Scan Record Object
# Export as CSV (downloads file)
curl -X GET "https://jmpy.me/api/v1/qranalytics/export?days=30&format=csv" \
-H "Authorization: Bearer YOUR_API_KEY" \
-o qr-analytics.csv
# Export as JSON
curl -X GET "https://jmpy.me/api/v1/qranalytics/export?days=30&format=json" \
-H "Authorization: Bearer YOUR_API_KEY"
# Export last 90 days as CSV
curl -X GET "https://jmpy.me/api/v1/qranalytics/export?days=90&format=csv" \
-H "Authorization: Bearer YOUR_API_KEY" \
-o qr-analytics-90d.csv
const fetch = require('node-fetch');
const fs = require('fs');
// Export as CSV and save to file
async function exportCSV() {
const response = await fetch(
'https://jmpy.me/api/v1/qranalytics/export?days=30&format=csv',
{
headers: { 'Authorization': 'Bearer YOUR_API_KEY' }
}
);
const csvContent = await response.text();
fs.writeFileSync('qr-analytics.csv', csvContent);
console.log('Exported to qr-analytics.csv');
}
// Export as JSON
async function exportJSON() {
const response = await fetch(
'https://jmpy.me/api/v1/qranalytics/export?days=30&format=json',
{
headers: { 'Authorization': 'Bearer YOUR_API_KEY' }
}
);
const data = await response.json();
console.log(`Exported ${data.data.length} scan records`);
return data.data;
}
import axios from 'axios';
import * as fs from 'fs';
interface ScanRecord {
scanned_at: string;
qr_name: string;
content_type: string;
device_type: string;
browser_name: string;
os_name: string;
country: string;
city: string;
is_unique: boolean;
}
// Export as JSON
async function exportAnalytics(): Promise<ScanRecord[]> {
const response = await axios.get<{ success: boolean; data: ScanRecord[] }>(
'https://jmpy.me/api/v1/qranalytics/export',
{
headers: { 'Authorization': 'Bearer YOUR_API_KEY' },
params: { days: 30, format: 'json' }
}
);
console.log(`Exported ${response.data.data.length} records`);
return response.data.data;
}
// Export as CSV
async function exportCSV(): Promise<void> {
const response = await axios.get(
'https://jmpy.me/api/v1/qranalytics/export',
{
headers: { 'Authorization': 'Bearer YOUR_API_KEY' },
params: { days: 30, format: 'csv' },
responseType: 'text'
}
);
fs.writeFileSync('qr-analytics.csv', response.data);
console.log('Exported to qr-analytics.csv');
}
import requests
import pandas as pd
from io import StringIO
# Export as CSV and load into pandas
def export_to_dataframe():
response = requests.get(
'https://jmpy.me/api/v1/qranalytics/export',
headers={'Authorization': 'Bearer YOUR_API_KEY'},
params={'days': 30, 'format': 'csv'}
)
# Parse CSV directly into DataFrame
df = pd.read_csv(StringIO(response.text))
print(f"Loaded {len(df)} records")
print(df.head())
return df
# Export as JSON
def export_json():
response = requests.get(
'https://jmpy.me/api/v1/qranalytics/export',
headers={'Authorization': 'Bearer YOUR_API_KEY'},
params={'days': 30, 'format': 'json'}
)
data = response.json()['data']
print(f"Exported {len(data)} scan records")
return data
# Save CSV to file
def save_csv(filename='qr-analytics.csv'):
response = requests.get(
'https://jmpy.me/api/v1/qranalytics/export',
headers={'Authorization': 'Bearer YOUR_API_KEY'},
params={'days': 30, 'format': 'csv'}
)
with open(filename, 'w') as f:
f.write(response.text)
print(f"Saved to {filename}")
<?php
$client = new GuzzleHttp\Client();
// Export as CSV
$response = $client->request('GET', 'https://jmpy.me/api/v1/qranalytics/export', [
'headers' => [
'Authorization' => 'Bearer YOUR_API_KEY'
],
'query' => [
'days' => 30,
'format' => 'csv'
]
]);
// Save to file
file_put_contents('qr-analytics.csv', $response->getBody());
echo "Exported to qr-analytics.csv\n";
// Export as JSON
$jsonResponse = $client->request('GET', 'https://jmpy.me/api/v1/qranalytics/export', [
'headers' => [
'Authorization' => 'Bearer YOUR_API_KEY'
],
'query' => [
'days' => 30,
'format' => 'json'
]
]);
$data = json_decode($jsonResponse->getBody(), true)['data'];
echo "Exported " . count($data) . " records\n";
?>
package main
import (
"fmt"
"net/http"
"net/url"
"io"
"os"
)
func main() {
baseURL := "https://jmpy.me/api/v1/qranalytics/export"
params := url.Values{}
params.Add("days", "30")
params.Add("format", "csv")
req, _ := http.NewRequest("GET", baseURL+"?"+params.Encode(), nil)
req.Header.Add("Authorization", "Bearer YOUR_API_KEY")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
// Save to file
file, _ := os.Create("qr-analytics.csv")
defer file.Close()
io.Copy(file, resp.Body)
fmt.Println("Exported to qr-analytics.csv")
}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.URI;
import java.net.http.HttpResponse;
import java.nio.file.Files;
import java.nio.file.Path;
HttpClient client = HttpClient.newHttpClient();
// Export as CSV
String url = "https://jmpy.me/api/v1/qranalytics/export?days=30&format=csv";
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer YOUR_API_KEY")
.GET()
.build();
HttpResponse<String> response = client.send(request,
HttpResponse.BodyHandlers.ofString());
// Save to file
Files.writeString(Path.of("qr-analytics.csv"), response.body());
System.out.println("Exported to qr-analytics.csv");
Scanned At,QR Name,Content Type,Device,Browser,OS,Country,City,Unique
2025-01-07T15:30:00Z,Product Launch,url,Mobile,Safari,iOS,United States,New York,Yes
2025-01-07T15:28:00Z,Store Display,url,Mobile,Chrome,Android,Germany,Berlin,No
2025-01-07T15:25:00Z,Business Card,vcard,Desktop,Chrome,Windows,United Kingdom,London,Yes
2025-01-07T15:20:00Z,Product Launch,url,Tablet,Safari,iOS,Canada,Toronto,Yes
{
"success": true,
"data": [
{
"scanned_at": "2025-01-07T15:30:00Z",
"qr_name": "Product Launch",
"content_type": "url",
"device_type": "Mobile",
"browser_name": "Safari",
"os_name": "iOS",
"country": "United States",
"city": "New York",
"is_unique": true
},
{
"scanned_at": "2025-01-07T15:28:00Z",
"qr_name": "Store Display",
"content_type": "url",
"device_type": "Mobile",
"browser_name": "Chrome",
"os_name": "Android",
"country": "Germany",
"city": "Berlin",
"is_unique": false
}
]
}
{
"success": false,
"error": {
"code": "UNAUTHORIZED",
"message": "User authentication required"
}
}
Create Excel reports
import requests
import pandas as pd
from io import StringIO
def create_excel_report():
# Fetch CSV data
response = requests.get(
'https://jmpy.me/api/v1/qranalytics/export',
headers={'Authorization': 'Bearer YOUR_API_KEY'},
params={'days': 30, 'format': 'csv'}
)
df = pd.read_csv(StringIO(response.text))
# Create Excel with multiple sheets
with pd.ExcelWriter('qr-report.xlsx', engine='openpyxl') as writer:
# Raw data
df.to_excel(writer, sheet_name='Raw Data', index=False)
# Summary by QR code
summary = df.groupby('QR Name').agg({
'Scanned At': 'count',
'Unique': lambda x: (x == 'Yes').sum()
}).rename(columns={
'Scanned At': 'Total Scans',
'Unique': 'Unique Scans'
})
summary.to_excel(writer, sheet_name='By QR Code')
# Summary by country
by_country = df.groupby('Country').size().reset_index(name='Scans')
by_country.to_excel(writer, sheet_name='By Country', index=False)
print("Created qr-report.xlsx")
Automated backup
const fetch = require('node-fetch');
const fs = require('fs');
const path = require('path');
async function backupAnalytics() {
const date = new Date().toISOString().split('T')[0];
const filename = `qr-analytics-backup-${date}.json`;
const response = await fetch(
'https://jmpy.me/api/v1/qranalytics/export?days=1&format=json',
{ headers: { 'Authorization': 'Bearer YOUR_API_KEY' } }
);
const data = await response.json();
// Save to backup directory
const backupDir = './backups';
if (!fs.existsSync(backupDir)) {
fs.mkdirSync(backupDir, { recursive: true });
}
fs.writeFileSync(
path.join(backupDir, filename),
JSON.stringify(data.data, null, 2)
);
console.log(`Backed up ${data.data.length} records to ${filename}`);
}
// Run daily with cron or scheduler
backupAnalytics();
Upload to Google Sheets
import { google } from 'googleapis';
async function exportToGoogleSheets(spreadsheetId: string) {
// Get CSV data
const response = await fetch(
'https://jmpy.me/api/v1/qranalytics/export?days=30&format=json',
{ headers: { 'Authorization': 'Bearer YOUR_API_KEY' } }
);
const { data } = await response.json();
// Prepare data for Sheets
const headers = [
'Scanned At', 'QR Name', 'Content Type', 'Device',
'Browser', 'OS', 'Country', 'City', 'Unique'
];
const rows = data.map(record => [
record.scanned_at,
record.qr_name,
record.content_type,
record.device_type,
record.browser_name,
record.os_name,
record.country,
record.city,
record.is_unique ? 'Yes' : 'No'
]);
// Upload to Google Sheets
const sheets = google.sheets({ version: 'v4' });
await sheets.spreadsheets.values.update({
spreadsheetId,
range: 'QR Analytics!A1',
valueInputOption: 'RAW',
requestBody: {
values: [headers, ...rows]
}
});
console.log(`Uploaded ${rows.length} rows to Google Sheets`);
}