Quick Reference: Recording Retention API

July 30, 2026 ยท View on GitHub

Database Functions

Stream Retention Configuration

// Get retention config for a stream
int get_stream_retention_config(const char *stream_name, 
                                stream_retention_config_t *config);

// Set retention config for a stream
int set_stream_retention_config(const char *stream_name, 
                                const stream_retention_config_t *config);

// Get storage usage for a stream
int get_stream_storage_usage(const char *stream_name, uint64_t *size_bytes);

// Structure
typedef struct {
    int retention_days;              // -1 global, 0 unlimited, >0 days
    int detection_retention_days;    // -1 global, 0 unlimited, >0 days
    uint64_t max_storage_mb;        // Storage quota (0 = unlimited)
} stream_retention_config_t;

Recording Protection

// Mark recording as protected/unprotected
int set_recording_protected(uint64_t recording_id, bool protected);

// Set custom retention override for recording
int set_recording_retention_override(uint64_t recording_id, int days);

// Get count of protected recordings for a stream
int get_protected_recordings_count(const char *stream_name);

Retention Policy Execution

// Apply retention policy for all streams
int apply_retention_policy(void);

// Apply retention policy for specific stream
static int apply_retention_policy_for_stream(const char *stream_name);

// Enforce storage quota for stream
static int enforce_storage_quota(const char *stream_name, uint64_t max_mb);

// Cleanup orphaned files and DB entries
static int cleanup_orphaned_files(void);
static int cleanup_orphaned_db_entries(void);

REST API Endpoints

Stream Retention Configuration

Update Stream Retention Settings

PATCH /api/streams/:name
Content-Type: application/json

{
  "retention_days": 30,
  "detection_retention_days": 90,
  "max_storage_mb": 10240
}

Response: 200 OK
{
  "success": true,
  "message": "Stream updated successfully"
}

Get Stream with Retention Settings

GET /api/streams/:name

Response: 200 OK
{
  "name": "camera1",
  "url": "rtsp://...",
  "retention_days": 30,
  "detection_retention_days": 90,
  "max_storage_mb": 10240,
  ...
}

Recording Protection

Protect/Unprotect Recording

PATCH /api/recordings/:id/protect
Content-Type: application/json

{
  "protected": true,
  "retention_override_days": 365  // Optional
}

Response: 200 OK
{
  "success": true,
  "message": "Recording protection updated"
}

Get Protected Recordings

GET /api/recordings?protected=true&stream_name=camera1

Response: 200 OK
{
  "recordings": [
    {
      "id": 123,
      "stream_name": "camera1",
      "protected": true,
      "retention_override_days": 365,
      "trigger_type": "detection",
      ...
    }
  ],
  "total": 5
}

Enhanced Batch Delete

Batch Delete with Filters

POST /api/recordings/batch-delete
Content-Type: application/json

{
  "filter": {
    "stream_name": "camera1",
    "start_time": 1234567890,
    "end_time": 1234567999,
    "has_detections": false,
    "protected": false,
    "trigger_type": "scheduled"
  }
}

Response: 200 OK
{
  "success": true,
  "deleted": 45,
  "failed": 0,
  "protected_excluded": 5,
  "breakdown": {
    "scheduled": 30,
    "detection": 15
  }
}

SQL Queries

Query Recordings for Deletion (Priority 1)

SELECT id, file_path, start_time, size_bytes
FROM recordings
WHERE stream_name = ?
  AND start_time < ?
  AND trigger_type != 'detection'
  AND protected = 0
  AND retention_override_days IS NULL
ORDER BY start_time ASC;

Query Recordings for Deletion (Priority 2)

SELECT id, file_path, start_time, size_bytes
FROM recordings
WHERE stream_name = ?
  AND start_time < ?
  AND trigger_type = 'detection'
  AND protected = 0
  AND retention_override_days IS NULL
ORDER BY start_time ASC;

Get Stream Storage Usage

SELECT SUM(size_bytes) as total_bytes
FROM recordings
WHERE stream_name = ?
  AND is_complete = 1;

Get Protected Recordings Count

SELECT COUNT(*) as protected_count
FROM recordings
WHERE stream_name = ?
  AND protected = 1;

Configuration Examples

Example 1: High-Security Camera

{
  "retention_days": 90,
  "detection_retention_days": 365,
  "max_storage_mb": 102400
}

Example 2: Low-Priority Camera

{
  "retention_days": 7,
  "detection_retention_days": 30,
  "max_storage_mb": 10240
}

Example 3: Archive Camera (Unlimited)

{
  "retention_days": 0,
  "detection_retention_days": 0,
  "max_storage_mb": 0
}

-1 inherits the live global setting, 0 means unlimited retention, and a positive number sets a per-stream day limit. New streams default to -1.

Error Codes

CodeMeaning
200Success
400Invalid parameters
403Permission denied
404Recording/Stream not found
500Internal server error