Documentation Index
Fetch the complete documentation index at: https://docs.exorde.io/llms.txt
Use this file to discover all available pages before exploring further.
Each recipe below is a working integration, not a sketch. Set EXORDE_API_KEY, paste the snippet, run.
The recipes lean on three core signal endpoints — see Trending, Narrative, and Alerts for the full envelopes powering each tile and event.
1. Newsroom — catch breaking stories before the wires
Goal: alert the news desk when a topic spikes outside its normal pattern.
Tier: Watch trial sufficient for global. See/Know required for cyber/finance/disinfo.
Endpoints: GET /v1/topics/{topic}/alerts, optional webhook subscription.
See Alerts for the full alert envelope, signal types, IOC schema, and webhook delivery details.
A real signal from this pipeline (2026-05-18, 6.67σ above 14-day baseline, validated by our LLM gate):
Multiple credible data breach disclosures (Turkish breach, FoxIT/Foxit software, gaming accounts) surfacing on dark web with fact-checker verification signals genuine cybersecurity incidents being reported and discussed across platforms.
import os, time, httpx
from datetime import datetime, timezone
BASE = "https://intel-v1.exorde.io"
HEADERS = {"X-API-Key": os.environ["EXORDE_API_KEY"]}
SEEN: set[str] = set()
def poll(topic: str = "global", hours: int = 168) -> list[dict]:
r = httpx.get(
f"{BASE}/v1/topics/{topic}/alerts",
params={"hours": hours, "limit": 50, "llm_validated": True},
headers=HEADERS,
timeout=10,
)
if r.status_code == 429:
time.sleep(int(r.headers.get("Retry-After", 5)))
return []
r.raise_for_status()
fresh = [a for a in r.json()["alerts"] if a["alert_id"] not in SEEN]
SEEN.update(a["alert_id"] for a in fresh)
return fresh
def slack_card(a: dict) -> dict:
sev = a["severity"]
spread = a["spread"]
text = (
f"*🚨 Volume spike on `{a['topic']}` — keyword `{a['keyword']}`*\n"
f"σ={sev['deviation_sigma']:.2f} "
f"current={sev['current_value']:.0f} "
f"baseline={sev['baseline_value']:.1f}\n"
f"Spread: {spread['domain_count']} domains, "
f"{spread['language_count']} languages\n\n"
f"_{a['description']}_"
)
return {
"text": f"*{a['keyword']}* — {a['description']}",
"blocks": [
{"type": "section", "text": {"type": "mrkdwn", "text": text}}
],
}
while True:
for a in poll("global"):
ts = datetime.now(timezone.utc).strftime("%H:%M:%S")
print(f"[{ts}] {a['keyword']:<25} σ={a['severity']['deviation_sigma']:.2f}")
# httpx.post(SLACK_WEBHOOK_URL, json=slack_card(a))
time.sleep(60)
Cost: 1,440 calls/day per topic. Comfortably inside Watch’s 5,000-call monthly budget for one topic; trivial on See’s 250,000 monthly budget across multiple topics.
Upgrade path: swap polling for a webhook subscription (See/Know) to get sub-second push delivery into Slack/Teams/PagerDuty without burning RPM.
2. Brand monitoring with watchlists
Goal: track every public mention of your brand, your domains, and your executives — across the whole conversation, not just one platform.
Tier: See or Know.
Endpoints: POST /v1/watchlists, GET /v1/watchlists/{id}/(trending|entities|platforms|posts|alerts). See Topics and watchlists for the full term-type reference.
import os, httpx
BASE = "https://intel-v1.exorde.io"
KEY = os.environ["EXORDE_API_KEY"]
HEADERS_JSON = {"X-API-Key": KEY, "Content-Type": "application/json"}
HEADERS_GET = {"X-API-Key": KEY}
# 1. Create the watchlist (one-time)
r = httpx.post(
f"{BASE}/v1/watchlists",
headers=HEADERS_JSON,
json={
"name": "acme-brand",
"base_topic": "global",
"terms": [
{"type": "keyword", "value": "acme"},
{"type": "keyword", "value": "acme corp"},
{"type": "domain", "value": "acme.com"},
{"type": "entity", "value": "jane doe"}, # CEO
{"type": "entity", "value": "john roe"}, # CFO
],
},
timeout=10,
)
r.raise_for_status()
wl_id = r.json()["id"]
print("created:", wl_id)
# 2. Daily snapshot — what's spiking, who's mentioned, where
def daily_snapshot(wl_id: str) -> None:
def g(path: str) -> dict:
return httpx.get(
f"{BASE}/v1/watchlists/{wl_id}{path}",
headers=HEADERS_GET,
timeout=10,
).json()
print("Top terms: ", [t["term"] for t in g("/trending")["terms"][:5]])
print("Top entities: ", [e["entity"] for e in g("/entities")["entities"][:5]])
print("Top platforms:", [p["platform"] for p in g("/platforms")["platforms"][:5]])
alerts = g("/alerts?hours=24")["alerts"]
if alerts:
print(f"!! {len(alerts)} brand alerts in last 24h")
daily_snapshot(wl_id)
Why watchlists beat keyword-only search: the Exorde pipeline already classifies entities and clusters posts by narrative. A watchlist runs the same pipeline filtered to your terms, so you get structured signal — entity leaderboards, platform breakdowns, narrative summaries — not a keyword feed.
3. Threat-intel desk — daily cyber alert digest
Goal: every morning, the analyst sees yesterday’s high-σ cyber events with IOCs extracted, sample posts, and matched cluster context.
Tier: See.
Endpoints: GET /v1/topics/cyber/alerts, GET /v1/topics/cyber/clusters/{id} for drill-down. Full alert envelope including the IOC schema lives in Alerts.
import os, httpx
from datetime import datetime, timezone
BASE = "https://intel-v1.exorde.io"
H = {"X-API-Key": os.environ["EXORDE_API_KEY"]}
def cyber_morning_digest() -> None:
r = httpx.get(
f"{BASE}/v1/topics/cyber/alerts",
params={"hours": 24, "limit": 50, "llm_validated": True},
headers=H,
timeout=10,
).json()
if not r["alerts"]:
print("no qualifying cyber alerts in last 24h")
return
today = datetime.now(timezone.utc).strftime("%Y-%m-%d")
print(f"=== Cyber digest, {today} ===")
for a in sorted(r["alerts"], key=lambda x: -x["severity"]["deviation_sigma"]):
sev = a["severity"]
iocs = a["iocs"]
ioc_summary: list[str] = []
for k in ("cves", "domains", "ips", "urls", "crypto_wallets"):
if iocs.get(k):
ioc_summary.append(f"{len(iocs[k])} {k}")
for h_alg in ("md5", "sha1", "sha256"):
if iocs["hashes"].get(h_alg):
ioc_summary.append(f"{len(iocs['hashes'][h_alg])} {h_alg}")
print(f"\n[{a['detected_at']}] σ={sev['deviation_sigma']:.2f} '{a['keyword']}'")
print(f" {a['description']}")
if a.get("matched_cluster"):
print(f" cluster: {a['matched_cluster']['cluster_title']}")
if ioc_summary:
print(f" IOCs: {', '.join(ioc_summary)}")
for cve in iocs.get("cves", [])[:3]:
print(f" - {cve}")
cyber_morning_digest()
Sample output, real run from 2026-05-18:
Cyber digest, 2026-05-19
[2026-05-18T04:00:30.148Z] σ=6.67 ‘dark web’
Multiple credible data breach disclosures (Turkish breach, FoxIT/Foxit software,
gaming accounts) surfacing on dark web with fact-checker verification…
cluster: Dark-web breach disclosures, May 2026
Drill-down: for any alert with a matched_cluster.cluster_id, fetch the full cluster context with GET /v1/topics/cyber/clusters/{id} (See tier) — top entities, top domains, time-series, full evidence post list.
Goal: catch coordinated narrative pushes before they reach mainstream amplification — multi-platform, multi-language synchronisation, LLM-validated.
Tier: See or Know.
Endpoints: GET /v1/topics/disinfo/alerts, GET /v1/topics/disinfo/narratives/history, GET /v1/topics/disinfo/platforms.
import os, httpx
BASE = "https://intel-v1.exorde.io"
H = {"X-API-Key": os.environ["EXORDE_API_KEY"]}
# 1. High-confidence disinfo alerts — LLM-validated, multi-language, multi-domain
r = httpx.get(
f"{BASE}/v1/topics/disinfo/alerts",
params={"hours": 168, "limit": 25},
headers=H,
timeout=10,
).json()
suspicious = [
a for a in r["alerts"]
if a.get("llm_validated")
and a["spread"]["language_count"] >= 3
and a["spread"]["domain_count"] >= 5
and a["confidence"] >= 0.7
]
print(f"{len(suspicious)} high-confidence multi-platform disinfo signals")
# 2. Cross-reference with cluster context where available
for a in suspicious[:5]:
sev = a["severity"]
spread = a["spread"]
print(f"\n- {a['keyword']} σ={sev['deviation_sigma']:.1f}")
print(f" spread: {spread['domain_count']} domains × {spread['language_count']} langs")
print(f" context: {a['description'][:200]}")
if a.get("matched_cluster"):
print(f" cluster: {a['matched_cluster']['cluster_title']}")
Operational tip: combine the disinfo signal with /narratives/history (See tier) to see whether the alert is part of a longer-running narrative pivot or a sudden burst. A campaign that’s been smouldering for two weeks behaves very differently from one that’s a 6-hour burst.
5. Executive dashboard — single-pane situational awareness
Goal: one page that shows, for every curated topic: latest narrative, top 3 trending terms, alert count last 24h, freshness.
Tier: See.
Endpoints: GET /v1/topics/{t}/(narrative|trending|alerts) × 4 topics.
See Trending and Narrative for the full response envelopes powering each tile.
import os, asyncio, httpx
from datetime import datetime, timezone
BASE = "https://intel-v1.exorde.io"
H = {"X-API-Key": os.environ["EXORDE_API_KEY"]}
TOPICS = ["global", "cyber", "finance", "disinfo"]
async def fetch(client: httpx.AsyncClient, topic: str) -> dict:
n, t, a = await asyncio.gather(
client.get(f"{BASE}/v1/topics/{topic}/narrative"),
client.get(f"{BASE}/v1/topics/{topic}/trending"),
client.get(f"{BASE}/v1/topics/{topic}/alerts?hours=24&limit=50"),
)
n_data, t_data, a_data = n.json(), t.json(), a.json()
return {
"topic": topic,
"narrative": n_data.get("summary", ""),
"top_terms": [x["term"] for x in t_data.get("terms", [])[:3]],
"alert_count": a_data.get("count", len(a_data.get("alerts", []))),
"freshness_seconds": n_data.get("data_freshness", {}).get("snapshot_age_seconds"),
}
async def main() -> None:
async with httpx.AsyncClient(headers=H, timeout=10) as client:
rows = await asyncio.gather(*[fetch(client, t) for t in TOPICS])
now = datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M UTC")
print(f"\n=== Exorde Intel — {now} ===\n")
for row in rows:
age_min = (row["freshness_seconds"] or 0) // 60
print(f"## {row['topic'].upper()} "
f"(snapshot {age_min}min ago, {row['alert_count']} alerts/24h)")
print(f" trending: {', '.join(row['top_terms'])}")
print(f" {row['narrative'][:240]}\n")
asyncio.run(main())
Cost: 12 API calls per refresh (3 endpoints × 4 topics). Refresh every minute = 12 calls/minute, comfortably inside See’s 120 RPM (10% utilisation) and a rounding error against See’s 250,000 monthly quota.
What to build next
| Pattern | Endpoints | Value |
|---|
| Backfill into a warehouse | /posts paginated, /narratives/history | Train your own models on the curated post stream |
| Custom topic for an enterprise | Email [email protected] with the desired scope | Know-tier private topic with bespoke baselines and tailored narrative voice |
| Multi-tenant SaaS layered on Exorde | One paid Know key, watchlist-per-tenant, your own quota plane | Resell intelligence to N customers from one contract |
| Design partner — narrative voice | Narrative is in alpha; tell us what shape your ideal output takes | Direct influence on the v1 contract, early access to tailoring features |
Reach out if you have a use case that doesn’t map cleanly onto these — most of our paid contracts started as a “can you do X” email.
Last reviewed: 2026-05-19. API version 1.2.8. All snippets tested against production.