Threat Events: the deduplicated occurrence layer.
This is the endpoint most integrations should start from. A Threat Event is a real-world occurrence, whether a specific breach, a specific exploitation campaign, or a specific leak, with every report describing it attached. Reporting repeats itself, so a report-per-item feed hands you six near-identical entries and leaves you to work out they are the same story. Here you read the occurrence once.
Requires the threat-events.read scope.
List Threat Events
GET /api/v1/threat-events/
curl "https://api.liberty91.com/api/v1/threat-events/?verification=corroborated&target_sector=Healthcare" \
-H "X-API-Key: $LIBERTY91_API_KEY"{
"next": "https://api.liberty91.com/api/v1/threat-events/?cursor=cD0yMDI2LTA3LTI5",
"previous": null,
"results": [
{
"id": "8f1a2b3c-4d5e-6f70-8192-a3b4c5d6e7f8",
"title": "Ransomware attack on a regional hospital group",
"summary": "...",
"event_class": "security-incident",
"event_type": "intrusions",
"verification": "corroborated",
"credibility": 2,
"credibility_label": "Probably True",
"occurred_start": "2026-07-18T00:00:00Z",
"occurred_end": null,
"first_reported_at": "2026-07-19T08:12:00Z",
"last_reported_at": "2026-07-24T16:03:00Z",
"sectors": ["healthcare"],
"regions": ["de", "western europe"],
"report_count": 4,
"source_count": 3,
"latest_source": "BleepingComputer",
"merged_into": null,
"created_at": "2026-07-19T08:20:00Z"
}
]
}Filters
| Filter | Meaning |
|---|---|
q | Free text over title and summary |
event_class, event_type | Taxonomy classification, see what happened |
verification | auto, corroborated, verified, disputed, rejected, merged |
min_credibility | 1 to 6; returns bands at least this good, so 2 gives you 1 and 2 |
source_count | 1, 2, 3+: how many independent sources reported it |
target_sector | Sector name or code |
target_country, source_country | Country name or ISO code: who was hit, and where the reporting came from |
technique | ATT&CK technique id, e.g. T1566 or T1566.001 |
occurred_after, occurred_before | When it happened (ISO 8601) |
last_reported_after, last_reported_before | When it was last written about |
relevant | true: only occurrences matched to your account |
organization | Organization UUID: only occurrences affecting that organization |
intel_requirement | Intelligence Requirement UUID |
An unrecognised filter value is a 400, not an empty list. A mistyped
sector returning zero results silently would read as "nothing in that sector",
which is the opposite of the truth.
Threat Event detail
GET /api/v1/threat-events/{id}/ adds the evidence.
{
"id": "8f1a2b3c-...",
"title": "Ransomware attack on a regional hospital group",
"credibility": 2,
"credibility_label": "Probably True",
"sources": [
{
"report_id": "1c2d3e4f-...",
"title": "Hospital group confirms ransomware incident",
"url": "https://example.test/report",
"source_name": "BleepingComputer",
"module": "Cyber news and reports",
"published_at": "2026-07-24T16:03:00Z",
"stance": "corroborates",
"reliability": "C",
"reliability_label": "Fairly reliable",
"event_id": "9a8b7c6d-..."
}
],
"actors": [{"id": "...", "name": "Qilin", "from_private_source": false}],
"malware": [],
"vulnerabilities": [],
"victims": [{"name": "Regional Hospital Group", "role": "victim"}],
"techniques": [
{"technique_id": "T1486", "name": "Data Encrypted for Impact",
"description": null, "from_private_source": false}
],
"organizations": [
{
"organization_id": "...",
"organization_name": "Acme Hospital",
"matched_sectors": ["Healthcare"],
"matched_regions": ["Germany"],
"matched_requirements": [
{"id": "...", "title": "Ransomware in healthcare", "priority": "HIGH", "scope": "ACCOUNT"}
],
"exposure": null
}
],
"organizations_truncated": false,
"intelligence_requirements": [...]
}event_id on a source is your copy of that report; pass it to
/events/{id}/ for your account's analysis of it. It is
null for a public report you have not been rendered a copy of.
What you can and cannot see
You see a Threat Event when you are entitled to at least one of the reports behind it, and you see only those reports.
This matters more than it sounds. A single occurrence can carry a public news article, a premium vendor report one customer licenses, and a report another customer uploaded themselves. All three contribute to the same occurrence. Each customer sees the occurrence plus the sources they hold, never anyone else's.
report_count and source_count are computed the same way, over only the
reports you can see. A count that included sources you are not entitled to
would tell you they exist, which is why it does not.
If you are entitled to an occurrence only through a report you uploaded or
licensed privately, the title you see is your own report's title. Once public
reporting names the occurrence, that public headline becomes the shared title
for everyone, including you.
Reading the trust signals
Three separate judgements travel with every occurrence. They answer different questions and should not be collapsed into one number.
Source reliability (reliability, A to F): who said it. A property of the
publisher, not of this occurrence. A is completely reliable, F means reliability
cannot be judged. Grades start from the source class (government, vendor, news)
and move on evidence.
Credibility (credibility, 1 to 6): how well-supported the claim is. Only
public, attributable reporting counts, and reports that are the same story
re-published are collapsed to one source.
| Band | Label | Read it as |
|---|---|---|
| 1 | Confirmed | Several reliable independent sources, actionable |
| 2 | Probably True | Independently corroborated, actionable |
| 3 | Possibly True | One moderate source, corroborate before acting |
| 4 | Doubtful | Weak or passing sourcing only |
| 5 | Improbable | Only unreliable-grade sourcing |
| 6 | Cannot be judged | No attributable sources |
Verification (verification): where the occurrence stands overall.
auto is machine-created from a single source; corroborated is reached
automatically at two independent sources; verified, disputed and rejected
are analyst judgements the automatic pipeline never overwrites. merged means
it was folded into another occurrence, and merged_into names it.
Stance is a property of each report, not the occurrence: whether that
source claims, corroborates, updates, mentions or disputes it.
Disagreement stays visible rather than being averaged away.
For a triage queue, ?verification=corroborated&min_credibility=2 is a good
starting filter: occurrences at least two independent sources agree on.
Relevance to your organizations
organizations[] answers why this matters to you, per organization, and it is
the field that turns a feed into a work queue. An occurrence surfaces for an
organization when it hits their sector, their region, something they
actually run (exposure), or a topic they follow
(matched_requirements). Each row says which.
# everything relevant to one organization
curl "https://api.liberty91.com/api/v1/threat-events/?organization=$ORG_ID" \
-H "X-API-Key: $LIBERTY91_API_KEY"IOCs and STIX
# indicators from the reporting you hold on this occurrence
curl ".../threat-events/$ID/iocs/" -H "X-API-Key: $KEY"
# a STIX 2.1 bundle carrying the occurrence AND its indicators, linked
curl ".../threat-events/$ID/iocs/export/" -H "X-API-Key: $KEY" -o bundle.json
# the occurrence, its sources and its entities as linked STIX objects
curl ".../threat-events/$ID/stix/" -H "X-API-Key: $KEY" -o event.jsonThese bundles are parented: they carry the occurrence itself plus relationships to each indicator, so a TIP keeps the context.
/stix/ additionally requires threats.read, because the bundle names the
threat actors and malware involved with their aliases and ATT&CK identifiers, which is
catalog data the threat library gates. The IOC
endpoints additionally require iocs.read. The flat
/iocs/export/?format=stix bundle is an indicator list with
no such context: right for a blocklist, wrong for MISP or OpenCTI.
Classifying what happened
event_class puts an occurrence on one of a few axes, and event_type
classifies within it. The security-incident types are the ENISA/TF-CSIRT RSIT
machine tags verbatim.
event_class | What it covers | Example event_type values |
|---|---|---|
security-incident | Something adverse happened to an identifiable victim | intrusions, availability, information-content-security, malicious-code, fraud, intrusion-attempts, information-gathering, vulnerable, abusive-content |
vulnerability | A vulnerability lifecycle event in a product, no named victim | disclosure, proof-of-concept, exploited-in-the-wild |
threat-development | Capability news with no victim | new malware or capability, actor tooling shifts |
data-exposure | Underground listings and leaks as artifacts | breach listing, credential dump |
A vulnerability with a named exploited victim is a security-incident, not a
vulnerability, because the axis is what happened in the world, not what the report
is about. The report's own document type is separate, and travels on the
report: see report_type on Events.
Frequently asked questions
What is the difference between /threat-events/ and /events/?
A Threat Event is the occurrence, one specific breach. An Event is one report about it. Six write-ups of the same breach are six Events and one Threat Event, and each Event names the Threat Event it belongs to.
Why can I see a Threat Event but only some of its sources?
You see the reports you are entitled to. A private source another customer licenses contributes to the occurrence but is masked out of your view of it, and never appears in your counts.
What do the credibility numbers mean?
They are the Admiralty information-credibility scale: 1 Confirmed, 2 Probably True, 3 Possibly True, 4 Doubtful, 5 Improbable, 6 Cannot be judged. Lower is better. Treat 1-2 as actionable and 3 as something to corroborate first.