CTI.FYI
API Reference
The CTI.FYI API mirrors the public ransomware group data gathered by the scraper. Use the interactive Swagger UI for testing or scroll through the summaries below to learn each endpoint, parameters, and returned fields.
Posts
GET
/api/v1/posts
Query every tracked post with optional group filtering, title search, date windows, and pagination.
| Parameter | Type | Description |
|---|---|---|
group | string | Case-insensitive name (e.g., akira) to limit posts. |
search | string | Substring search within post_title. |
since | date | Posts discovered on or after this date (YYYY-MM-DD). |
until | date | Posts discovered before this date (YYYY-MM-DD). |
limit | int | Items per page (default: 50, max: 500). |
offset | int | Skip the first N matches (default: 0). |
Each result includes post_title, group_name, discovery timestamp, post_url, and optional screenshot_path.
// GET /api/v1/posts?group=play&since=2026-03-01&limit=2
{
"count": 52,
"limit": 2,
"offset": 0,
"results": [
{...},
{...}
]
}
GET
/api/v1/posts/recent
Shortcut for the freshest posts without pagination metadata (returns the first limit items).
| Parameter | Type | Description |
|---|---|---|
limit | int | Number of posts to return (default: 50, max: 500). |
Groups
GET
/api/v1/groups
List tracked groups with location records, site status, parser flags, and a post_count summary.
| Parameter | Type | Description |
|---|---|---|
status | string | Filter locations by site_status (e.g., online). |
search | string | Substring match against group names. |
has_posts | bool | Only return groups with published posts. |
Each group includes locations (site URLs, availability, status), captcha, parser, and optional meta notes.
GET
/api/v1/groups/{name}
Details for a single group by name, optionally returning paginated posts.
| Parameter | Type | Description |
|---|---|---|
include_posts | bool | Embed posts for that group (default: true). |
limit | int | Posts per page (default: 50, max: 500). |
offset | int | Skip the first N posts (default: 0). |
Stats
GET
/api/v1/stats
Summary metadata from meta.json plus last_scrape_details with duration, groups attempted, and crawl highlights.
GET
/api/v1/stats/history
Ordered history of daily post totals. Results include date, total_posts, and per-group counts.
| Parameter | Type | Description |
|---|---|---|
days | int | Number of days to return (default: 30, max: 365). |
Admin & Health
POST
/api/v1/reload
Trigger an immediate data reload from disk. Requires X-API-Key header matching the RELOAD_API_KEY configured on the service.
GET
/api/v1/health
Lightweight health check: returns status, posts_loaded, and groups_loaded.
Static exports
Raw JSON and feeds served alongside the query endpoints. The API reads the same files.
/posts.json
Full array of posts (same fields as /api/v1/posts but unpaginated).
/groups.json
Group definitions, locations, site metadata, and parser flags.
/meta.json
Summary totals such as last_scrape, groups_total, and posts_last_7d.
/rss.xml
RSS feed of the 50 most recent posts.
/feeds.opml
OPML import for feed readers.
Usage notes
- GET endpoints are limited to 60 requests/minute per IP through the
slowapilimiter. - Data is refreshed automatically after each orchestrator scrape run (typically hourly).
- Responses that page results always include
count,limit,offset, and aresultslist. sinceanduntilexpect UTC dates with theYYYY-MM-DDformat.- Historical posts may have
post_urlorscreenshot_pathset tonull. - Report issues or integrations to ransom@cti.fyi.
Examples
cURL
curl "https://cti.fyi/api/v1/posts/recent?limit=10"
curl "https://cti.fyi/api/v1/groups?status=online&has_posts=true"
curl -X POST https://cti.fyi/api/v1/reload -H "X-API-Key: YOUR_KEY"
Python
import requests
resp = requests.get("https://cti.fyi/api/v1/posts", params={
"search": "hospital",
"limit": 100,
})
data = resp.json()
print(data["count"], "matches")