GET
https://jmpy.me/api/v1
/
qranalytics
/
timeline
Scans Timeline
curl --request GET \
  --url https://jmpy.me/api/v1/qranalytics/timeline \
  --header 'Authorization: Bearer <token>'
{
  "data": [
    {
      "date": "<string>",
      "scans": 123,
      "uniqueScanners": 123,
      "uniqueScans": 123
    }
  ]
}
Get scan data over time with configurable granularity. This endpoint returns time-series data showing scan counts, unique scanners, and unique scans for each time period.
This endpoint returns user-level aggregated timeline data across all your QR codes. For timeline data on a specific QR code, use the Complete Analytics endpoint.

Query Parameters

days
integer
default:30
Number of days to include in the timeline (1-365).
granularity
string
default:"day"
Time interval granularity for grouping data: hour, day, week.
  • hour - Best for short timeframes (1-7 days)
  • day - Best for medium timeframes (7-90 days)
  • week - Best for long timeframes (30-365 days)

Response

data
array
Array of timeline data points.

Request Examples

# Get daily timeline for last 30 days
curl -X GET "https://jmpy.me/api/v1/qranalytics/timeline?days=30&granularity=day" \
  -H "Authorization: Bearer YOUR_API_KEY"

# Get hourly data for last 7 days
curl -X GET "https://jmpy.me/api/v1/qranalytics/timeline?days=7&granularity=hour" \
  -H "Authorization: Bearer YOUR_API_KEY"

# Get weekly data for last 90 days
curl -X GET "https://jmpy.me/api/v1/qranalytics/timeline?days=90&granularity=week" \
  -H "Authorization: Bearer YOUR_API_KEY"

Response Examples

{
  "success": true,
  "data": [
    {
      "date": "2025-01-01",
      "scans": 78,
      "uniqueScanners": 65,
      "uniqueScans": 52
    },
    {
      "date": "2025-01-02",
      "scans": 92,
      "uniqueScanners": 78,
      "uniqueScans": 61
    },
    {
      "date": "2025-01-03",
      "scans": 156,
      "uniqueScanners": 120,
      "uniqueScans": 89
    }
  ]
}

Use Cases

Analyze scan patterns to identify peak usage times.
import requests
from collections import defaultdict

def analyze_scan_patterns():
    response = requests.get(
        'https://jmpy.me/api/v1/qranalytics/timeline',
        headers={'Authorization': 'Bearer YOUR_API_KEY'},
        params={'days': 30, 'granularity': 'day'}
    )
    timeline = response.json()['data']
    
    # Group by day of week
    from datetime import datetime
    day_totals = defaultdict(int)
    
    for point in timeline:
        date = datetime.strptime(point['date'], '%Y-%m-%d')
        day_name = date.strftime('%A')
        day_totals[day_name] += point['scans']
    
    # Find best day
    best_day = max(day_totals, key=day_totals.get)
    print(f"Best performing day: {best_day} ({day_totals[best_day]} total scans)")
    
    return dict(day_totals)
Compare current week performance to the previous week.
async function getWeeklyGrowth(): Promise<number> {
  const response = await fetch(
    'https://jmpy.me/api/v1/qranalytics/timeline?days=14&granularity=day',
    { headers: { 'Authorization': 'Bearer YOUR_API_KEY' } }
  );
  const { data } = await response.json();
  
  // Split into two weeks
  const thisWeek = data.slice(-7);
  const lastWeek = data.slice(0, 7);
  
  const thisWeekTotal = thisWeek.reduce((sum, d) => sum + d.scans, 0);
  const lastWeekTotal = lastWeek.reduce((sum, d) => sum + d.scans, 0);
  
  const growth = lastWeekTotal > 0 
    ? ((thisWeekTotal - lastWeekTotal) / lastWeekTotal) * 100 
    : 0;
  
  console.log(`Week-over-week growth: ${growth.toFixed(1)}%`);
  return growth;
}