Skip to content

Getting started

What you will build

A GraphQL request that authenticates and searches process lineage — the ancestry tree of processes around a suspicious process on a host — for a batch of processes at once.

Prerequisites

Get credentials

Follow the audience guide above to create a service principal and exchange it for a bearer token, using the same client_credentials grant as every other Sophos API.

First authenticated call

Send a POST request to the GraphQL endpoint, with the token from the previous step in the Authorization header and your tenant ID in X-Tenant-ID. Every tenant shares this same endpoint — there is no per-environment or per-region host to look up.

searchLineage takes a lineageId (the process tree to search) and a batch of processCorrelationIds (up to 100 per call), and returns one result per process. This call asks for counts and matchingCounts only, filtered by searchTerm, for two processes in a lineage.

curl -X POST "https://api.taegis.sophos.com/graphql" \
  -H "Authorization: Bearer <jwt>" \
  -H "X-Tenant-ID: <tenant-id>" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "query ($input: SearchLineageInput!) { searchLineage(input: $input) { processCorrelationId counts { lineageNode lineageNodeDetections } matchingCounts { lineageNode lineageNodeDetections } } }",
    "variables": {
      "input": {
        "lineageId": "a7819600-5fe1-496a-9588-e26a3a2fcdcf",
        "processCorrelationIds": ["p1", "p2"],
        "searchTerm": "powershell"
      }
    }
  }'

Choose response fields

The fields you select determine the cost of a GraphQL request. Start with counts and matchingCounts, then add record fields only when you need their details.

Each selected detail field adds work for every process in the batch. Select only the fields you need, and use each field's paging arguments to limit the records. Avoid deeply nested selections.

If the API rejects a query because it is too complex, request fewer fields, reduce page sizes, or split the request.

A successful response looks like this:

{
  "data": {
    "searchLineage": [
      {
        "processCorrelationId": "p1",
        "counts": { "lineageNode": 1, "lineageNodeDetections": 4 },
        "matchingCounts": { "lineageNode": 1, "lineageNodeDetections": 1 }
      },
      {
        "processCorrelationId": "p2",
        "counts": { "lineageNode": 1, "lineageNodeDetections": 9 },
        "matchingCounts": { "lineageNode": 0, "lineageNodeDetections": 0 }
      }
    ]
  }
}

Verify it worked

data.searchLineage has exactly one entry per processCorrelationId you requested, in the order you requested them. Each entry's counts is the total for that process, ignoring searchTerm; matchingCounts is the same counts narrowed to entries matching searchTerm. Use matchingCounts to decide which processes are worth expanding further.

A request that fails at the GraphQL layer — for example, a lineageId that isn't a valid UUID — still returns HTTP 200, with an errors array alongside data instead of an HTTP error status. This differs from the status-coded error object described in Errors, which covers this API's transport layer instead. An expired token or a rate limit still fails that way, with a non-2xx status and that error object, before your query ever reaches the GraphQL layer.

What to do next

For more information, see the API reference, types, rate limits, and errors.