Skip to main content

Overview

Event endpoints allow you to retrieve events from your categories with filtering and pagination.
These endpoints use Hono.js server procedures and require authentication via session cookies (not Bearer tokens). They are primarily used by the PingPilot web dashboard.

Get Events by Category

Retrieve events for a specific category with time-based filtering and pagination.
GET /api/category/getEventsByCategoryName

Query Parameters

name
string
required
Category name to retrieve events from.Validation:
  • Must contain only letters, numbers, or hyphens
  • Must match an existing category
page
number
required
Page number for pagination (1-indexed).Example: 1, 2, 3
limit
number
required
Number of events per page.Constraints:
  • Maximum: 50
  • Minimum: 1
Example: 10, 25, 50
timeRange
string
required
Time range to filter events.Options:
  • today - Events from today (since midnight)
  • week - Events from this week (since Sunday)
  • month - Events from this month (since 1st of month)

Request Example

GET /api/category/getEventsByCategoryName?name=bug&page=1&limit=25&timeRange=week

Response

events
array
Array of event objects.
events[].id
string
Unique event identifier.
events[].name
string
Event category name.
events[].formattedMessage
string
Formatted event message sent in notifications.
events[].fields
object
Custom fields attached to the event.
events[].deliveryStatus
string
Delivery status: "DELIVERED" or "FAILED".
events[].createdAt
string
ISO timestamp when event was created.
events[].userId
string
User ID who owns this event.
events[].eventCategoryId
string
Category ID this event belongs to.
eventsCount
number
Total number of events matching the query (for pagination).
uniqueFieldCount
number
Number of unique field keys used across all events in the time range.
success
boolean
Whether the operation succeeded.

Success Response

{
  "events": [
    {
      "id": "evt_clx1234567890",
      "name": "bug",
      "formattedMessage": "🐛 Bug\n\nDatabase connection timeout",
      "fields": {
        "severity": "high",
        "service": "api-server",
        "error_code": "ETIMEDOUT"
      },
      "deliveryStatus": "DELIVERED",
      "createdAt": "2026-03-06T10:30:00.000Z",
      "userId": "user_123",
      "eventCategoryId": "cat_abc"
    },
    {
      "id": "evt_clx0987654321",
      "name": "bug",
      "formattedMessage": "🐛 Bug\n\nMemory leak detected",
      "fields": {
        "severity": "medium",
        "memory_usage": "2.5GB"
      },
      "deliveryStatus": "DELIVERED",
      "createdAt": "2026-03-05T15:20:00.000Z",
      "userId": "user_123",
      "eventCategoryId": "cat_abc"
    }
  ],
  "eventsCount": 47,
  "uniqueFieldCount": 8,
  "success": true
}

Error Response

Status Code: 404 Not Found
{
  "message": "Category \"nonexistent\" not found"
}

Event Object Structure

Event Fields


Time Range Behavior

Today

Returns events from midnight (00:00:00) of the current day in your timezone.
startDate = startOfDay(now)
// Example: 2026-03-06T00:00:00.000Z

Week

Returns events from the start of the current week (Sunday at 00:00:00).
startDate = startOfWeek(now, { weekStartsOn: 0 })
// Example: 2026-03-02T00:00:00.000Z (last Sunday)

Month

Returns events from the 1st of the current month at 00:00:00.
startDate = startOfMonth(now)
// Example: 2026-03-01T00:00:00.000Z

Pagination

Events are returned in descending order by creation time (newest first).

Calculation

const skip = (page - 1) * limit
const take = limit

// Example: page=2, limit=25
// skip=25, take=25
// Returns events 26-50

Example: Fetching All Events

const fetchAllEvents = async (categoryName, timeRange) => {
  const limit = 50; // Max allowed
  let page = 1;
  let allEvents = [];
  let hasMore = true;

  while (hasMore) {
    const response = await fetch(
      `/api/events/${categoryName}?page=${page}&limit=${limit}&timeRange=${timeRange}`,
      { credentials: 'include' }
    );
    
    const data = await response.json();
    allEvents = allEvents.concat(data.events);
    
    // Check if there are more pages
    hasMore = data.events.length === limit;
    page++;
  }

  return allEvents;
};

Unique Field Count

The uniqueFieldCount field indicates how many distinct field keys have been used across all events in the selected time range. Example: If you have 3 events:
// Event 1
{ "fields": { "severity": "high", "user_id": "123" } }

// Event 2
{ "fields": { "severity": "low", "error_code": "E001" } }

// Event 3
{ "fields": { "user_id": "456", "timestamp": "2026-03-06" } }
Unique field keys: severity, user_id, error_code, timestamp Result: uniqueFieldCount: 4

Filtering Events

By Delivery Status

To find failed events, filter the results client-side:
const failedEvents = data.events.filter(
  event => event.deliveryStatus === 'FAILED'
);

By Field Value

To find events with specific field values:
const highSeverityEvents = data.events.filter(
  event => event.fields.severity === 'high'
);

By Date Range (Custom)

For custom date ranges, fetch all events and filter:
const eventsSince = (events, sinceDate) => {
  const since = new Date(sinceDate);
  return events.filter(event => new Date(event.createdAt) >= since);
};

Best Practices

  • Use appropriate time ranges to limit result size
  • Implement pagination for large datasets (use max limit of 50)
  • Cache results when possible to reduce API calls
  • Monitor delivery status to identify notification failures
  • Index field keys client-side for fast filtering
  • Handle empty results gracefully (new categories may have no events)

Build docs developers (and LLMs) love