API Reference

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.

GET
/v1/actors

Cost: 1 credit per successful call

Query parameters

typestringoptional

Filter by actor type: ransomware, apt, cybercrime, hacktivist, unknown. Omit for all types.

limitintegeroptional

1–100. Defaults to 25.

industrystringoptional

If 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

200 OK
{
  "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.countintegeroptional

Number of actors returned in items.

data.totalintegeroptional

Total actors matching the filter before limit was applied. Use it to tell "that's everything" from "that's the first page".

data.actor_typestring | nulloptional

Echo of the type filter, or null when unfiltered.

data.items[].slugstringoptional

Pass to Get Actor or Actor CVEs.

data.items[].idstringoptional

Internal UUID. Stable across renames, where slug is not — use it as the join key if you mirror this data locally.

data.items[].countsobjectoptional

Per-category evidence totals for that actor.

data.items[].evidence_totalintegeroptional

The sum that determined ranking position.

data.items[].profile_updated_atstring | nulloptional

When the actor's profile was last enriched.

Ranking changed in v1.2.0

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

StatuserrorWhen
400invalid_typetype contains characters outside [A-Za-z0-9 _-] or exceeds 40 characters.
400invalid_limitlimit is non-numeric or outside 1–100.
401invalid_authorizationMissing or malformed Authorization header.
401unauthorizedInvalid/revoked key, or IP not allowlisted.
402insufficient_creditsOrganisation credit balance is below 1.
405method_not_allowedOnly GET and OPTIONS are accepted.
500internalUnexpected 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.