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.
Note
The terms Alerts and Investigations have recently been changed to Detections and Cases in Taegis XDR. You may still see references to the old terms while we continue to work towards platform convergence of Sophos and Taegis technologies. For more information, see Taegis Terminology Updates.
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
@customeror@secureworks. - Setting the status to
AWAITING_ACTIONwith 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, andalertsSearchQueriesfields.- The
alertsSearchQueriesfield accepts a CQL search to append alerts to an investigation in bulk. - If attaching evidence in the create call, the
processingStatusfields 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_ACTIONwith 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
processingStatuscan 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
processingStatuscan 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
alertsResolutionStatusis required and all associated alerts will have their status updated. - The close
reasonwill 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
processingStatuscan 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
archiveInvestigationV2mutation 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
unarchiveInvestigationV2mutation 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.