> ## Documentation Index
> Fetch the complete documentation index at: https://docs.scrubbe.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Signals: How Scrubbe Ingests Alert Events

> Understand how Scrubbe ingests, normalizes, and routes signals from monitoring tools and internal systems into the incident intelligence pipeline.

A signal is a normalized event that enters Scrubbe from an internal or external source — a metric spike from Prometheus, an alert from Datadog, a deployment event from GitHub, or any raw event you send via the API. Signals are the raw material of incident detection. Scrubbe's intelligence layer (Ezra) correlates signals across services, assesses blast radius, and, when patterns match, promotes them into incident tickets automatically.

## Signal fields

When you ingest a signal, you provide the following fields:

| Field         | Required | Description                                                                                                            |
| ------------- | -------- | ---------------------------------------------------------------------------------------------------------------------- |
| `name`        | Yes      | Short label identifying the signal (e.g. `"High error rate on payments"`)                                              |
| `source`      | Yes      | Origin system: `PROMETHEUS`, `DATADOG`, `GRAFANA`, `GITHUB`, `GITLAB`, `PAGERDUTY`, `WEBHOOK`, `MANUAL`, or `INTERNAL` |
| `type`        | Yes      | Category of signal: `METRIC`, `ALERT`, `LOG`, `TRACE`, `DEPLOYMENT`, `CODE_CHANGE`, or `ANOMALY`                       |
| `severity`    | No       | `LOW`, `MEDIUM`, or `HIGH` — defaults to `LOW` if omitted                                                              |
| `description` | No       | Longer explanation of what the signal represents                                                                       |
| `serviceId`   | No       | ID of the service node this signal is associated with                                                                  |
| `value`       | No       | Free-form JSON payload containing the raw metric or event data                                                         |
| `metadata`    | No       | Additional context (e.g. labels, tags, alert rule name)                                                                |
| `triggeredAt` | No       | ISO 8601 timestamp of when the event occurred — defaults to the current time                                           |

## Ingesting a single signal

```http theme={null}
POST /api/v1/signals
```

```json theme={null}
{
  "name": "High error rate on payments",
  "source": "PROMETHEUS",
  "type": "METRIC",
  "severity": "HIGH",
  "description": "Error rate exceeded 5% for the last 3 minutes.",
  "serviceId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "value": { "errorRate": 0.07, "window": "3m" },
  "metadata": { "alertRule": "payments_error_rate", "labels": { "env": "production" } },
  "triggeredAt": "2026-05-22T14:00:00Z"
}
```

## Bulk ingestion

When you need to forward a batch of signals from a monitoring system or replay historical events, use the bulk endpoint. Send an array of signal objects under the `signals` key:

```http theme={null}
POST /api/v1/signals/bulk
```

```json theme={null}
{
  "signals": [
    {
      "name": "CPU spike on api-server-1",
      "source": "DATADOG",
      "type": "METRIC",
      "severity": "MEDIUM"
    },
    {
      "name": "Deployment of payments-service v2.4.1",
      "source": "GITHUB",
      "type": "DEPLOYMENT",
      "severity": "LOW"
    }
  ]
}
```

Duplicate signals are silently skipped, so bulk ingestion is safe to call repeatedly from your pipeline.

## Signal lifecycle

A signal moves through four states from ingestion to closure:

<Steps>
  <Step title="OPEN (active)">
    A newly ingested signal enters an active state. It is visible in the signal list and is available for correlation by Ezra. SLA and alerting rules evaluate active signals.
  </Step>

  <Step title="ACKNOWLEDGED">
    A team member has reviewed the signal and is aware of it. Acknowledging a signal suppresses repeat notifications but keeps the signal in scope for Ezra's correlation.

    ```http theme={null}
    PATCH /api/v1/signals/:id/acknowledge
    ```
  </Step>

  <Step title="RESOLVED">
    The condition that produced the signal has cleared. Resolving a signal records a `resolvedAt` timestamp.

    ```http theme={null}
    PATCH /api/v1/signals/:id/resolve
    ```

    <Note>You cannot resolve a signal that has already been resolved.</Note>
  </Step>

  <Step title="SUPPRESSED">
    The signal is known and expected — no further action or correlation is needed. Suppressed signals are excluded from Ezra's active pipeline.

    ```http theme={null}
    PATCH /api/v1/signals/:id/suppress
    ```
  </Step>
</Steps>

## Filtering signals

`GET /api/v1/signals` accepts query parameters to narrow results:

| Parameter   | Description                                                                 |
| ----------- | --------------------------------------------------------------------------- |
| `status`    | Filter by lifecycle state: `OPEN`, `ACKNOWLEDGED`, `RESOLVED`, `SUPPRESSED` |
| `severity`  | Filter by severity: `LOW`, `MEDIUM`, `HIGH`                                 |
| `source`    | Filter by source system (e.g. `PROMETHEUS`)                                 |
| `type`      | Filter by signal type (e.g. `METRIC`)                                       |
| `serviceId` | Filter to a specific service node                                           |
| `from`      | ISO 8601 start of the `triggeredAt` range                                   |
| `to`        | ISO 8601 end of the `triggeredAt` range                                     |
| `limit`     | Number of results to return (default: 50)                                   |
| `offset`    | Pagination offset                                                           |

## Signal stats

`GET /api/v1/signals/stats` returns a summary of signal activity for your organization:

```json theme={null}
{
  "total": 4821,
  "open": 12,
  "acknowledged": 5,
  "resolved": 4790,
  "suppressed": 14,
  "critical": 3,
  "bySeverity": [...],
  "bySource": [...]
}
```

Use this endpoint to build signal health dashboards or trigger external alerts when active critical signals accumulate.

## How signals become incidents

When Ezra receives a signal, it runs a four-stage reasoning pipeline: it assesses the situation, hypothesizes a root cause by correlating related signals and recent deployments, estimates blast radius, and selects a remediation option. If a matching playbook exists and guardrails allow, Scrubbe can promote the signal to an incident ticket automatically. If no playbook matches, the signal is promoted to an `OPEN` incident for your on-call team to handle.

The correlated signal IDs appear on the resulting incident ticket in the `correlatedSignalIds` field, giving you a full trace from raw event to incident.
