List Threat Actors
Tracked threat actors, ranked by how much corroborated evidence exists for each.
The ranking is a plain sum of the actor's evidence counts — techniques +
campaigns + CVEs + industries + malware — with no hidden weighting. Every
component is returned in counts, so you can see exactly what produced the
order and re-rank on whichever axis matters to you.
/v1/actorsCost: 1 credit per successful call
Query parameters
typestringoptionalFilter by actor type: ransomware, apt, cybercrime, hacktivist,
unknown. Omit for all types.
limitintegeroptional1–100. Defaults to 25.
industrystringoptionalIf present, the request is served by
Actors by Industry instead, and type
is ignored.
Request
curl "https://api.precursorintelligence.com/functions/v1/actors?type=ransomware&limit=5" \
-H "Authorization: Bearer $PRECURSOR_API_KEY"Response
{
"data": {
"count": 5,
"total": 388,
"limit": 5,
"actor_type": "ransomware",
"items": [
{
"id": "228233a4-d091-4214-baf7-f10db9aecda4",
"name": "SafePay",
"slug": "safepay",
"actor_type": "ransomware",
"suspected_origin_country": "Unknown (Russian-speaking nexus suspected; the encryptor aborts on Cyrillic keyboard layouts)",
"motivation": "financial",
"first_seen": "2024-09-01",
"last_seen": "2025-07-01",
"profile_updated_at": "2026-08-03T12:16:03.752Z",
"counts": {
"techniques": 168, "campaigns": 3, "cves": 2,
"industries": 8, "malware": 4
},
"evidence_total": 185
}
],
"generated_at": "2026-08-04T10:20:34.843Z"
},
"meta": {
"request_id": "8b16efb8-9a6c-4ace-b817-11cbee626d08",
"generated_at": "2026-08-04T10:20:34.843Z",
"credits": { "charged": 1, "remaining": 9998 }
}
}Response fields
data.countintegeroptionalNumber of actors returned in items.
data.totalintegeroptionalTotal actors matching the filter before limit was applied. Use it to tell
"that's everything" from "that's the first page".
data.actor_typestring | nulloptionalEcho of the type filter, or null when unfiltered.
data.items[].slugstringoptionalPass to Get Actor or Actor CVEs.
data.items[].idstringoptionalInternal UUID. Stable across renames, where slug is not — use it as the
join key if you mirror this data locally.
data.items[].countsobjectoptionalPer-category evidence totals for that actor.
data.items[].evidence_totalintegeroptionalThe sum that determined ranking position.
data.items[].profile_updated_atstring | nulloptionalWhen the actor's profile was last enriched.
Earlier releases ranked this endpoint by how often an actor's name appeared in scraped security blogs. That measured press coverage, not activity. Ranking is now evidence-based, and the payload fields changed with it — see the Changelog.
Errors
| Status | error | When |
|---|---|---|
| 400 | invalid_type | type contains characters outside [A-Za-z0-9 _-] or exceeds 40 characters. |
| 400 | invalid_limit | limit is non-numeric or outside 1–100. |
| 401 | invalid_authorization | Missing or malformed Authorization header. |
| 401 | unauthorized | Invalid/revoked key, or IP not allowlisted. |
| 402 | insufficient_credits | Organisation credit balance is below 1. |
| 405 | method_not_allowed | Only GET and OPTIONS are accepted. |
| 500 | internal | Unexpected server error (credit auto-refunded). |
A type that is well-formed but matches no actor returns 200 OK with an empty
items array and total: 0.
Validation errors are raised before billing, so a malformed request costs nothing.
See Errors for the full error reference.