Skip to content

External Feed API

The External Feed API is a read-only REST API that allows MSSP partners, customer SOC teams, SOAR platforms, and external SIEMs to pull security data from RhythmX. API keys authenticate requests and control access scope — master keys see all entities, scoped keys see only their entity.


How It Works

flowchart LR
    A["MSSP Partner<br>or Customer SOC"] -->|"X-API-Key header"| B["API Key<br>Authentication"]
    B --> C{"Master Key?"}
    C -->|"Yes (entity_name=*)"| D["All Entities<br>or filter by ?entity_name="]
    C -->|"No (entity_name=CustomerA)"| E["CustomerA Only"]
    D --> F["JSON Response<br><i>Paginated</i>"]
    E --> F

    style A fill:#4a148c,stroke:#9c27b0,color:#fff
    style B fill:#b71c1c,stroke:#f05545,color:#fff
    style C fill:#e65100,stroke:#ff9800,color:#fff
    style D fill:#0d47a1,stroke:#42a5f5,color:#fff
    style E fill:#0d47a1,stroke:#42a5f5,color:#fff
    style F fill:#1b5e20,stroke:#4c8c4a,color:#fff

Base URL

https://<your-rhythmx-host>/api/v1/feed

All endpoints are prefixed with /api/v1/feed.


Authentication

Include your API key in the X-API-Key header with every request.

curl -H "X-API-Key: smk_your_api_key_here" \
     https://rhythmx.example.com/api/v1/feed/health

Key Types

Key Type entity_name in DB Behavior
Master Key * Sees all entities. Pass ?entity_name=X to filter, or omit for all.
Scoped Key CustomerA Only sees CustomerA data. Cannot access other entities.

Key Properties

  • Non-retrievable — plaintext key shown only once at creation
  • Revocable — can be disabled or deleted anytime
  • Expirable — optional expiration date
  • Rate-limited — 120 requests per minute per API key (configurable via FEED_RATE_LIMIT env var)

Rate Limiting

All external feed endpoints are rate-limited per API key to prevent abuse:

Setting Default Configurable
Requests per minute 120 FEED_RATE_LIMIT in .env.production
Scope Per API key Each key has its own limit
Response when exceeded 429 Too Many Requests Includes Retry-After header

Example error when rate limit is exceeded:

{
  "error": "Rate limit exceeded",
  "retry_after": 30
}

Common Parameters

These parameters are available on all list endpoints:

Parameter Type Description
entity_name string Filter by entity (master keys only — scoped keys ignore this)
since string ISO 8601 timestamp — only return records created/updated after this time
limit integer Results per page (default: 50, max: 500)
offset integer Pagination offset (default: 0)

Incremental Polling (since parameter)

The since parameter enables efficient incremental polling — consumers only pull data that has changed since their last request. Supported on all endpoints that return time-based data.

Accepted formats:

?since=2026-03-20T10:30:00Z       (ISO 8601 with timezone)
?since=2026-03-20T10:30:00        (ISO 8601 without timezone — treated as UTC)
?since=2026-03-20                  (date only — from midnight UTC)

Example — poll every 5 minutes for new alerts:

# First call — get everything from the last hour
curl -H "X-API-Key: smk_abc12345..." \
     "https://rhythmx.example.com/api/v1/feed/alerts?since=2026-03-20T09:30:00Z"

# Subsequent calls — only get what's new since last poll
curl -H "X-API-Key: smk_abc12345..." \
     "https://rhythmx.example.com/api/v1/feed/alerts?since=2026-03-20T09:35:00Z"

Endpoints supporting since:

Endpoint Time column filtered
/incidents updated_at
/cases updated_at
/alerts system_time
/alerts/stats system_time
/risks/top-users system_time
/risks/top-computers system_time
/risks/top-rules system_time
/mitre/tactics system_time
/mitre/techniques system_time

Response Format

All endpoints return this structure:

{
  "success": true,
  "data": [ ... ],
  "pagination": {
    "total": 150,
    "limit": 50,
    "offset": 0,
    "has_more": true
  },
  "timestamp": "2026-03-20T10:30:00Z"
}

Endpoints

Health Check

GET /api/v1/feed/health

Returns the API service status.

Example:

curl -H "X-API-Key: smk_abc12345..." \
     https://rhythmx.example.com/api/v1/feed/health

Response:

{
  "status": "ok",
  "service": "external_feed_api"
}


List Incidents

GET /api/v1/feed/incidents

Returns security incidents. Each incident represents a group of related alarms for an actor (user or computer).

Parameters:

Parameter Type Description
entity_name string (Optional) Filter by entity/site. Master keys only — scoped keys ignore this.
status string OPEN, IN_PROGRESS, CLOSED, FALSE_POSITIVE
since string ISO 8601 — incidents updated after this time
limit integer Results per page (default: 50)
offset integer Pagination offset

Example:

# All entities
curl -H "X-API-Key: smk_abc12345..." \
     "https://rhythmx.example.com/api/v1/feed/incidents?status=OPEN&limit=20"

# Specific entity
curl -H "X-API-Key: smk_abc12345..." \
     "https://rhythmx.example.com/api/v1/feed/incidents?entity_name=Primary%20Site&status=OPEN"

Response:

{
  "success": true,
  "data": [
    {
      "incident_id": "INC-a1b2c3d4",
      "group_key": "jsmith",
      "actor_type": "user",
      "entity_name": "Primary Site",
      "status": "OPEN",
      "assigned_analyst": null,
      "first_alarm_time": "2026-03-02T08:15:00Z",
      "last_alarm_time": "2026-03-02T14:20:00Z",
      "created_at": "2026-03-02T14:22:00Z",
      "updated_at": "2026-03-02T14:22:00Z",
      "closed_at": null,
      "external_ticket_id": null,
      "external_system": null
    }
  ],
  "pagination": {
    "total": 12,
    "limit": 20,
    "offset": 0,
    "has_more": false
  },
  "timestamp": "2026-03-20T10:30:00Z"
}


Get Incident Detail

GET /api/v1/feed/incidents/{incident_id}

Returns full details for a single incident including all fields.

Example:

curl -H "X-API-Key: smk_abc12345..." \
     https://rhythmx.example.com/api/v1/feed/incidents/INC-a1b2c3d4


List Cases

GET /api/v1/feed/cases

Returns threat cases — correlated attack patterns detected by the analytics engine.

Parameters:

Parameter Type Description
entity_name string (Optional) Filter by entity/site. Master keys only — scoped keys ignore this.
status string OPEN, IN_PROGRESS, CLOSED, FALSE_POSITIVE
severity string CRITICAL, HIGH, MEDIUM, LOW
case_type string e.g., LATERAL_MOVEMENT, RANSOMWARE_INDICATORS, BRUTE_FORCE, CREDENTIAL_THEFT, PERSISTENCE, PRIVILEGE_ESCALATION, RECONNAISSANCE
since string ISO 8601 — cases updated after this time
limit integer Results per page (default: 50)
offset integer Pagination offset

Example:

curl -H "X-API-Key: smk_abc12345..." \
     "https://rhythmx.example.com/api/v1/feed/cases?severity=CRITICAL&case_type=RANSOMWARE_INDICATORS"

Response:

{
  "success": true,
  "data": [
    {
      "case_id": "CASE-x1y2z3",
      "entity_name": "Primary Site",
      "case_type": "RANSOMWARE_INDICATORS",
      "status": "OPEN",
      "severity": "CRITICAL",
      "primary_user": "admin",
      "affected_computers": "DC01,WS-PC42",
      "alert_count": 47,
      "max_risk_score": 95,
      "first_alert_time": "2026-03-19T03:10:00Z",
      "last_alert_time": "2026-03-19T04:45:00Z",
      "created_at": "2026-03-19T04:46:00Z",
      "updated_at": "2026-03-19T04:46:00Z"
    }
  ],
  "pagination": {
    "total": 3,
    "limit": 50,
    "offset": 0,
    "has_more": false
  },
  "timestamp": "2026-03-20T10:30:00Z"
}


Get Case Detail

GET /api/v1/feed/cases/{case_id}

Returns full details for a single threat case.

Example:

curl -H "X-API-Key: smk_abc12345..." \
     https://rhythmx.example.com/api/v1/feed/cases/CASE-x1y2z3


List Alerts

GET /api/v1/feed/alerts

Returns RhythmX detection alerts — individual rule matches from the detection engine.

Parameters:

Parameter Type Description
entity_name string (Optional) Filter by entity/site. Master keys only — scoped keys ignore this.
rule_level string informational, low, medium, high, critical
since string ISO 8601 — alerts with system_time after this
limit integer Results per page (default: 50, max: 500)
offset integer Pagination offset

Example:

curl -H "X-API-Key: smk_abc12345..." \
     "https://rhythmx.example.com/api/v1/feed/alerts?rule_level=critical&limit=10"

Response:

{
  "success": true,
  "data": [
    {
      "id": 154832,
      "title": "Mimikatz Command Line Usage",
      "description": "Detects Mimikatz command line arguments",
      "rule_level": "critical",
      "tags": "attack.credential_access,attack.t1003",
      "tactics": "credential_access",
      "techniques": "T1003",
      "computer_name": "DC01",
      "user_id": "admin",
      "ip_address": "10.0.5.42",
      "entity_name": "Primary Site",
      "system_time": "2026-03-19T14:22:00Z",
      "risk": 95,
      "image_path": "C:\\Windows\\Temp\\mimi.exe",
      "command_line": "sekurlsa::logonpasswords",
      "count": 1,
      "first_seen": "2026-03-19T14:22:00Z",
      "last_seen": "2026-03-19T14:22:00Z"
    }
  ],
  "pagination": {
    "total": 5,
    "limit": 10,
    "offset": 0,
    "has_more": false
  },
  "timestamp": "2026-03-20T10:30:00Z"
}


Get Alert Detail

GET /api/v1/feed/alerts/{alert_id}

Returns full details for a single alert including raw log data.


Alert Statistics

GET /api/v1/feed/alerts/stats

Returns aggregate alert statistics.

Parameters:

Parameter Type Description
entity_name string (Optional) Filter by entity/site. Master keys only — scoped keys ignore this.

Example:

curl -H "X-API-Key: smk_abc12345..." \
     https://rhythmx.example.com/api/v1/feed/alerts/stats

Response:

{
  "success": true,
  "data": {
    "total_alerts": 45832,
    "by_level": {
      "critical": 127,
      "high": 1893,
      "medium": 12450,
      "low": 28100,
      "informational": 3262
    },
    "by_entity": [
      { "entity_name": "Primary Site", "count": 28000 },
      { "entity_name": "Branch Office", "count": 17832 }
    ],
    "top_rules": [
      { "title": "Remote Access Tool Execution", "rule_level": "high", "count": 4521 },
      { "title": "Suspicious PowerShell Command", "rule_level": "medium", "count": 3102 }
    ]
  },
  "timestamp": "2026-03-20T10:30:00Z"
}


SOC Metrics Overview

GET /api/v1/feed/metrics/overview

Returns high-level SOC metrics — total counts across incidents, cases, and alerts.

Parameters:

Parameter Type Description
entity_name string (Optional) Filter by entity/site. Master keys only — scoped keys ignore this.

Example:

curl -H "X-API-Key: smk_abc12345..." \
     https://rhythmx.example.com/api/v1/feed/metrics/overview

Response:

{
  "success": true,
  "data": {
    "total_incidents": 342,
    "open_incidents": 28,
    "in_progress_incidents": 12,
    "total_cases": 89,
    "open_cases": 15,
    "critical_cases": 3,
    "total_alerts": 45832,
    "critical_alerts": 127,
    "high_alerts": 1893
  },
  "timestamp": "2026-03-20T10:30:00Z"
}


Severity Breakdown

GET /api/v1/feed/metrics/severity

Returns incident and case counts broken down by status and severity.

Parameters:

Parameter Type Description
entity_name string (Optional) Filter by entity/site. Master keys only — scoped keys ignore this.

Response:

{
  "success": true,
  "data": {
    "incidents_by_status": {
      "OPEN": 28,
      "IN_PROGRESS": 12,
      "CLOSED": 285,
      "FALSE_POSITIVE": 17
    },
    "cases_by_severity": {
      "CRITICAL": 3,
      "HIGH": 22,
      "MEDIUM": 41,
      "LOW": 23
    },
    "cases_by_type": {
      "LATERAL_MOVEMENT": 12,
      "BRUTE_FORCE": 18,
      "CREDENTIAL_THEFT": 8,
      "PERSISTENCE": 15,
      "RANSOMWARE_INDICATORS": 3
    }
  },
  "timestamp": "2026-03-20T10:30:00Z"
}


Mean Time to Respond (MTTR)

GET /api/v1/feed/metrics/mttr

Returns average time from incident creation to closure.

Parameters:

Parameter Type Description
entity_name string (Optional) Filter by entity/site. Master keys only — scoped keys ignore this.

Response:

{
  "success": true,
  "data": {
    "overall_mttr_minutes": 142,
    "closed_incidents": 285,
    "by_status": {
      "CLOSED": { "avg_minutes": 125, "count": 268 },
      "FALSE_POSITIVE": { "avg_minutes": 45, "count": 17 }
    }
  },
  "timestamp": "2026-03-20T10:30:00Z"
}


GET /api/v1/feed/metrics/trends

Returns daily incident and case creation counts over time.

Parameters:

Parameter Type Description
entity_name string (Optional) Filter by entity/site. Master keys only — scoped keys ignore this.
days integer Number of days to look back (default: 30, max: 90)

Example:

curl -H "X-API-Key: smk_abc12345..." \
     "https://rhythmx.example.com/api/v1/feed/metrics/trends?days=7"

Response:

{
  "success": true,
  "data": {
    "daily": [
      { "date": "2026-03-19", "incidents": 5, "cases": 2 },
      { "date": "2026-03-18", "incidents": 8, "cases": 3 },
      { "date": "2026-03-17", "incidents": 3, "cases": 1 },
      { "date": "2026-03-16", "incidents": 12, "cases": 4 },
      { "date": "2026-03-15", "incidents": 6, "cases": 2 },
      { "date": "2026-03-14", "incidents": 4, "cases": 1 },
      { "date": "2026-03-13", "incidents": 7, "cases": 3 }
    ]
  },
  "timestamp": "2026-03-20T10:30:00Z"
}


MITRE ATT&CK Tactics

GET /api/v1/feed/mitre/tactics

Returns alert counts grouped by MITRE ATT&CK tactic.

Parameters:

Parameter Type Description
entity_name string (Optional) Filter by entity/site. Master keys only — scoped keys ignore this.
limit integer Results per page (default: 50, max: 500)
offset integer Pagination offset (default: 0)

Response:

{
  "success": true,
  "data": [
    { "tactic": "credential_access", "count": 4521 },
    { "tactic": "lateral_movement", "count": 3102 },
    { "tactic": "execution", "count": 2890 },
    { "tactic": "persistence", "count": 2145 },
    { "tactic": "defense_evasion", "count": 1876 }
  ],
  "pagination": {
    "total": 11,
    "limit": 50,
    "offset": 0,
    "has_more": false
  },
  "timestamp": "2026-03-20T10:30:00Z"
}


MITRE ATT&CK Techniques

GET /api/v1/feed/mitre/techniques

Returns alert counts grouped by MITRE ATT&CK technique.

Parameters:

Parameter Type Description
entity_name string (Optional) Filter by entity/site. Master keys only — scoped keys ignore this.
limit integer Results per page (default: 50, max: 500)
offset integer Pagination offset (default: 0)

Response:

{
  "success": true,
  "data": [
    { "technique": "T1003", "count": 2341 },
    { "technique": "T1059", "count": 1892 },
    { "technique": "T1021", "count": 1654 },
    { "technique": "T1053", "count": 1230 },
    { "technique": "T1078", "count": 987 }
  ],
  "pagination": {
    "total": 45,
    "limit": 50,
    "offset": 0,
    "has_more": false
  },
  "timestamp": "2026-03-20T10:30:00Z"
}


List Entities

GET /api/v1/feed/entities

Returns all entities (sites/customers) with their incident, case, and alert counts.

Parameters:

Parameter Type Description
limit integer Results per page (default: 50, max: 500)
offset integer Pagination offset (default: 0)

Response:

{
  "success": true,
  "data": [
    {
      "entity_name": "Primary Site",
      "incident_count": 215,
      "case_count": 52,
      "alert_count": 28000
    },
    {
      "entity_name": "Branch Office",
      "incident_count": 127,
      "case_count": 37,
      "alert_count": 17832
    }
  ],
  "pagination": {
    "total": 2,
    "limit": 50,
    "offset": 0,
    "has_more": false
  },
  "timestamp": "2026-03-20T10:30:00Z"
}


Entity Summary

GET /api/v1/feed/entities/{entity_name}/summary

Returns a detailed summary for a specific entity.

Example:

curl -H "X-API-Key: smk_abc12345..." \
     "https://rhythmx.example.com/api/v1/feed/entities/Primary%20Site/summary"

Response:

{
  "success": true,
  "data": {
    "entity_name": "Primary Site",
    "incidents": {
      "total": 215,
      "open": 18,
      "in_progress": 8,
      "closed": 180,
      "false_positive": 9
    },
    "cases": {
      "total": 52,
      "critical": 2,
      "high": 12,
      "medium": 25,
      "low": 13
    },
    "alerts": {
      "total": 28000,
      "critical": 82,
      "high": 1200
    },
    "top_rules": [
      { "title": "Remote Access Tool Execution", "count": 2800 },
      { "title": "Suspicious PowerShell Command", "count": 1950 }
    ],
    "top_users": [
      { "user_id": "admin", "alert_count": 450, "total_risk": 12500 },
      { "user_id": "svc_backup", "alert_count": 320, "total_risk": 8900 }
    ],
    "top_computers": [
      { "computer_name": "DC01", "alert_count": 890, "total_risk": 24000 },
      { "computer_name": "WS-PC42", "alert_count": 650, "total_risk": 18000 }
    ]
  },
  "timestamp": "2026-03-20T10:30:00Z"
}


Top Risky Users

GET /api/v1/feed/risks/top-users

Returns users with the highest cumulative risk scores.

Parameters:

Parameter Type Description
entity_name string (Optional) Filter by entity/site. Master keys only — scoped keys ignore this.
limit integer Results per page (default: 50, max: 500)
offset integer Pagination offset (default: 0)

Response:

{
  "success": true,
  "data": [
    { "user_id": "admin", "entity_name": "Primary Site", "total_risk": 12500, "alert_count": 450 },
    { "user_id": "svc_backup", "entity_name": "Primary Site", "total_risk": 8900, "alert_count": 320 },
    { "user_id": "jsmith", "entity_name": "Branch Office", "total_risk": 6200, "alert_count": 180 }
  ],
  "pagination": {
    "total": 85,
    "limit": 50,
    "offset": 0,
    "has_more": true
  },
  "timestamp": "2026-03-20T10:30:00Z"
}


Top Risky Computers

GET /api/v1/feed/risks/top-computers

Returns computers with the highest cumulative risk scores.

Parameters:

Parameter Type Description
entity_name string (Optional) Filter by entity/site. Master keys only — scoped keys ignore this.
limit integer Results per page (default: 50, max: 500)
offset integer Pagination offset (default: 0)

Response:

{
  "success": true,
  "data": [
    { "computer_name": "DC01", "entity_name": "Primary Site", "total_risk": 24000, "alert_count": 890 },
    { "computer_name": "WS-PC42", "entity_name": "Primary Site", "total_risk": 18000, "alert_count": 650 },
    { "computer_name": "EXCH01", "entity_name": "Branch Office", "total_risk": 9500, "alert_count": 420 }
  ],
  "pagination": {
    "total": 42,
    "limit": 50,
    "offset": 0,
    "has_more": false
  },
  "timestamp": "2026-03-20T10:30:00Z"
}


Top Triggered Rules

GET /api/v1/feed/risks/top-rules

Returns the most frequently triggered detection rules.

Parameters:

Parameter Type Description
entity_name string (Optional) Filter by entity/site. Master keys only — scoped keys ignore this.
limit integer Results per page (default: 50, max: 500)
offset integer Pagination offset (default: 0)

Response:

{
  "success": true,
  "data": [
    { "title": "Remote Access Tool Execution", "rule_level": "high", "count": 4521, "description": "Detects execution of known remote access tools" },
    { "title": "Suspicious PowerShell Command", "rule_level": "medium", "count": 3102, "description": "Detects suspicious PowerShell command line patterns" },
    { "title": "Mimikatz Command Line Usage", "rule_level": "critical", "count": 127, "description": "Detects Mimikatz command line arguments" }
  ],
  "pagination": {
    "total": 156,
    "limit": 50,
    "offset": 0,
    "has_more": true
  },
  "timestamp": "2026-03-20T10:30:00Z"
}



Entity Filtering (Master Keys)

Master keys (entity_name=*) can filter by entity on any endpoint:

# All entities
curl -H "X-API-Key: smk_master_key..." \
     "https://rhythmx.example.com/api/v1/feed/incidents"

# Specific entity
curl -H "X-API-Key: smk_master_key..." \
     "https://rhythmx.example.com/api/v1/feed/incidents?entity_name=Primary%20Site"

# Scoped keys ignore the entity_name parameter
curl -H "X-API-Key: smk_customer_key..." \
     "https://rhythmx.example.com/api/v1/feed/incidents"
# ^ Always returns only that customer's data

Rate Limiting

API keys have a configurable rate limit (default: 60 requests per minute). When exceeded, the API returns 429 Too Many Requests.


Error Codes

Code Meaning
200 Success
400 Bad request (missing required parameter)
401 Invalid, expired, or disabled API key
404 Resource not found
429 Rate limit exceeded
500 Internal server error

Error Response:

{
  "error": "Invalid or disabled API key"
}


Quick Reference

Endpoint Method Description
/api/v1/feed/health GET Service health check
/api/v1/feed/incidents GET List incidents
/api/v1/feed/incidents/{id} GET Incident detail
/api/v1/feed/cases GET List threat cases
/api/v1/feed/cases/{id} GET Case detail
/api/v1/feed/alerts GET List RhythmX alerts
/api/v1/feed/alerts/{id} GET Alert detail
/api/v1/feed/alerts/stats GET Alert statistics
/api/v1/feed/metrics/overview GET SOC overview metrics
/api/v1/feed/metrics/severity GET Severity/status breakdown
/api/v1/feed/metrics/mttr GET Mean time to respond
/api/v1/feed/metrics/trends GET Daily incident/case trends
/api/v1/feed/mitre/tactics GET MITRE ATT&CK tactics
/api/v1/feed/mitre/techniques GET MITRE ATT&CK techniques
/api/v1/feed/entities GET List entities with counts
/api/v1/feed/entities/{name}/summary GET Entity detail summary
/api/v1/feed/risks/top-users GET Top risky users
/api/v1/feed/risks/top-computers GET Top risky computers
/api/v1/feed/risks/top-rules GET Top triggered rules

API Key Management

API keys are managed by administrators through the Integration Admin interface in System Settings.

Field Description
Label Human-readable label for the key
Description Purpose of the key
Entity Name Entity to scope to, or * for master key
Scopes Permissions granted (default: all read scopes)
Rate Limit Requests per minute (default: 60)
Expires At Optional expiration date
Enabled Whether the key is active