Threat Actors API v2 Integration Guide
Overview
The Threat Actors API v2 integration connects your NINA workflows to the internal Threat Intelligence (TI) API for searching and retrieving threat-actor intelligence data (/ti/threat-actors).
It supersedes the original Threat Actors API integration with a new contract:
- No authentication — the service is reachable in-cluster
- Cursor-based pagination — pass the
cursor_valuefrom the previous response to retrieve the next page - Three operations — list with filters, lookup by STIX ID, and lookup by internal ID
- 17 filter dimensions — name, type, labels, IOCs, MITRE ATT&CK patterns, CVEs, CPEs, tools, malware, targeted sectors/countries/organizations/regions, and first/last-seen date ranges
This integration is intended for threat intelligence workflows running inside the cluster.
Status
The integration supports:
- List with filters: cursor-paginated list of threat actors with 17 filter dimensions
- Lookup by STIX ID: retrieve a single actor by its STIX identifier
- Lookup by Internal ID: retrieve a single actor by its internal database identifier
Credential Configuration
This integration requires no authentication — only a base URL for the TI service.
Authentication Method
| Field | Description | Example |
|---|---|---|
| Domain | TI API base URL | https://ti.internal.example.com |
How to obtain your Domain:
- Contact your organization's security administrator for in-cluster access
- Request the internal Threat Intelligence API domain
- Ensure network access to the service (internal)
Creating a Threat Actors API v2 Credential
- Navigate to the Credentials section in NINA
- Click Add New Credential
- Fill in the credential details:
- Name: A descriptive name (e.g., "TI API Production")
- Description: Optional details about the credential's purpose
- Integration Service: Select "Threat Actors API v2"
- Auth Type: "No Authentication" (automatically selected)
- Domain: Enter the TI API base URL (include
https://)
- Click Test Connection to verify the endpoint is reachable
- Click Save to store the credential
Supported Resources and Operations
Threat Actors
| Operation | Description |
|---|---|
List Threat Actors (getAll) | Cursor-paginated list with comprehensive filtering across 17 dimensions |
Get Threat Actor by STIX ID (getById) | Retrieve a single threat actor by its STIX identifier |
Get Threat Actor by Internal ID (getByInternalId) | Retrieve a single threat actor by its internal database identifier |
Parameter Merging
The Threat Actors API v2 integration uses NINA's standard parameter merging.
Parameter Sources (in order of precedence)
- Node Parameters: Parameters configured directly in the integration node
- Extracted Parameters: Parameters automatically extracted from the input data
- Input Data: The complete input data from upstream nodes
Pagination
The getAll operation uses cursor-based pagination, configured via the pagination object:
pagination.pageSize— number of items per page (1–100, default20; clamped if out of range)pagination.cursor— opaque cursor returned by the previous response ascursor_value. Omit on the first page; pass the previouscursor_valueto fetch the next page.
The getById and getByInternalId operations do not paginate.
Examples
List — Basic (First Page)
{
"integration_service": "threat-actors-api-v2",
"resource": "threat-actors",
"operation": "getAll",
"pagination": { "pageSize": 20 }
}
List — Fetching the Next Page
{
"integration_service": "threat-actors-api-v2",
"resource": "threat-actors",
"operation": "getAll",
"pagination": {
"pageSize": 20,
"cursor": "eyJwYWdlIjoyfQ=="
}
}
Filter by Name
{
"integration_service": "threat-actors-api-v2",
"resource": "threat-actors",
"operation": "getAll",
"filters": {
"nameEq": "APT29"
}
}
{
"integration_service": "threat-actors-api-v2",
"resource": "threat-actors",
"operation": "getAll",
"filters": {
"nameIn": ["APT29", "Cozy Bear", "Midnight Blizzard"]
}
}
Filter by Actor Type and Labels
{
"integration_service": "threat-actors-api-v2",
"resource": "threat-actors",
"operation": "getAll",
"filters": {
"actorTypesIn": ["Nation-State", "criminal"],
"labelsIn": ["ransomware", "espionage"]
}
}
Filter by IOCs
{
"integration_service": "threat-actors-api-v2",
"resource": "threat-actors",
"operation": "getAll",
"filters": {
"indicatorNameIn": [
"203.0.113.42",
"malicious-c2.example.com",
"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
]
}
}
Filter by MITRE ATT&CK Techniques
{
"integration_service": "threat-actors-api-v2",
"resource": "threat-actors",
"operation": "getAll",
"filters": {
"attackPatternMitreIdIn": ["T1566.001", "T1059.003", "T1055"]
}
}
Filter by Tools and Malware
{
"integration_service": "threat-actors-api-v2",
"resource": "threat-actors",
"operation": "getAll",
"filters": {
"toolsNameIn": ["Cobalt Strike", "PowerShell", "PsExec"],
"malwareNameIn": ["AkiraBot", "LaZagne"]
}
}
Filter by CVEs and Targeted CPEs
{
"integration_service": "threat-actors-api-v2",
"resource": "threat-actors",
"operation": "getAll",
"filters": {
"cvesNameIn": ["CVE-2024-40711", "CVE-2020-3259"],
"cvesCpesIn": ["fortinet", "cisco", "vmware"]
}
}
Filter by Targeted Sectors, Countries, and Regions
{
"integration_service": "threat-actors-api-v2",
"resource": "threat-actors",
"operation": "getAll",
"filters": {
"targetsSectorNameIn": ["Healthcare", "Finance"],
"targetsCountryNameIn": ["United States", "Germany"],
"targetsRegionNameIn": ["Europe", "North America"]
},
"pagination": { "pageSize": 25 }
}
Filter by First/Last Seen Date Range
{
"integration_service": "threat-actors-api-v2",
"resource": "threat-actors",
"operation": "getAll",
"filters": {
"firstSeenGte": "2024-01-01T00:00:00Z",
"lastSeenLte": "2024-12-31T23:59:59Z"
}
}
Combined Filters
{
"integration_service": "threat-actors-api-v2",
"resource": "threat-actors",
"operation": "getAll",
"filters": {
"nameIn": ["APT"],
"attackPatternMitreIdIn": ["T1059.003"],
"toolsNameIn": ["Cobalt Strike"],
"cvesNameIn": ["CVE-2021-26855"],
"targetsSectorNameIn": ["Technology", "Government"]
},
"pagination": { "pageSize": 50 }
}
Get by STIX ID
{
"integration_service": "threat-actors-api-v2",
"resource": "threat-actors",
"operation": "getById",
"stixId": "threat-actor--abc123"
}
The stixId is URL-path-encoded before the request is sent, so values containing reserved characters are handled safely.
Get by Internal ID
{
"integration_service": "threat-actors-api-v2",
"resource": "threat-actors",
"operation": "getByInternalId",
"internalId": "internal-999"
}
Response Structure
getAll — Paginated Envelope
{
"items": [ /* threat actor objects */ ],
"total": 1234,
"cursor_value": "<opaque string or null>"
}
items— array of threat-actor objectstotal— total number of matching records on the servercursor_value— opaque cursor for the next page; absent or empty when no more results
getById and getByInternalId
A single threat-actor object as returned by the TI API. Shapes follow the TI contract — treat unknown fields as opaque and forward them through your workflow.
Available Parameters
List Threat Actors (getAll)
Pagination
| Parameter | Type | Description | Required | Default |
|---|---|---|---|---|
pagination.cursor | string | Opaque cursor from a previous cursor_value | No | - |
pagination.pageSize | number | Results per page (1–100; clamped if out of range) | No | 20 |
Filters (all optional, all under filters)
| Parameter (UI) | API Name | Type | Description |
|---|---|---|---|
nameEq | name_eq | string | Exact threat-actor name match |
nameIn | name_in | array | Match any of the listed names |
actorTypesIn | actor_types_in | array | Match any of the listed actor types (e.g. Nation-State, criminal) |
labelsIn | labels_in | array | Match any of the listed labels |
indicatorNameIn | indicator_name_in | array | Match any of the listed IOC names (IPs, domains, hashes) |
attackPatternMitreIdIn | attack_pattern_mitre_id_in | array | Match any of the listed MITRE ATT&CK technique IDs |
cvesNameIn | cves_name_in | array | Match any of the listed CVE names |
cvesCpesIn | cves_cpes_in | array | Match any of the listed CPE identifiers of associated CVEs |
toolsNameIn | tools_name_in | array | Match any of the listed tool names |
malwareNameIn | malware_name_in | array | Match any of the listed malware names |
targetsSectorNameIn | targets_sector_name_in | array | Match any of the listed target sectors |
targetsCountryNameIn | targets_country_name_in | array | Match any of the listed target countries |
targetsOrganizationNameIn | targets_organization_name_in | array | Match any of the listed target organizations |
targetsRegionNameIn | targets_region_name_in | array | Match any of the listed target regions |
firstSeenGte | first_seen_gte | string | First-seen on or after this ISO 8601 date-time |
firstSeenLte | first_seen_lte | string | First-seen on or before this ISO 8601 date-time |
lastSeenGte | last_seen_gte | string | Last-seen on or after this ISO 8601 date-time |
lastSeenLte | last_seen_lte | string | Last-seen on or before this ISO 8601 date-time |
The UI accepts camelCase keys; the integration maps them to the API's snake_case query parameters internally.
Get Threat Actor by STIX ID (getById)
| Parameter | Type | Description | Required |
|---|---|---|---|
stixId | string | STIX identifier of the threat actor (e.g. threat-actor--abc123) | Yes |
Get Threat Actor by Internal ID (getByInternalId)
| Parameter | Type | Description | Required |
|---|---|---|---|
internalId | string | Internal database identifier of the threat actor | Yes |
Filter Behavior
- Omitted filters and empty arrays (
[]) are silently ignored — the filter is not applied. - Array filters use repeat-style query parameters: each element is sent as its own query value. Comma-joined strings are not parsed — pass actual arrays.
- Multiple filter keys are combined with AND logic — a threat actor must satisfy all specified filters to appear in results.
- Within a single array-valued filter, values are combined with OR logic (any match).
Best Practices
- Use specific filters to reduce result volume and improve performance.
- Paginate large queries with
pagination.cursorandpagination.pageSize; do not request a single large page. - Normalize IOC formats (IPs, domains, hashes) before querying with
indicatorNameIn. - Start broad (e.g.,
nameIn: ["APT"]) and refine with tactics/techniques and targeted-asset filters. - Prefer
getById/getByInternalIdwhen you already have an identifier — it is cheaper than a filteredgetAll.
Integration in Workflow Context
Common patterns:
-
IOC Attribution Alert Node → Script Node (extract IOCs) → Threat Actors v2 (
getAll,indicatorNameIn) → Enrichment Node → Slack/Email notification. -
CVE-to-Actor Pivot CVEs v2 (
vulnerability.list) → Script Node (collect CVE IDs) → Threat Actors v2 (getAll,cvesNameIn) → Report. -
Targeted-Sector Watchlist Schedule Node → Threat Actors v2 (
getAll,targetsSectorNameIn,firstSeenGte=<recent>) → Filter Node (new actors only) → Jira Integration Node (create tickets). -
Actor Profile Lookup Workflow Input Node → Threat Actors v2 (
getById) → Markdown Report Node.
Troubleshooting
| Issue | Resolution |
|---|---|
| Connection timeout / unreachable | Verify the Domain URL, that it includes https://, and that the worker has in-cluster access to the TI service. |
stixId is required | Provide a non-empty stixId for the getById operation. |
internalId is required | Provide a non-empty internalId for the getByInternalId operation. |
Empty items with non-empty filters | Filter values may be over-constraining. Try removing one filter at a time. Remember that omitted/empty arrays are no-ops. |
| Array filter not applied | Pass an actual JSON array, not a comma-separated string. The integration uses repeat-style query parameters. |
cursor_value keeps appearing | Pagination continues until cursor_value is empty or absent. Pass it back as pagination.cursor to fetch the next page. |
Upstream returned 4xx / 5xx | The integration surfaces the upstream status and body. Review the error for the specific reason (validation, not found, service down). |
| Slow responses on large pages | Reduce pagination.pageSize (max 100) and paginate via cursor instead. |
Updated: 2026-05-14