Skip to main content
GET
/
email-meter
/
stats
/
hourly-trends
/
{startDate}
/
{endDate}
Get hourly email traffic trends
curl --request GET \
  --url http://localhost:2000/email-meter/stats/hourly-trends/{startDate}/{endDate} \
  --header 'Authorization: Bearer <token>'
{
  "message": "",
  "data": {
    "labels": [
      "00:00:00",
      "01:00:00",
      "02:00:00"
    ],
    "series": {
      "received": [
        {
          "name": "2025-10-01",
          "data": [
            0,
            1,
            3,
            2,
            5,
            10,
            6,
            8,
            3,
            1,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0
          ]
        }
      ],
      "sent": [
        {
          "name": "2025-10-01",
          "data": [
            0,
            2,
            5,
            1,
            3,
            8,
            6,
            4,
            2,
            1,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0
          ]
        }
      ]
    }
  }
}
Returns hourly email volume (received and sent) between the given start and end dates. Each day is broken down into 24 hourly buckets, showing how many emails were received and sent during each hour.

Request

Headers

NameTypeRequiredDescription
AuthorizationstringYesBearer token

Path Parameters

ParameterTypeRequiredDescription
startDatestringYesStart date for the range (YYYY-MM-DD)
endDatestringYesEnd date for the range (YYYY-MM-DD)

Parameter Format

  • Format: YYYY-MM-DD (ISO 8601 date)
  • Timezone: UTC
  • Default: Last 7 days if not provided

Response

{
  "message": "",
  "data": {
    "labels": [
      "00:00:00",
      "01:00:00",
      "02:00:00",
      "03:00:00",
      "04:00:00",
      "05:00:00",
      "06:00:00",
      "07:00:00",
      "08:00:00",
      "09:00:00",
      "10:00:00",
      "11:00:00",
      "12:00:00",
      "13:00:00",
      "14:00:00",
      "15:00:00",
      "16:00:00",
      "17:00:00",
      "18:00:00",
      "19:00:00",
      "20:00:00",
      "21:00:00",
      "22:00:00",
      "23:00:00"
    ],
    "series": {
      "received": [
        {
          "name": "2025-10-01",
          "data": [0, 1, 3, 2, 5, 10, 6, 8, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
        },
        {
          "name": "2025-10-02",
          "data": [0, 2, 5, 3, 8, 15, 12, 18, 25, 22, 19, 15, 12, 18, 20, 16, 14, 8, 5, 2, 1, 0, 0, 0]
        }
      ],
      "sent": [
        {
          "name": "2025-10-01",
          "data": [0, 0, 2, 1, 3, 8, 5, 8, 12, 15, 18, 14, 10, 8, 6, 4, 2, 1, 0, 0, 0, 0, 0, 0]
        },
        {
          "name": "2025-10-02",
          "data": [0, 1, 3, 2, 6, 8, 8, 10, 15, 20, 25, 22, 18, 15, 12, 10, 8, 5, 2, 1, 0, 0, 0, 0]
        }
      ]
    }
  }
}

401 Unauthorized

{
  "error": {
    "code": "UNAUTHORIZED",
    "message": "Missing or invalid token"
  }
}

500 Internal Server Error

{
  "error": {
    "code": "SERVER_ERROR",
    "message": "Internal server error"
  }
}

Example

curl -X GET 'http://localhost:2000/email-meter/stats/hourly-trends/2025-10-01/2025-10-20' \
  -H 'Authorization: oBearer your-jwt-token'

Data Structure

Labels Array

FieldTypeDescription
labelsarrayHour labels from 00:00:00 to 23:00:00

Series Object

FieldTypeDescription
receivedarraySeries showing received emails per hour per day
sentarraySeries showing sent emails per hour per day

Data Series Structure

Each object in received/sent arrays contains:
FieldTypeDescription
namestringDate of the data point (YYYY-MM-DD)
dataarray24-hour email counts

Data Alignment

  • series.received[i].data[j] corresponds to labels[j] for received emails on date series.received[i].name
  • series.sent[i].data[j] corresponds to labels[j] for sent emails on date series.sent[i].name
  • All data arrays have exactly 24 elements (one for each hour)

Use Cases

  • Peak Hours Analysis: Identify busiest email hours
  • Staff Scheduling: Optimize agent scheduling based on volume
  • Resource Planning: Allocate resources during peak times
  • Performance Monitoring: Track hourly performance patterns
  • Heat Map Visualization: Create hourly heat maps

Analysis Examples

Peak Hour Identification

const findPeakHours = (data) => {
  const hourlyTotals = data.labels.map((_, hourIndex) => {
    return data.series.received.reduce((sum, day) => sum + day.data[hourIndex], 0);
  });
  
  const maxVolume = Math.max(...hourlyTotals);
  const peakHour = hourlyTotals.indexOf(maxVolume);
  
  return {
    peakHour: data.labels[peakHour],
    peakVolume: maxVolume,
    peakHourIndex: peakHour
  };
};

Daily Pattern Analysis

const analyzeDailyPatterns = (data) => {
  return data.series.received.map(day => ({
    date: day.name,
    totalEmails: day.data.reduce((a, b) => a + b, 0),
    peakHour: data.labels[day.data.indexOf(Math.max(...day.data))],
    peakVolume: Math.max(...day.data)
  }));
};

Business Hours vs Non-Business Hours

const businessHoursAnalysis = (data) => {
  const businessHourIndices = [9, 10, 11, 12, 13, 14, 15, 16]; // 9 AM - 5 PM
  const nonBusinessHourIndices = [0, 1, 2, 3, 4, 5, 6, 7, 8, 17, 18, 19, 20, 21, 22, 23];
  
  const businessVolume = data.series.received.reduce((sum, day) => {
    return sum + businessHourIndices.reduce((daySum, hour) => daySum + day.data[hour], 0);
  }, 0);
  
  const nonBusinessVolume = data.series.received.reduce((sum, day) => {
    return sum + nonBusinessHourIndices.reduce((daySum, hour) => daySum + day.data[hour], 0);
  }, 0);
  
  return {
    businessHours: businessVolume,
    nonBusinessHours: nonBusinessVolume,
    businessPercentage: (businessVolume / (businessVolume + nonBusinessVolume)) * 100
  };
};

Visualization Examples

Heat Map

// Create heat map data
const heatMapData = data.series.received.map(day => day.data);

// Example using Chart.js with heatmap plugin
new Chart(ctx, {
  type: 'matrix',
  data: {
    datasets: [{
      label: 'Email Volume',
      data: heatMapData.flat().map((value, index) => ({
        x: index % 24,
        y: Math.floor(index / 24),
        v: value
      })),
      backgroundColor(ctx) {
        const value = ctx.dataset.data[ctx.dataIndex].v;
        const alpha = value / maxVolume;
        return `rgba(54, 162, 235, ${alpha})`;
      }
    }]
  }
});

Multi-Day Line Chart

const ctx = document.getElementById('hourlyTrends').getContext('2d');
new Chart(ctx, {
  type: 'line',
  data: {
    labels: data.labels,
    datasets: data.series.received.map(day => ({
      label: day.name,
      data: day.data,
      borderColor: `hsl(${Math.random() * 360}, 70%, 50%)`,
      tension: 0.4
    }))
  }
});

Best Practices

  1. Date Range: Use reasonable ranges (recommended: max 30 days for hourly detail)
  2. Time Zone: Convert UTC times to local time zones for display
  3. Aggregation: Consider aggregating multiple days for pattern analysis
  4. Visualization: Use heat maps for better pattern visualization
  5. Business Hours: Focus analysis on business hours for operational insights

Performance Considerations

  • Data Volume: Hourly data generates 24x more points than daily
  • Processing Time: Larger date ranges take longer to process
  • Memory Usage: Consider client-side memory for large datasets
  • Caching: Cache results for dashboard performance
  • Use /email-meter/stats/emails-trend for daily trends
  • Use /email-meter/stats/email-counts for aggregate statistics
  • Use /email-meter/stats/response-times for hourly response analysis

Notes

  • All times are in UTC - convert to local time for operational analysis
  • Zero-value hours are included for complete timeline
  • Data includes all email types (incoming, outgoing, internal)
  • Weekends and holidays are included in hourly breakdown
  • Automated emails are included unless filtered specifically

Authorizations

Authorization
string
header
required

Bearer authentication header of the form Bearer <token>, where <token> is your auth token.

Path Parameters

startDate
string<date>
required

Start date for the range (YYYY-MM-DD)

endDate
string<date>
required

End date for the range (YYYY-MM-DD)

Response

Hourly email trends between given dates

message
string
Example:

""

data
object