Get Started with the Investigations v2 GraphQL API🔗
Important
Before proceeding, complete the API Authentication steps in order to obtain a working client_id
and client_secret
.
Regions
The URL to access XDR APIs may differ according to the region your environment is deployed in:
- US1—
https://api.ctpx.secureworks.com
- US2—
https://api.delta.taegis.secureworks.com
- US3—
https://api.foxtrot.taegis.secureworks.com
- EU—
https://api.echo.taegis.secureworks.com
The examples in this XDR API documentation use https://api.ctpx.secureworks.com
throughout. If you are in a different region substitute appropriately.
Create an Investigation🔗
Mutation🔗
mutation createInvestigationV2($input: CreateInvestigationInput!) {
createInvestigationV2(input: $input) {
id
shortId
title
keyFindings
priority
type
status
contributorIds
assigneeId
tenantId
createdById
createdAt
updatedById
updatedAt
processingStatus {
alerts
events
assets
}
}
}
Variables🔗
{
"input": {
"title": "My Example Investigation",
"assigneeId": "<assignee_user_id>",
"status": "OPEN",
"keyFindings": "Example Key Findings",
"priority": 2,
"type": "SECURITY_INVESTIGATION"
}
}
Example Curl🔗
curl --request POST \
--url <Environment Specific URL/Endpoint> \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--header 'X-Tenant-Context: <tenant id>' \
--data '{"query":"mutation createInvestigationV2($input: CreateInvestigationInput!) {\n\tcreateInvestigationV2(input: $input) {\n\t\tid\n\t\tshortId\n\t\ttitle\n\t\tkeyFindings\n\t\tpriority\n\t\ttype\n\t\tstatus\n\t\tcontributorIds\n\t\tassigneeId\n\t\ttenantId\n\t\tcreatedById\n\t\tcreatedAt\n\t\tupdatedById\n\t\tupdatedAt\n\t\tprocessingStatus {\n\t\t\talerts\n\t\t\tevents\n\t\t\tassets\n\t\t}\n\t}\n}\n","operationName":"createInvestigationV2","variables":{"input":{"title":"My Example Investigation","assigneeId":"<assignee_user_id>","status":"OPEN","keyFindings":"Example Key Findings","priority":2,"type":"SECURITY_INVESTIGATION"}}}'
Notes🔗
- Investigation assignment can be set to either a specific user or a group mention such as
@customer
or@secureworks
. - Setting the status to
AWAITING_ACTION
with a user other than the person or client creating the investigation will trigger an email to be sent to that user or group. - The create investigation call also allows callers to attach evidence in one request using the
alerts
,events
, andalertsSearchQueries
fields.- The
alertsSearchQueries
field accepts a CQL search to append alerts to an investigation in bulk. - If attaching evidence in the create call, the
processingStatus
fields will be updated and subsequent queries for the investigation will return the updated status as evidence processing finishes.
- The
Update an Investigation🔗
Mutation🔗
mutation updateInvestigationV2($input: UpdateInvestigationV2Input!) {
updateInvestigationV2(input: $input) {
id
shortId
title
keyFindings
priority
type
status
contributorIds
assigneeId
tenantId
createdById
createdAt
updatedById
updatedAt
processingStatus {
alerts
events
assets
}
}
}
Variables🔗
{
"input": {
"id": "<investigation_id>",
"title": "My Updated Example Investigation",
"assigneeId": "@customer",
"status": "AWAITING_ACTION",
"keyFindings": "Updated Example Key Findings"
}
}
Example Curl🔗
curl --request POST \
--url <Environment Specific URL/Endpoint> \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--header 'X-Tenant-Context: <tenant id>' \
--data '{"query":"mutation updateInvestigationV2(\n\t$input: UpdateInvestigationV2Input!\n) {\n\tone: updateInvestigationV2(input: $input) {\n\t\tid\n\t\ttitle\n\t\tassigneeId\n\t\tstatus\n\t}\n}\n","operationName":"updateInvestigationV2","variables":{"input":{"id": "<investigation_id>", "title":"My Updated Example Investigation","assigneeId":"@customer","status":"AWAITING_ACTION","keyFindings":"Updated Example Key Findings"}}}'
Notes🔗
- Updating an investigation through GraphQL works similarly to a RESTful PATCH update; if a field is null or not sent, it will be ignored and not updated. So, only the fields that need to be changed need to be sent.
- There are some fields that cannot be made empty or null, such as
type
,assigneeId
,priority
, and others; the API will reject the request in cases where that is attempted.
- There are some fields that cannot be made empty or null, such as
- Setting the status to
AWAITING_ACTION
with a user other than the person or client that is updating the investigation or that is currently set as the assignee will trigger an email to be sent to that user or group.- If the assignee changes but the status remains
AWAITING_ACTION
, an email will still be sent; an email will not be sent if the status changes fromAWAITING_ACTION
.
- If the assignee changes but the status remains
Add Additional Evidence to an Investigation🔗
Mutation🔗
mutation addEvidenceToInvestigation($input: AddEvidenceToInvestigationInput!) {
addEvidenceToInvestigation(input: $input) {
investigationId
alerts
events
alertsSearchQuery
searchQueries
}
}
Variables🔗
{
"input": {
"investigationId": "<investigation_id>",
"alerts": [
"alert://priv:stolen-user-credentials:11772:1723482198701:9640c014-cd59-448d-b47d-aa8e8e3747fe",
"alert://priv:stolen-user-credentials:11772:1723473198181:4c919a6b-0eee-4876-9d34-7cdbb5afe48b"
],
"events": [
"event://priv:scwx.auth:11772:1708626661995:422496f6-a491-4983-af90-020a4b46a0e8"
]
}
}
Example Curl🔗
curl --request POST \
--url <Environment Specific URL/Endpoint> \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--header 'X-Tenant-Context: <tenant id>' \
--data '{"query":"mutation addEvidenceToInvestigation($input: AddEvidenceToInvestigationInput!) {\n\taddEvidenceToInvestigation(input: $input) {\n\t\tinvestigationId\n\t\talerts\n\t\tevents\n\t\talertsSearchQuery\n\t\tsearchQueries\n\t}\n}\n","operationName":"addEvidenceToInvestigation","variables":{"input":{"investigationId":"4697e8fb-44f1-4221-951c-309b14f1f1aa","alerts":["alert://priv:stolen-user-credentials:11772:1723482198701:9640c014-cd59-448d-b47d-aa8e8e3747fe","alert://priv:stolen-user-credentials:11772:1723473198181:4c919a6b-0eee-4876-9d34-7cdbb5afe48b"],"events":["event://priv:scwx.auth:11772:1708626661995:422496f6-a491-4983-af90-020a4b46a0e8"]}}}'
Notes🔗
- Adding evidence is an asynchronous operation, the accepted IDs will be returned.
- The evidence
processingStatus
can be retrieved with a query requesting the investigation.
Remove Evidence from an Investigation🔗
Mutation🔗
mutation removeEvidenceFromInvestigation($input: RemoveEvidenceFromInvestigationInput!) {
removeEvidenceFromInvestigation(input: $input) {
investigationId
alerts
events
assets
}
}
Variables🔗
{
"input": {
"investigationId": "<investigation_id>",
"alerts": [
"alert://priv:stolen-user-credentials:11772:1723482198701:9640c014-cd59-448d-b47d-aa8e8e3747fe",
"alert://priv:stolen-user-credentials:11772:1723473198181:4c919a6b-0eee-4876-9d34-7cdbb5afe48b"
],
"events": [
"event://priv:scwx.auth:11772:1708626661995:422496f6-a491-4983-af90-020a4b46a0e8"
]
}
}
Example Curl🔗
curl --request POST \
--url <Environment Specific URL/Endpoint> \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--header 'X-Tenant-Context: <tenant id>' \
--data '{"query":"mutation removeEvidenceFromInvestigation($input: RemoveEvidenceFromInvestigationInput!) {\n\tremoveEvidenceFromInvestigation(input: $input) {\n\t\tinvestigationId\n\t\talerts\n\t\tevents\n\t\tassets\n\t}\n}\n","operationName":"removeEvidenceFromInvestigation","variables":{"input":{"investigationId":"<investigation_id>","alerts":["alert://priv:stolen-user-credentials:11772:1723482198701:9640c014-cd59-448d-b47d-aa8e8e3747fe","alert://priv:stolen-user-credentials:11772:1723473198181:4c919a6b-0eee-4876-9d34-7cdbb5afe48b"],"events":["event://priv:scwx.auth:11772:1708626661995:422496f6-a491-4983-af90-020a4b46a0e8"]}}}'
Notes🔗
- Removing evidence is an asynchronous operation, the accepted ids will be returned.
- The evidence
processingStatus
can be retrieved with a query requesting the investigation. - Removing an alert will not remove related evidence.
- Events and assets added because they were related to the alert will need to be removed separately. Similarly if removing an asset or event, the other related evidence will need to be manually removed.
Close an Investigation🔗
Mutation🔗
mutation closeInvestigation($input: CloseInvestigationInput!) {
closeInvestigation(input: $input) {
id
title
status
closeReason
}
}
Variables🔗
{
"input": {
"id": "<investigation_id>",
"reason": "Example reason for closing this investigation",
"status": "CLOSED_NOT_VULNERABLE",
"alertsResolutionStatus": "NOT_ACTIONABLE"
}
}
Example Curl🔗
curl --request POST \
--url <Environment Specific URL/Endpoint> \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--header 'X-Tenant-Context: <tenant id>' \
--data '{"query":"mutation closeInvestigation($input: CloseInvestigationInput!) {\n\tcloseInvestigation(input: $input) {\n\t\tid\n\t\ttitle\n\t\tstatus\n\t\tcloseReason\n\t}\n}\n","operationName":"closeInvestigation","variables":{"input":{"id":"<investigation_id>","reason":"Example reason for closing this investigation","status":"CLOSED_NOT_VULNERABLE","alertsResolutionStatus":"NOT_ACTIONABLE"}}}'
Notes🔗
- When closing an investigation that has alerts, an
alertsResolutionStatus
is required and all associated alerts will have their status updated. - The close
reason
will be set on both the investigation and on every alert that is closed by this operation. - While closing the investigation is immediate, updating the associated alerts is an asynchronous operation.
- The evidence
processingStatus
can be retrieved with a query requesting the investigation.
Archive Investigations🔗
Mutation🔗
mutation archiveInvestigationsV2($input: ArchiveInvestigationsInput!) {
archiveInvestigationsV2(input: $input) {
ids
}
}
Variables🔗
Example Curl🔗
curl --request POST \
--url <Environment Specific URL/Endpoint> \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--header 'X-Tenant-Context: <tenant id>' \
--data '{"query":"mutation archiveInvestigationsV2($input: ArchiveInvestigationsInput!) {\n\tarchiveInvestigationsV2(input: $input) {\n\t\tids\n\t}\n}","operationName":"archiveInvestigationsV2","variables":{"input":{"ids":["<investigation_id_1>","<investigation_id_2>"]}}}'
Notes🔗
- Only closed investigations can be archived.
- If there is an issue archiving an investigation (e.g., not closed, doesn't exist) the API will still archive the ones it can and return errors for the others.
- There is also an
archiveInvestigationV2
mutation that can be used to archive just one investigation and receive the full investigation as a response.
Unarchive Investigations🔗
Mutation🔗
mutation unarchiveInvestigationV2($input: UnarchiveInvestigationInput!) {
unarchiveInvestigationV2(input: $input) {
ids
}
}
Variables🔗
Example Curl🔗
curl --request POST \
--url <Environment Specific URL/Endpoint> \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--header 'X-Tenant-Context: <tenant id>' \
--data '{"query":"mutation unarchiveInvestigationV2($input: UnarchiveInvestigationInput!) {\n\tunarchiveInvestigationV2(input: $input) {\n\t\tids\n\t}\n}","operationName":"unarchiveInvestigationV2","variables":{"input":{"ids":["<investigation_id_1>","<investigation_id_2>"]}}}'
Notes🔗
- If there is an issue unarchiving an investigation (e.g., doesn't exist) the API will still unarchive the ones it can and return errors for the others.
- There is also an
unarchiveInvestigationV2
mutation that can be used to unarchive just one investigation and receive the full investigation as a response.
Query for an Investigation by ID🔗
Query🔗
query investigationV2($arguments: InvestigationV2Arguments!) {
investigationV2(arguments: $arguments) {
id
shortId
title
keyFindings
priority
type
status
contributorIds
assigneeId
tenantId
createdById
createdAt
updatedById
updatedAt
processingStatus {
alerts
events
assets
}
}
}
Variables🔗
Example Curl🔗
curl --request POST \
--url <Environment Specific URL/Endpoint> \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--header 'X-Tenant-Context: <tenant id>' \
--data '{"query":"query investigationV2($arguments: InvestigationV2Arguments!) {\n\tinvestigationV2(arguments: $arguments) {\n\t\tid\n\t\tshortId\n\t\ttitle\n\t\tkeyFindings\n\t\tpriority\n\t\ttype\n\t\tstatus\n\t\tcontributorIds\n\t\tassigneeId\n\t\ttenantId\n\t\tcreatedById\n\t\tcreatedAt\n\t\tupdatedById\n\t\tupdatedAt\n\t\tprocessingStatus {\n\t\t\talerts\n\t\t\tevents\n\t\t\tassets\n\t\t}\n\t}\n}\n","operationName":"investigationV2","variables":{"arguments":{"id":"<investigation_id>"}}}'
Search Investigations🔗
Query🔗
query investigationsV2($arguments: InvestigationsV2Arguments!) {
investigationsV2(arguments: $arguments) {
investigations {
id
shortId
title
keyFindings
priority
type
status
contributorIds
assigneeId
tenantId
createdById
createdAt
updatedById
updatedAt
processingStatus {
alerts
events
assets
}
}
totalCount
}
}
Variables🔗
{
"arguments": {
"cql": "status IN ('Open', 'Awaiting Action') and createdAt >= '2024-07-19T21:55:28.163531Z' | sort by createdAt asc",
"page": 1,
"perPage": 100
}
}
Example Curl🔗
curl --request POST \
--url <Environment Specific URL/Endpoint> \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--header 'X-Tenant-Context: <tenant id>' \
--data '{"query":"query investigationsV2($arguments: InvestigationsV2Arguments!) {\n\tinvestigationsV2(arguments: $arguments) {\n\t\tinvestigations {\n\t\t\tid\n\t\t\tshortId\n\t\t\ttitle\n\t\t\tkeyFindings\n\t\t\tpriority\n\t\t\ttype\n\t\t\tstatus\n\t\t\tcontributorIds\n\t\t\tassigneeId\n\t\t\ttenantId\n\t\t\tcreatedById\n\t\t\tcreatedAt\n\t\t\tupdatedById\n\t\t\tupdatedAt\n\t\t\tprocessingStatus {\n\t\t\t\talerts\n\t\t\t\tevents\n\t\t\t\tassets\n\t\t\t}\n\t\t}\n\t\ttotalCount\n\t}\n}\n","operationName":"investigationsV2","variables":{"arguments":{"cql":"status IN ('\''Open'\'', '\''Awaiting Action'\'') and createdAt >= '\''2024-07-19T21:55:28.163531Z'\'' | sort by createdAt asc","page":1,"perPage":100}}}'
Notes🔗
- If searching from the context of a partner tenant, the search will be performed across all children tenants.
- Investigations CQL search does not supported
- Aggregations
- HEAD or TAIL (use page/perPage)
- Joins
Supported Fields for CQL🔗
CQL query fields available in the investigationsV2
query include the following:
Field | Type | Example Values | Notes |
---|---|---|---|
id |
string | d638e49d-a3b5-421e-b28d-cb9322a5eaa6 | |
title |
String | My Investigation Title | |
tenantId |
String | 11772 | |
keyFindings |
String | Investigation Key Findings | |
status |
String | Open, Awaiting Action, Active, Suspended, Closed: Confirmed Security Incident, Closed: Authorized Activity, Closed: Threat Mitigated, Closed: Not Vulnerable, Closed: False Positive Alert, Closed: Inconclusive, Closed: Informational | The enums defined in the GraphQL schema cannot be used as is and must match one of the valid values. |
tags |
String | Tag1 | Tags is a String List but accepts queries that use logical type String. |
contributors |
String | 6f2fed75-ce7f-4790-9ea1-849b9615c87d, 1534, zrZXXgfKZKSiphdZ71aL4ILVvWZYBIvM@clients | contributors is a String List but accepts queries that use logical type String. |
assigneeId |
String | 6f2fed75-ce7f-4790-9ea1-849b9615c87d, 1534, @customer | Accepts user IDs, client IDs and @customer. It will also accept your partner's mention code. |
createdBy |
String | 6f2fed75-ce7f-4790-9ea1-849b9615c87d, 1534, zrZXXgfKZKSiphdZ71aL4ILVvWZYBIvM@clients | |
createdAt |
Timestamp | 2024-08-14T15:52:30.509542Z | |
updatedBy |
String | 6f2fed75-ce7f-4790-9ea1-849b9615c87d, 1534, zrZXXgfKZKSiphdZ71aL4ILVvWZYBIvM@clients | |
updatedAt |
Timestamp | 2024-08-14T15:52:30.509542Z | |
archivedAt |
Timestamp | 2024-08-14T15:52:30.509542Z | |
priority |
Number | 1, 2, 3, 4 | |
type |
String | Security Investigation, Incident Response, Threat Hunt, MDR Threat Hunt, CTU Threat Hunt, MDR Elite Threat Hunt, Secureworks Incident Response, Unlimited Response, OT Investigation, MDR OT Investigation, Detection Research, Informational | The enums defined in the GraphQL schema cannot be used as is and must match one of the valid values. |
shortId |
String | INV00026 | |
closeReason |
String | Investigation Close Reason | |
createdByPartner |
Bool | true, false | |
handedOffAt |
Timestamp | 2024-08-14T15:52:30.509542Z | Will only be set if createdByPartner is true. |
timeToHandOff |
Number | 360 | Will only be set if createdByPartner is true. Defined in seconds. |
handedOffBy |
String | 6f2fed75-ce7f-4790-9ea1-849b9615c87d, 1534, zrZXXgfKZKSiphdZ71aL4ILVvWZYBIvM@clients | Will only be set if createdByPartner is true. |
acknowledgedAt |
Timestamp | 2024-08-14T15:52:30.509542Z | Will only be set if createdByPartner is true. |
timeToAcknowledgement |
Number | 800 | Will only be set if createdByPartner is true. Defined in seconds. |
acknowledgedBy |
String | 6f2fed75-ce7f-4790-9ea1-849b9615c87d, 1534 | Will only be set if createdByPartner is true. |
resolvedAt |
Timestamp | 2024-08-14T15:52:30.509542Z | Will only be set if createdByPartner is true. |
timeToResolution |
Number | 687 | Will only be set if createdByPartner is true. Defined in seconds. |
resolvedBy |
String | 6f2fed75-ce7f-4790-9ea1-849b9615c87d, 1534, zrZXXgfKZKSiphdZ71aL4ILVvWZYBIvM@clients | Will only be set if createdByPartner is true. |
Next Steps🔗
For more information, see the Investigations v2 GraphQL API Documentation.