Skip to content

Getting started

API under active development

Use the Search GraphQL API reference for supported operations and fields. Introspection can expose additional fields.

What you will build

Run a QL search for process events from the last hour:

  1. Create a search and keep its search URN.
  2. Wait for the search to complete.
  3. Read its results and follow the next-page cursor.

The search URN identifies this execution. Use it unchanged in the status and results requests below.

Prerequisites

  • A tenant with process event data.
  • API credentials for your account. Follow the Tenant, Partner, or Organization guide.
  • Your tenant UUID and a client that can send JSON HTTP requests.

Get credentials

Use your account guide to exchange your service-principal credentials for a bearer token with the client_credentials grant. Replace <jwt> and <tenant-id> below with that token and your tenant UUID.

First authenticated call

Send a JSON POST to https://api.taegis.sophos.com/graphql. These examples select the default GraphQL schema.

The QL query selects three event fields to keep the response compact. The API can also add enriched fields, such as a hostname resolved from host_id.

curl -X POST "https://api.taegis.sophos.com/graphql" \
  -H "Authorization: Bearer <jwt>" \
  -H "X-Tenant-ID: <tenant-id>" \
  -H "X-GraphQL-Schema: default" \
  -H "Content-Type: application/json" \
  -d '{
    "operationName": "CreateSearch",
    "query": "mutation CreateSearch($input: CreateSearchInput) { createSearch(input: $input) { urn status } }",
    "variables": {
      "input": {
        "text": "from process where earliest = -1h | fields host_id, commandline, image_path"
      }
    }
  }'

This excerpt comes from a live response. Identifiers and event values in this guide are redacted. Your initial status can differ.

{
  "data": {
    "createSearch": {
      "urn": "<search-urn>",
      "status": "QUEUED"
    }
  }
}

Keep data.createSearch.urn. For the next calls, reuse the URL and headers above and replace the JSON request body with the examples below. Replace <search-urn> with the returned URN.

Verify it worked

Wait for completion

Send this status request. Leave time between calls while status is QUEUED or IN_PROGRESS. outcome.success is UNKNOWN until completion.

{
  "operationName": "SearchStatus",
  "query": "query SearchStatus($urn: URN!) { search(urn: $urn) { urn status outcome { success errors { urn errors } } } }",
  "variables": { "urn": "<search-urn>" }
}

Check both status and outcome.success. This live response excerpt shows a completed search whose partitions all succeeded:

{
  "data": {
    "search": {
      "urn": "<search-urn>",
      "status": "COMPLETE",
      "outcome": { "success": "ALL", "errors": [] }
    }
  }
}

COMPLETE means execution ended. PARTIAL or NONE indicates failed partitions. For those outcomes, see Handle search failures.

Read a result page

Use the same search URN. Omit cursor from the variables for the first page. Here, limit requests at most two rows per page.

{
  "operationName": "SearchResults",
  "query": "query SearchResults($urn: URN!, $limit: Int, $cursor: String) { searchResults(urn: $urn, limit: $limit, cursor: $cursor) { fields { name baseType originSchemaTypes } values totals { total { value } subtotals { schemaType value } } nextCursor } }",
  "variables": { "urn": "<search-urn>", "limit": 2 }
}

This live response excerpt shows one row and part of its field metadata. totals counts the whole result set, not this page.

{
  "data": {
    "searchResults": {
      "fields": [
        { "name": "host_id", "baseType": "STRING", "originSchemaTypes": ["process"] },
        { "name": "hostname", "baseType": "STRING", "originSchemaTypes": [] }
      ],
      "values": [
        {
          "commandline": "<commandline>",
          "enrichSummary": "<enriched-summary>",
          "host_id": "<host-id>",
          "hostname": "<hostname>",
          "image_path": "<image-path>",
          "schema_type": "process"
        }
      ],
      "totals": {
        "total": { "value": 13 },
        "subtotals": [{ "schemaType": "process", "value": 13 }]
      },
      "nextCursor": "<next-cursor>"
    }
  }
}

To read the next page, use the same SearchResults query with these variables:

{ "urn": "<search-urn>", "limit": 2, "cursor": "<next-cursor>" }

Pass the returned cursor unchanged. Continue until nextCursor is null or absent. A small page limit does not limit the total search results.

Check HTTP status and top-level GraphQL errors on every call, including HTTP 200 responses.

What to do next