Skip to content

Build with the API / Weekly executive brief

Weekly executive brief

The week's top 10 threat clusters as a Markdown brief.

What you get

Pulls the ten highest-scoring threat clusters of the last 7 days and renders a Markdown brief: rank, title, score and urgency, a one-sentence summary, entity chips (actors, malware, CVEs, platforms...) and a link to each cluster. Saved to brief.md and printed.

Endpoints
/threats
Credits per run
1
Key
Works on the free key

Step by step

  1. 1. Get a key

    Sign in, open Settings, then API & Feeds, and select Generate API key. The key is shown once, so copy it. Every account has one and the free key covers this recipe.

    The ThreatCluster API page with the Get a free key button and the quick start, which begins with creating a key
    The API page. The key itself is created in Settings, under API & Feeds.
  2. 2. Download the script and set the key

    The script is one file with one dependency. It reads the key from the environment, so the key never goes into the file.

    curl -sO https://raw.githubusercontent.com/Jam0k/Cyber-Threat-Intelligence-API/main/examples/recipes/weekly-exec-brief.py
    pip install requests
    export THREATCLUSTER_API_KEY=tc_live_your_key_here
  3. 3. Run it

    The script writes brief.md to the current folder and prints it. It is the ten highest-scoring incidents of the last 7 days, each with a score, a two-sentence summary and a link.

    python3 weekly-exec-brief.py
    A terminal running the script, which reports it wrote brief.md and prints the start of the brief: a title and the first incident with its score and summary
    Run on 29 September 2026. The top incident that week was the F5 and Check Point zero-days, scored 83.
  4. 4. Read the brief

    The file is plain Markdown, so it renders in anything that reads Markdown: a wiki page, an email client, a pull request.

    The brief rendered as a document, with a title, three numbered incidents, their scores and urgency, short summaries, entity tags and links
    brief.md from the run above, rendered as HTML.
  5. 5. Send it every Monday

    Write the file where your wiki or mailer picks it up. The run costs one credit.

    # crontab -e, Mondays at 07:00
    0 7 * * 1 THREATCLUSTER_API_KEY=... /usr/bin/python3 /opt/tc/weekly-exec-brief.py --out /srv/wiki/security/brief.md

The code

weekly-exec-brief.py, 136 lines. Python 3, needs requests.

#!/usr/bin/env python3
"""weekly-exec-brief: the week's top 10 threat clusters as a Markdown brief.

What it does
  Pulls the ten highest-scoring threat clusters of the last 7 days and renders a Markdown
  brief: rank, title, score and urgency, a one-sentence summary, entity chips (actors,
  malware, CVEs, platforms...) and a link to each cluster. Saved to brief.md and printed.

Endpoints
  GET /threats?time_filter=7d&sort_by=threat_score&limit=10   (1 credit)

Cost: 1 credit per run. Works on the free tier.

Usage
  python3 weekly-exec-brief.py                # writes ./brief.md
  python3 weekly-exec-brief.py --out /tmp/brief.md
"""
import argparse
from datetime import datetime, timezone
import json
import os
import sys
import time

import requests

API_BASE = os.environ.get("THREATCLUSTER_API_BASE", "https://threatcluster.io/api/public/v1").rstrip("/")
API_KEY = os.environ.get("THREATCLUSTER_API_KEY", "")
SITE = os.environ.get("THREATCLUSTER_SITE", "https://threatcluster.io")  # where the linked pages live
PACE_SECONDS = 2.1  # free keys get 30 requests/min; ~28/min keeps loops clear of 429s
_credits = {"used": 0, "remaining": None}


def _auth_headers():
    # A tc_... key is sent as X-API-Key; anything else is a short-lived bearer (e.g. from `tc login`).
    if not API_KEY:
        sys.exit("THREATCLUSTER_API_KEY is not set. Free keys: https://threatcluster.io/about/api")
    if API_KEY.startswith("tc_"):
        return {"X-API-Key": API_KEY}
    return {"Authorization": "Bearer " + API_KEY}


def api_get(path, _allow=(), **params):
    """GET one endpoint. Exits non-zero with the API's own error body, unless the
    status is listed in _allow (per-item lookups where a 404 is itself an answer)."""
    r = requests.get(API_BASE + path, headers=_auth_headers(), params=params, timeout=60)
    if "X-Request-Cost" in r.headers:
        _credits["used"] += int(r.headers["X-Request-Cost"])
    if "X-RateLimit-Remaining" in r.headers:
        _credits["remaining"] = r.headers["X-RateLimit-Remaining"]
    if r.status_code >= 400 and r.status_code not in _allow:
        try:
            body = json.dumps(r.json())
        except ValueError:
            body = r.text[:500]
        sys.exit("HTTP %d from %s: %s" % (r.status_code, path, body))
    return r


def cluster_url(cluster):
    # The free payload carries `slug` (canonical page) and `cluster_id`; the last 8 hex
    # chars of the id also resolve, via a 301 to the slug, when slug is missing.
    ident = cluster.get("slug") or cluster.get("short_id") or cluster.get("cluster_id", "").replace("-", "")[-8:]
    return "%s/cluster/%s" % (SITE, ident)


def report_credits():
    # Stderr, so it never pollutes piped output (brief.md, blocklists, JSON).
    # Keys without a daily cap send no remaining-credits header.
    left = ", remaining today: %s" % _credits["remaining"] if _credits["remaining"] is not None else ""
    sys.stderr.write("[threatcluster] credits used this run: %d%s\n" % (_credits["used"], left))

CHIP_TYPES = ("apt_group", "ransomware_group", "malware", "campaign", "cve", "platform", "company", "country")


def first_sentence(text):
    text = (text or "").strip().replace("\n", " ")
    for stop in (". ", "! ", "? "):
        if stop in text:
            return text.split(stop, 1)[0] + stop.strip()
    return text


def chips(entities, max_chips=6):
    # One chip per type first (breadth), then fill the remaining slots.
    out = []
    ents = entities if isinstance(entities, dict) else {}
    for t in CHIP_TYPES:
        if ents.get(t):
            out.append("`%s: %s`" % (t, ents[t][0]))
    for t in CHIP_TYPES:
        for v in (ents.get(t) or [])[1:]:
            if len(out) >= max_chips:
                break
            out.append("`%s: %s`" % (t, v))
    return " ".join(out[:max_chips])


def main():
    ap = argparse.ArgumentParser(description="Top-10 weekly brief in Markdown")
    ap.add_argument("--out", default="brief.md", help="where to write the brief")
    args = ap.parse_args()

    data = api_get("/threats", time_filter="7d", sort_by="threat_score", limit=10).json()
    threats = data.get("threats", [])
    today = datetime.now(timezone.utc).strftime("%Y-%m-%d")

    md = ["# ThreatCluster weekly executive brief: week ending %s" % today, "",
          "Top %d threat clusters of the last 7 days, ranked by ThreatCluster threat score." % len(threats), ""]
    for i, t in enumerate(threats, 1):
        title = t.get("ai_title") or t.get("title") or "(untitled)"
        md.append("## %d. %s" % (i, title))
        md.append("**Score %.0f** · %s urgency · %s article(s) · latest activity %s"
                  % (t.get("threat_score") or 0, t.get("urgency_level") or "unknown",
                     t.get("article_count") or 0, (t.get("date_range_latest") or "")[:10]))
        md.append("")
        md.append(first_sentence(t.get("ai_summary")))
        md.append("")
        chip_line = chips(t.get("entities"))
        if chip_line:
            md.append(chip_line)
        md.append("[Read the cluster](%s)" % cluster_url(t))
        md.append("")
    md.append("---")
    md.append("Generated with the ThreatCluster public API (free tier, 7-day window).")
    text = "\n".join(md) + "\n"

    with open(args.out, "w", encoding="utf-8") as fh:
        fh.write(text)
    print(text, end="")
    sys.stderr.write("[weekly-exec-brief] wrote %s\n" % args.out)
    report_credits()


if __name__ == "__main__":
    main()

Output

From a run on 29 September 2026. Yours will differ as the corpus moves.

# ThreatCluster weekly executive brief: week ending 2026-09-29

Top 10 threat clusters of the last 7 days, ranked by ThreatCluster threat score.

## 1. Critical Zero-Day Exploits Target F5 and Check Point Products
**Score 83** · medium urgency · 4 article(s) · latest activity 2026-09-26

F5 Networks released emergency hotfixes for a critical zero-day vulnerability, CVE-2026-94127, in its BIG-IP Access Policy Manager on September 22, 2026, after confirming active exploitation.

`cve: CVE-2026-85102` `cve: CVE-2026-93616` `cve: CVE-2026-93952` `cve: CVE-2026-94127`
[Read the cluster](https://threatcluster.io/cluster/critical-zero-day-exploits-target-f5-and-check-point-product-87a87199)

## 2. Critical Zero-Day Vulnerability in F5 BIG-IP APM Exploited for Remote Code Execution
**Score 82** · medium urgency · 33 article(s) · latest activity 2026-09-22

F5 Networks has reported a critical vulnerability in its BIG-IP Access Policy Manager (APM), tracked as CVE-2026-94127, which is being actively exploited in the wild.

`campaign: BlueMoon Patch-Gap` `cve: CVE-2025-53521` `platform: Azure` `company: F5 Networks` `country: Qatar` `cve: CVE-2026-58138`
[Read the cluster](https://threatcluster.io/cluster/critical-rce-vulnerability-in-f5-big-ip-apm-exploited-4660d2ee)

## 3. Critical Citrix NetScaler Zero-Day Vulnerabilities Exploited
**Score 82** · medium urgency · 45 article(s) · latest activity 2026-09-28

Citrix disclosed two critical zero-day vulnerabilities, CVE-2026-88771 and CVE-2026-88772, affecting NetScaler ADC and Gateway systems, which are being actively exploited.

`apt_group: Earth Estries` `ransomware_group: Clop` `malware: Deed RAT` `campaign: Citrix Bleed One` `cve: CVE-2023-4966` `platform: Cisco Devices`
[Read the cluster](https://threatcluster.io/cluster/critical-citrix-netscaler-zero-day-exploitation-confirmed-4d8f6ff9)

## 4. Critical Zero-Day Vulnerabilities in Citrix NetScaler Under Active Exploitation
**Score 81** · medium urgency · 100 article(s) · latest activity 2026-09-26

On September 26, 2026, security firm watchTowr reported two unpatched zero-day vulnerabilities in Citrix NetScaler ADC and Gateway appliances, allowing remote code execution (RCE) and actively exploited in the wild.

`apt_group: Unc6240` `malware: Sideeye` `cve: CVE-2019-19781` `platform: Citrix NetScaler` `company: Citrix` `country: Israel`
[Read the cluster](https://threatcluster.io/cluster/active-exploitation-of-citrix-netscaler-zero-day-vulnerabili-bada67d1)

## 5. Massive Network of AI Proxy Servers Used for Malicious Activities Uncovered
**Score 81** · medium urgency · 5 article(s) · latest activity 2026-09-23

…

The file on GitHub: weekly-exec-brief.py.

Goes well with

All recipes: /build. Endpoint reference: /api/public/v1/docs.