Skip to main content

Creating API Endpoints for Specific Data

Focused endpoints return the smallest useful result for a particular user need. This tutorial adds filtered and summary endpoints using PDO and fictional records.

Endpoint for one severity

Create api/events-by-severity.php:

<?php
declare(strict_types=1);

require __DIR__ . '/../includes/database.php';

header('Content-Type: application/json; charset=utf-8');
header('Cache-Control: no-store');

$allowed = ['low', 'medium', 'high', 'critical'];
$severity = strtolower(trim($_GET['severity'] ?? ''));

if (!in_array($severity, $allowed, true)) {
    http_response_code(400);
    echo json_encode([
        'ok' => false,
        'error' => 'Choose low, medium, high or critical.'
    ]);
    exit;
}

$statement = $pdo->prepare(
    'SELECT
        event_id,
        event_timestamp,
        device_id,
        room,
        event_type,
        severity
     FROM security_events
     WHERE severity = :severity
     ORDER BY event_timestamp DESC
     LIMIT 100'
);

$statement->execute(['severity' => $severity]);
$events = $statement->fetchAll();

echo json_encode([
    'ok' => true,
    'filter' => ['severity' => $severity],
    'count' => count($events),
    'events' => $events
]);

Test it with a fictional category:

http://localhost/project/api/events-by-severity.php?severity=high

The allow-list rejects unexpected values and the prepared statement keeps the supplied value separate from the SQL.

Endpoint for summary totals

Create api/event-summary.php:

<?php
declare(strict_types=1);

require __DIR__ . '/../includes/database.php';

header('Content-Type: application/json; charset=utf-8');
header('Cache-Control: no-store');

$statement = $pdo->query(
    'SELECT severity, COUNT(*) AS total
     FROM security_events
     GROUP BY severity
     ORDER BY severity'
);

$rows = $statement->fetchAll();

$summary = [];

foreach ($rows as $row) {
    $summary[] = [
        'severity' => $row['severity'],
        'total' => (int) $row['total']
    ];
}

echo json_encode([
    'ok' => true,
    'summary' => $summary
]);

This endpoint returns processed information rather than every event record. It can support an accessible table or chart.

Choose endpoints from user needs

Useful endpoints might answer:

  • Which fictional events require urgent review?
  • How many events occurred in each category?
  • Which events belong to a selected device?
  • How has the event count changed over time?

Avoid creating many endpoints that expose the same unnecessary fields.

Check

  • Invalid filters return HTTP 400 and a clear JSON error.
  • User-supplied values are validated and passed through prepared statements.
  • Totals are cast to numbers before encoding.
  • Responses contain only the required fields.
  • No personal information or credentials are exposed.
  • All demonstration records are fictional.