Docs

Security Alerts

LogStitch detects suspicious patterns in your audit log stream in real-time. When event activity matches a detection rule, an alert fires automatically. Built-in rules cover common threats out of the box, and paid plans unlock custom rules and webhook delivery.

Overview#

Security alerts work inline during event ingestion. Every event is evaluated against all enabled rules as it arrives. Detection is fire-and-forget — it never blocks or delays event ingestion.

  1. An event is ingested via the API
  2. The detection engine checks the event against all enabled rules
  3. If the event matches a rule's action pattern, the engine increments a counter for the rule's group key (e.g. actor_id)
  4. If the counter exceeds the threshold within the sliding window, an alert fires
  5. If webhooks are configured, a signed POST is sent to each endpoint

Built-in Detection Rules#

LogStitch ships with six built-in detection rules. Five are enabled by default. You can toggle any rule on or off and adjust the cooldown period via the API.

IDNameAction PatternThresholdGroup BySeverityDefault
auth_brute_forceAuth Brute Forceauth.failed*5 in 5minactor_idhighOn
privilege_escalation_burstPrivilege Escalation Burst*.role.updated3 in 10minactor_idcriticalOn
rapid_api_key_creationRapid API Key Creation*.api_key.created3 in 5minactor_idmediumOn
bulk_data_exportBulk Data Export*.exported5 in 10minactor_idmediumOn
account_deletion_spikeAccount Deletion Spike*.deleted5 in 10mintenant_idhighOn
suspicious_ip_changeSuspicious IP Change*3 distinct IPs in 30minactor_idmediumOff

How Detection Works#

Action Pattern Matching#

Each rule has an action_pattern that uses glob-style matching against the event's action field:

  • * — matches all events
  • auth.failed* — matches auth.failed, auth.failed_mfa, etc.
  • *.deleted — matches user.deleted, document.deleted, etc.

Group-By Extraction#

The group_by field determines how matching events are grouped for counting. For example, grouping by actor_id means each actor has their own independent counter. A brute-force rule grouped by actor_id fires when a single actor exceeds the threshold, not when all actors combined do.

Sliding Window#

The engine uses a sliding time window. If threshold is 5 and window_seconds is 300 (5 minutes), the alert fires when 5 or more matching events from the same group arrive within any 5-minute window.

Cooldown#

After an alert fires for a given group key, the rule enters a cooldown period (default: 1 hour). During cooldown, matching events are still counted but no new alert fires for that group. This prevents alert fatigue from sustained attacks.

Managing Rules via API#

Use the Alerts API to list, toggle, and manage alert rules programmatically.

List all rules
curl https://logstitch.io/api/v1/alerts/rules \
  -H "Authorization: Bearer pk_..."
Disable a built-in rule
curl -X PATCH https://logstitch.io/api/v1/alerts/rules/auth_brute_force \
  -H "Authorization: Bearer mk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "enabled": false
  }'
Re-enable with custom cooldown
curl -X PATCH https://logstitch.io/api/v1/alerts/rules/auth_brute_force \
  -H "Authorization: Bearer mk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "enabled": true,
    "cooldown_seconds": 7200
  }'

Custom Alert Rules (Paid)#

Paid plan required

Custom alert rules are available on Pro and Enterprise plans. Free-tier projects can only use the built-in rules.

Custom rules let you define your own detection logic. Specify an action pattern, threshold, window, and severity to match your application's threat model.

Create a custom rule
curl -X POST https://logstitch.io/api/v1/alerts/rules \
  -H "Authorization: Bearer mk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Bulk invite spike",
    "action_pattern": "team.member.invited",
    "threshold": 10,
    "window_seconds": 600,
    "group_by": "tenant_id",
    "severity": "medium"
  }'
201Custom rule created
Response
{
  "rule": {
    "id": "550e8400-...",
    "type": "custom",
    "name": "Bulk invite spike",
    "action_pattern": "team.member.invited",
    "threshold": 10,
    "window_seconds": 600,
    "group_by": "tenant_id",
    "severity": "medium",
    "enabled": true,
    "cooldown_seconds": 3600,
    "created_at": "2026-01-20T14:00:00.000Z"
  },
  "request_id": "req_abc123"
}

Alert Lifecycle#

Every fired alert follows a three-state lifecycle:

  1. open — Alert has fired and requires attention
  2. acknowledged — A team member has seen the alert and is investigating
  3. resolved — The issue has been addressed

Transition alerts using the PATCH endpoint:

Acknowledge an alert
curl -X PATCH https://logstitch.io/api/v1/alerts/alt_01HX... \
  -H "Authorization: Bearer pk_..." \
  -H "Content-Type: application/json" \
  -d '{ "status": "acknowledged" }'
Resolve an alert
curl -X PATCH https://logstitch.io/api/v1/alerts/alt_01HX... \
  -H "Authorization: Bearer pk_..." \
  -H "Content-Type: application/json" \
  -d '{ "status": "resolved" }'

Webhooks (Paid)#

Paid plan required

Webhook delivery is available on Pro and Enterprise plans.

When an alert fires, LogStitch sends a signed HTTP POST to each enabled webhook endpoint. The payload includes the alert details and the rule that triggered it.

Webhook Payload#

Example webhook body
{
  "type": "alert.fired",
  "alert": {
    "id": "alt_01HX...",
    "rule_id": "auth_brute_force",
    "rule_name": "Auth Brute Force",
    "severity": "high",
    "status": "open",
    "group_key": "user_456",
    "event_count": 7,
    "sample_event_ids": ["evt_01HX...", "evt_01HX..."],
    "fired_at": "2026-01-20T15:30:00.000Z"
  },
  "project_id": "proj_01HX...",
  "timestamp": "2026-01-20T15:30:01.000Z"
}

Signature Verification#

Every webhook request includes an X-LogStitch-Signature header containing an HMAC-SHA256 signature of the request body, signed with the webhook secret. Always verify this signature before processing the payload.

Verify webhook signature (Node.js)
import { createHmac, timingSafeEqual } from 'crypto';

function verifyWebhookSignature(
  body: string,
  signature: string,
  secret: string,
): boolean {
  const expected = createHmac('sha256', secret)
    .update(body)
    .digest('hex');
  return timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected),
  );
}

// In your webhook handler:
const sig = req.headers['x-logstitch-signature'];
if (!verifyWebhookSignature(rawBody, sig, webhookSecret)) {
  return res.status(401).send('Invalid signature');
}

Retry Behavior#

If your endpoint returns a non-2xx status or times out (10 second limit), LogStitch retries up to 3 times with exponential backoff (30s, 120s, 480s). After all retries are exhausted, the delivery is marked as failed.

Dashboard#

Security alerts are also manageable from the LogStitch dashboard. The dashboard provides a visual interface for viewing fired alerts, toggling rules, and configuring webhooks. See the dashboard to get started.