Skip to content

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, and alertsSearchQueries 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.

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.
  • 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 from AWAITING_ACTION.

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🔗

{
    "input": {
        "ids": [
            "<investigation_id_1>",
            "<investigation_id_2>"
        ]
    }
}

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🔗

{
    "input": {
        "ids": [
            "<investigation_id_1>",
            "<investigation_id_2>"
        ]
    }
}

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🔗

{
    "arguments": {
        "id": "<investigation_id>"
    }
}

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.