API Reference

Get a Threat Actor

Full dossier for one threat actor: description, origin, motivation, aliases, ATT&CK techniques, campaigns, related groups, ransomware tradecraft, and the CVEs it exploits, industries it targets and malware it uses.

Every claim carries the quote that supports it and the URL that quote came from. That citation is the point of this dataset — an analyst can follow any statement back to its source rather than taking the record on trust.

GET
/v1/actors/{name}

Cost: 1 credit per successful call

Path parameters

namestringrequired

Slug, alias, or display name — all three resolve, in that order. 1–120 characters, URL-encoded. Examples: safepay, Cozy%20Bear, APT29.

Request

curl https://api.precursorintelligence.com/functions/v1/actors/safepay \
  -H "Authorization: Bearer $PRECURSOR_API_KEY"

Response

Trimmed for length — techniques, campaigns, industries and malware are arrays of the same shape as the single entries shown.

200 OK
{
  "data": {
    "name": "SafePay",
    "slug": "safepay",
    "actor_type": "ransomware",
    "suspected_origin_country": "Unknown (Russian-speaking nexus suspected; the encryptor aborts on Cyrillic keyboard layouts)",
    "motivation": "financial",
    "description": "SafePay is a financially motivated ransomware operation first observed in September 2024 that grew rapidly through 2025...",
    "first_seen": "2024-09-01",
    "last_seen": "2025-07-01",
    "targeted_countries": ["US", "DE", "GB", "CA"],
    "tools": ["ShareFinder.ps1", "PsExec", "WinRAR", "FileZilla", "ScreenConnect"],
    "reference_links": [
      { "url": "https://www.bitdefender.com/en-us/blog/businessinsights/safepay-ransomware-attacks-ttps",
        "title": "SafePay Ransomware: How a Non-RaaS Group Executes Rapid Fire Attacks - Bitdefender" }
    ],
    "aliases": ["SafePay Ransomware", "safepay"],
    "counts": {
      "techniques": 168, "campaigns": 3, "cves": 2,
      "industries": 8, "malware": 4, "relationships": 3
    },
    "techniques": [
      {
        "technique_id": "T1001.003",
        "technique_name": "Protocol or Service Impersonation",
        "tactic": "Command And Control",
        "is_attack": true,
        "source_url": "https://www.ransomware.live/group/safepay",
        "evidence_quote": "Listed as a known TTP of safepay by ransomware.live"
      }
    ],
    "techniques_truncated": true,
    "campaigns": [
      {
        "name": "SafePay MSP campaign",
        "slug": "safepay-msp-campaign",
        "description": "Compromise of managed service providers to reach downstream customers.",
        "first_seen": "2025-01-01",
        "last_seen": "2025-06-01",
        "source_url": "https://www.acronis.com/en/tru/posts/safepay-ransomware-the-fast-rising-threat-targeting-msps/",
        "evidence_quote": "SafePay has increasingly targeted managed service providers..."
      }
    ],
    "relationships": [
      {
        "rel_type": "overlaps_with",
        "target_name": "LockBit",
        "target_slug": "lockbit",
        "source_url": "https://www.bitdefender.com/en-us/blog/businessinsights/safepay-ransomware-attacks-ttps",
        "evidence_quote": "Researchers have documented substantial overlap with the leaked LockBit 3.0 builder."
      }
    ],
    "ransomware": {
      "raas": false,
      "extortion_type": "double",
      "encryption": "AES wrapped in RSA",
      "initial_access": ["Valid accounts on exposed VPN/RDP", "Misconfigured FortiGate without MFA"],
      "notable_tools": ["ShareFinder.ps1", "PsExec", "WinRAR", "FileZilla"],
      "sanctioned": false
    },
    "cves": [
      {
        "cve_id": "CVE-2023-27997",
        "relation": "exploited",
        "evidence_quote": "FortiOS SSL VPN Heap Buffer Overflow CVE-2023-27997 Pre-authentication module vulnerability allows remote code execution through heap overflow exploitation",
        "source_url": "https://www.halcyon.ai/threat-group/safepay"
      }
    ],
    "industries": [
      {
        "name": "Manufacturing",
        "slug": "manufacturing",
        "relation": "targeted",
        "evidence_quote": "Manufacturing accounted for the largest share of SafePay victims...",
        "source_url": "https://www.checkpoint.com/cyber-hub/threat-prevention/ransomware/safepay-ransomware/"
      }
    ],
    "malware": [
      {
        "name": "SafePay locker",
        "malware_type": "ransomware",
        "relation": "uses",
        "evidence_quote": "The encryptor is a DLL executed via regsvr32/rundll32...",
        "source_url": "https://www.huntress.com/blog/its-not-safe-to-pay-safepay"
      }
    ],
    "query": "safepay",
    "matched_on": "slug",
    "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.namestringoptional

Canonical actor name.

data.slugstringoptional

Stable URL-safe identifier. Use this in subsequent calls.

data.idstringoptional

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

data.actor_typestringoptional

One of ransomware, apt, cybercrime, hacktivist, unknown.

data.actor_subtypestring | nulloptional

Finer classification where known, e.g. extortion-only.

data.suspected_origin_countrystring | nulloptional

Attributed origin. Free text, not an ISO code — it carries the hedging the source used ("Unknown (Russian-speaking nexus suspected…)").

data.motivationstring | nulloptional

e.g. financial, espionage, hacktivism.

data.mitre_attack_idstring | nulloptional

MITRE ATT&CK group id (e.g. G1054) when the actor is a named intrusion set. null for the majority, which ATT&CK does not name.

data.countsobjectoptional

True totals per category — techniques, campaigns, cves, industries, malware, relationships. Authoritative even when an array is truncated.

data.techniquesarrayoptional

Up to 100 techniques, ATT&CK-mapped ones first. Each has technique_id, technique_name, tactic, is_attack, source_url, evidence_quote.

data.techniques[].is_attackbooleanoptional

false marks a real observed behaviour that is not an ATT&CK technique — it has no ATT&CK id to pivot on and does not belong in a matrix.

data.techniques_truncatedbooleanoptional

true when more techniques exist than were returned. Compare against counts.techniques.

data.relationships[].target_slugstring | nulloptional

Non-null only when the related group has a dossier of its own — that is how you know which names are followable and which are plain text.

data.ransomwareobject | nulloptional

Present only for ransomware operations. Leak site, RaaS model, extortion type, encryption, initial access, notable tools, sanction status.

data.matched_onstringoptional

Which identifier resolved the lookup: slug, alias, or name.

data.merged_fromstring | nulloptional

Present only when {name} hit a merged actor's tombstone. The body is the surviving actor's; update your stored identifier to data.slug.

Notes on the data

  • Claims under review are included. The dataset marks each claim auto_published or in_review; both are returned, matching exactly what the Precursor Intelligence web app shows. Rejected claims are never returned. Internal confidence scores are not exposed.
  • Aliases resolve. Cozy Bear and APT29 return the same dossier.
  • Merged actors resolve through. A retired name returns the surviving actor's record plus merged_from, so a stale identifier still gets an answer in one call.

Errors

StatuserrorWhen
400missing_name, invalid_nameThe path segment is missing or failed validation.
401invalid_authorizationMissing or malformed Authorization header.
401unauthorizedInvalid/revoked key, or IP not allowlisted.
402insufficient_creditsOrganisation credit balance is below 1.
404not_foundThe path shape is wrong (e.g. /actors/a/b/c). Free — charged before billing.
405method_not_allowedOnly GET and OPTIONS are accepted.
500internalUnexpected server error (credit auto-refunded).
An unknown actor is a 200, not a 404

An unknown actor name is not a 404. A well-formed name that matches nothing returns 200 OK with data set to { "error": "not_found", "name": "…" }, and the credit is still charged — the call succeeded, it just found nothing. Check for data.error before reading data.name.

See Errors for the full error reference.