API User Guide: Reference
This page is the endpoint-by-endpoint reference for the Logster REST API. Every shape here is derived from services/api/src/logster_api/app.py. If anything here drifts from that file, the file wins.
For base URL, authentication posture, and interactive docs, see the Overview. For task-oriented workflows, see API Usage.
Endpoints at a glance
| Method | Path | Purpose |
|---|---|---|
GET |
/health |
Service health check |
GET |
/alerts |
List alerts, filtered and paginated |
GET |
/alerts/{alert_id} |
Fetch one alert |
PATCH |
/alerts/{alert_id} |
Update status / notes |
POST |
/feedback |
Submit analyst verdict |
GET |
/endpoints |
Per-endpoint summary |
GET /health
Returns a lightweight liveness response plus a cheap summary of how many alerts the in-process store currently holds.
Response — HealthResponse
| Field | Type | Notes |
|---|---|---|
status |
string | "ok" when the alert store is attached. |
service |
string | Always "logster-api". |
uptime_seconds |
float | Seconds since the FastAPI app started. |
alerts_count |
int | Current count of alerts in the store. |
Example
GET /alerts
List alerts with optional filtering and pagination.
Query parameters
| Name | Type | Default | Notes |
|---|---|---|---|
tenant_id |
string | — | Restrict to a single tenant. |
status |
string | — | One of open, acknowledged, investigating, resolved, false_positive (lowercase — enum values in libs/logster-common/logster_common/schemas/alerts.py). Invalid values return 400. |
limit |
int | 100 |
Must be 1..1000. |
offset |
int | 0 |
Zero-based page offset. |
Response — AlertListResponse
| Field | Type | Notes |
|---|---|---|
alerts |
array of AlertResponse |
Current page. |
total |
int | Total matching alerts in the store (pre-pagination), for this tenant if tenant_id is supplied. |
limit |
int | Echo of the request limit. |
offset |
int | Echo of the request offset. |
Example
GET /alerts/{alert_id}
Fetch a single alert by id.
Path parameters
| Name | Type | Notes |
|---|---|---|
alert_id |
string | The alert_id returned by a previous /alerts query. |
Responses
200—AlertResponse404—{"detail": "Alert <id> not found"}
Example
PATCH /alerts/{alert_id}
Update an alert's status and optionally attach analyst notes. This is how analysts move an alert through its lifecycle.
Request body — UpdateAlertRequest
| Field | Type | Default | Notes |
|---|---|---|---|
status |
string | — | Required. One of the AlertStatus values. Invalid → 400. |
notes |
string | "" |
Free-form analyst notes. |
resolved_by |
string | "" |
Identifier of the analyst or service account performing the transition. |
Valid AlertStatus values
Source of truth: libs/logster-common/logster_common/schemas/alerts.py.
The AlertStatus enum values are lowercase strings. The API
expects them lowercase on input and returns them lowercase in
responses.
[!NOTE] The API does not enforce a specific transition graph — any valid enum value is accepted from any starting state. Enforce your own workflow at the client or the reverse proxy if you need it.
Responses
200—AlertResponsereflecting the new state.400—{"detail": "Invalid status: <value>"}404— Alert not found.
Example
curl -X PATCH http://localhost:8080/alerts/6f0a8d3e-2b1c-4f6e-9a70-123456789abc \
-H 'Content-Type: application/json' \
-d '{"status":"investigating","notes":"Reviewing process tree","resolved_by":"alice"}'
POST /feedback
Record an analyst's true-positive / false-positive verdict on an
alert. Under the hood this is a thin wrapper that calls
store.update_status(...) with resolved or false_positive
depending on is_true_positive.
This is the canonical "ground truth" hook — in future Logster Support model releases, it will feed a retraining pipeline.
Request body — FeedbackRequest
| Field | Type | Default | Notes |
|---|---|---|---|
alert_id |
string | — | Required. |
is_true_positive |
bool | — | Required. true → status becomes resolved; false → false_positive. |
notes |
string | "" |
Analyst notes, stored on the alert. |
analyst |
string | "" |
Analyst identifier, stored as resolved_by. |
Response
200— Success.404— Alert not found.
Example
curl -X POST http://localhost:8080/feedback \
-H 'Content-Type: application/json' \
-d '{"alert_id":"6f0a8d3e-...","is_true_positive":false,"notes":"Dev workstation","analyst":"alice"}'
GET /endpoints
Aggregates all alerts by endpoint and returns one row per endpoint, regardless of status.
Query parameters
| Name | Type | Default | Notes |
|---|---|---|---|
tenant_id |
string | — | Restrict to a single tenant. |
Response — array of EndpointStatusResponse
| Field | Type | Notes |
|---|---|---|
endpoint_id |
string | Hostname (lowercased). |
tenant_id |
string | Tenant the endpoint belongs to. |
platform |
string | windows or linux. |
total_alerts |
int | All alerts ever seen for this endpoint. |
open_alerts |
int | Count where status == "open". |
last_alert_time |
float | Unix epoch of most recent alert, or null. |
[!CAUTION] This endpoint internally calls
store.list_alerts(..., limit=10000). Tenants with more than ~10,000 alerts in the store will have truncated summaries. Back the API with the Postgres store before relying on this at scale. See Admin Guide: Important Considerations.
Example
AlertResponse schema
Every single-alert response uses this shape. Source definition: services/api/src/logster_api/app.py.
| Field | Type | Notes |
|---|---|---|
alert_id |
string | UUID, primary key. |
tenant_id |
string | Tenant isolation key. |
endpoint_id |
string | Hostname (lowercased). |
severity |
string | low / medium / high / critical. Derived from attack_prob. Serialized as the enum's lowercase value. |
status |
string | Current AlertStatus (open, acknowledged, investigating, resolved, false_positive). Serialized as the enum's lowercase value. |
platform |
string | windows or linux. |
attack_prob |
float | Model probability of attack (0.0–1.0). |
confidence |
float | Model confidence. |
prediction |
string | Raw model label: attack / benign / error. |
ttp_techniques |
array of string | MITRE ATT&CK technique IDs (e.g. T1059.001). Empty if the TTP analyzer is not deployed. |
ttp_explanation |
string, nullable | Human-readable TTP description. |
inference_ids |
array of string | All inference results merged into this alert by dedup. |
related_endpoints |
array of string | Other endpoints that alerted within alerts.correlation_window_seconds. |
first_seen |
float | Unix epoch of first contributing inference. |
last_seen |
float | Unix epoch of most recent contributing inference. |
created_at |
float | Unix epoch when the alert was first opened. |
updated_at |
float | Unix epoch of last state change. |
analyst_notes |
string | Free-form notes attached via PATCH/feedback. |
resolved_by |
string, nullable | Identifier of the analyst or automation that most recently transitioned the alert. |
model_name |
string | Name of the model that produced the underlying inference. |
num_nodes |
int | Nodes in the GNN graph that produced the most recent inference. |
num_edges |
int | Edges in that graph. |
Severity derivation
attack_prob >= 0.95 → CRITICAL
attack_prob >= 0.85 → HIGH
attack_prob >= 0.70 → MEDIUM
attack_prob < 0.70 → LOW
This is enforced by the alerts service. alerts.min_threshold in
Admin Guide: Installation Parameters
controls whether LOW alerts ever reach the store at all.
Error shape
All error responses use FastAPI's standard shape:
Status codes
| Code | When |
|---|---|
200 |
Success. |
400 |
Invalid status on PATCH /alerts/{id}. |
404 |
Unknown alert_id. |
422 |
FastAPI automatic validation error. |
503 |
Alert store is not attached (misconfiguration). |