GET
https://jmpy.me/api/v1
/
analytics
/
timeline
Clicks Timeline
curl --request GET \
  --url https://jmpy.me/api/v1/analytics/timeline \
  --header 'Authorization: Bearer <token>'
{
  "data": [
    {
      "date": "<string>",
      "clicks": 123,
      "unique_visitors": 123
    }
  ]
}
Get click data over time with customizable date ranges and granularity. Perfect for building charts and tracking trends.

Query Parameters

days
integer
default:30
Number of days to include in the timeline (1-365).
granularity
string
default:"day"
Time interval for data aggregation: hour or day.

Response

data
array
Array of time-series data points.

Request Examples

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

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

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

Response Examples

{
  "success": true,
  "data": [
    {
      "date": "2024-01-01T00:00:00.000Z",
      "clicks": 234,
      "unique_visitors": 198
    },
    {
      "date": "2024-01-02T00:00:00.000Z",
      "clicks": 289,
      "unique_visitors": 245
    },
    {
      "date": "2024-01-03T00:00:00.000Z",
      "clicks": 312,
      "unique_visitors": 267
    },
    {
      "date": "2024-01-04T00:00:00.000Z",
      "clicks": 198,
      "unique_visitors": 176
    },
    {
      "date": "2024-01-05T00:00:00.000Z",
      "clicks": 156,
      "unique_visitors": 134
    }
  ]
}

Use Cases

Create a line chart showing click trends over time.
// Using Chart.js
async function renderClicksChart(canvasId) {
  const response = await fetch(
    'https://jmpy.me/api/v1/analytics/timeline?days=30&granularity=day',
    { headers: { 'Authorization': 'Bearer YOUR_API_KEY' } }
  );
  const { data } = await response.json();
  
  const ctx = document.getElementById(canvasId).getContext('2d');
  new Chart(ctx, {
    type: 'line',
    data: {
      labels: data.map(d => new Date(d.date).toLocaleDateString()),
      datasets: [
        {
          label: 'Clicks',
          data: data.map(d => d.clicks),
          borderColor: '#3b82f6',
          tension: 0.4
        },
        {
          label: 'Unique Visitors',
          data: data.map(d => d.unique_visitors),
          borderColor: '#10b981',
          tension: 0.4
        }
      ]
    },
    options: {
      responsive: true,
      plugins: {
        title: { display: true, text: 'Clicks Over Time' }
      }
    }
  });
}
Calculate week-over-week or month-over-month growth.
import requests
from datetime import datetime, timedelta

def calculate_growth():
    response = requests.get(
        'https://jmpy.me/api/v1/analytics/timeline',
        headers={'Authorization': 'Bearer YOUR_API_KEY'},
        params={'days': 14, 'granularity': 'day'}
    )
    
    timeline = response.json()['data']
    
    # Split into this week and last week
    this_week = timeline[7:]  # Last 7 days
    last_week = timeline[:7]  # Previous 7 days
    
    this_week_clicks = sum(d['clicks'] for d in this_week)
    last_week_clicks = sum(d['clicks'] for d in last_week)
    
    if last_week_clicks > 0:
        growth = ((this_week_clicks - last_week_clicks) / last_week_clicks) * 100
    else:
        growth = 100 if this_week_clicks > 0 else 0
    
    print(f"This Week: {this_week_clicks} clicks")
    print(f"Last Week: {last_week_clicks} clicks")
    print(f"Growth: {growth:+.1f}%")
    
    return growth
Find the best times to post based on click patterns.
interface HourlyPattern {
  hour: number;
  avgClicks: number;
  label: string;
}

async function findPeakHours(): Promise<HourlyPattern[]> {
  const response = await fetch(
    'https://jmpy.me/api/v1/analytics/timeline?days=7&granularity=hour',
    { headers: { 'Authorization': 'Bearer YOUR_API_KEY' } }
  );
  const { data } = await response.json();
  
  // Group by hour of day
  const hourlyData: Record<number, number[]> = {};
  
  data.forEach(point => {
    const hour = new Date(point.date).getHours();
    if (!hourlyData[hour]) hourlyData[hour] = [];
    hourlyData[hour].push(point.clicks);
  });
  
  // Calculate averages
  const patterns = Object.entries(hourlyData)
    .map(([hour, clicks]) => ({
      hour: parseInt(hour),
      avgClicks: clicks.reduce((a, b) => a + b, 0) / clicks.length,
      label: `${hour.toString().padStart(2, '0')}:00`
    }))
    .sort((a, b) => b.avgClicks - a.avgClicks);
  
  console.log('Peak Hours (by avg clicks):');
  patterns.slice(0, 5).forEach((p, i) => {
    console.log(`  ${i + 1}. ${p.label}: ${p.avgClicks.toFixed(1)} avg clicks`);
  });
  
  return patterns;
}
Identify unusual spikes or drops in traffic.
async function detectAnomalies(threshold = 2) {
  const response = await fetch(
    'https://jmpy.me/api/v1/analytics/timeline?days=30&granularity=day',
    { headers: { 'Authorization': 'Bearer YOUR_API_KEY' } }
  );
  const { data } = await response.json();
  
  // Calculate mean and standard deviation
  const clicks = data.map(d => d.clicks);
  const mean = clicks.reduce((a, b) => a + b, 0) / clicks.length;
  const variance = clicks.reduce((sum, c) => sum + Math.pow(c - mean, 2), 0) / clicks.length;
  const stdDev = Math.sqrt(variance);
  
  // Find anomalies (outside threshold * stdDev)
  const anomalies = data.filter(d => {
    const zScore = Math.abs((d.clicks - mean) / stdDev);
    return zScore > threshold;
  });
  
  console.log(`Mean: ${mean.toFixed(1)} clicks/day`);
  console.log(`Std Dev: ${stdDev.toFixed(1)}`);
  console.log(`\nAnomalies (${threshold}σ threshold):`);
  
  anomalies.forEach(a => {
    const zScore = (a.clicks - mean) / stdDev;
    const type = zScore > 0 ? '📈 Spike' : '📉 Drop';
    console.log(`  ${type}: ${a.date} - ${a.clicks} clicks (${zScore.toFixed(1)}σ)`);
  });
  
  return anomalies;
}