Security Events
Broad published security-event registry feed and its relation to the promoted events feed.
GET /v1/security-events
List the broad published security-event registry feed. Items that affect the tracked universe can also be promoted into /v1/events.
A row is published either by an editor (published_by: "admin") or by the auto-publish pass that runs after every registry poll (published_by: "auto"): a draft that touches the tracked universe, or is linked to a casebook entry with a USD loss, is published automatically. The feed always has published_only semantics: draft, dismissed, removed, purged and retracted rows are excluded. The auto-publish pass processes a bounded batch (50 per poll); publication or promotion failures and a backlog can delay appearance. A successful empty response means no published rows match, not that no source incidents exist. Registry ids are integers; loss-board ids are strings. This documents the existing publication policy; it does not enable a new source-wide auto-publish rule.
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
| page | number | 1 | Page number (values beyond 10000 answer an empty page) |
| limit | number | 50 | Results per page, max 100 |
| source | string | - | Registry source |
| affectsTrackedUniverse | string | - | true to return only in-universe events |
| published_by | string | - | admin or auto: how the row was published |
| chainId | number | - | Chain ID |
| severity | string | - | Info, Warning or Critical; with hasLoss=true, use loss-board severity |
| search | string | - | Search title and description (terms over 200 characters answer an empty page) |
| sort | string | - | loss orders by loss amount; anything else by attackedAt |
| hasLoss | string | - | true returns the loss board instead (see GET /v1/security-events/losses) |
Example
curl "https://api.philidor.io/v1/security-events?affectsTrackedUniverse=true&limit=5"Response
{
"data": [
{
"id": 101,
"source": "thatsrekt",
"sourceId": "rekt-101",
"chainId": 1,
"chainSlug": "ethereum",
"title": "Security event",
"description": "Published registry item",
"attackers": [],
"victims": [],
"netScore": 12,
"confirmations": 3,
"disconfirmations": 0,
"lossAmountUsd": null,
"severity": "Warning",
"txHash": "0x...",
"nativeUrl": "https://example.com/event",
"links": [],
"affectsTrackedUniverse": true,
"attackedAt": "2026-07-01T12:00:00Z",
"promotedEventId": 42
}
],
"meta": {
"page": 1,
"limit": 5,
"hasMore": false
}
}GET /v1/security-events/losses
The loss board: one row per incident with a positive USD loss (DeFiLlama is the coverage baseline; other casebook sources enrich rows but never add to the headline), plus coverage metadata. GET /v1/security-events?hasLoss=true returns the same body; this route is the documented address. Row ids are strings such as rekt:defillama:ether-fi-liquid-1789084800.
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
| page | number | 1 | Page number; beyond 10000 returns an empty page |
| limit | number | 50 | Results per page, max 100 |
| source | string | - | Only defillama is a loss-board source |
| chainId | number | - | Chain ID |
| severity | string | - | low, medium, high or critical; unknown values return an empty page |
| search | string | - | Search labels, source ids, causal summaries and case metadata; max 200 characters |
| sort | string | - | loss orders by loss amount; anything else by date |
Response
{
"data": [
{
"id": "rekt:defillama:ether-fi-liquid-1789084800",
"title": "…",
"lossAmountUsd": 12000000,
"attackedAt": "2026-09-10T00:00:00Z"
}
],
"meta": {
"page": 1,
"limit": 50,
"hasMore": true,
"total": 1215,
"totalLossUsd": 9500000000,
"coverageSource": "DeFiLlama",
"coverageTotal": 2328,
"coverageTotalLossUsd": 14000000000,
"coverageRefreshedAt": "2026-09-11T06:00:00Z",
"evidenceCoveredIncidents": 900,
"transactionCoveredIncidents": 600,
"evidenceRefreshedAt": "2026-09-11T06:00:00Z"
}
}The coverage* and evidence* fields describe the whole corpus, not the page. Invalid enum filters, search terms over 200 characters, source names over 64 characters and pages beyond 10000 return an empty page without executing a case search or page offset; global coverage is still returned. Unknown sort values retain chronological ordering. affectsTrackedUniverse=true restricts to covered-universe incidents; minLossUsd accepts a nonnegative USD threshold (invalid values are ignored).
Loss severity uses the casebook taxonomy: low below $1M, medium from $1M, high from $10M and critical from $50M for DeFiLlama cases. The filter matches the case severity, falling back to published registry severity and then Info when absent. Legacy Info, Warning and Critical filters remain accepted; comparison ignores case, so Critical also matches critical. Info and Warning do not group the native loss tiers. Returned severity values retain their source labels. The same rules apply to ?hasLoss=true.
Loss cases are public source records, independently of the security registry publication gate. Only source-active positive-loss DeFiLlama cases are included; human-verified contamination exclusions are omitted. Joined registry details must be published and not removed, purged or retracted. Unmapped cases use chainId: 0 and chainSlug: "unmapped". The OpenAPI schema declares the row fields, including classification, technique, mechanism, chains, returnedFundsUsd, protocol metadata and incidentDossier (evidence, provenance and coverage). Nullable fields indicate unavailable information.
The host health monitor polls the unfiltered registry, loss board and critical-incidents vault list. A valid empty list lasting more than 24 hours triggers an alert; a nonempty response resets that window. HTTP errors and malformed responses alert independently. Monitor activation and live verification belong to the host release gate.