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:
- Create a search and keep its search URN.
- Wait for the search to complete.
- 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¶
- Work with search results to choose fields, handle enrichment, and set polling and retry policies.
- Migrate from the XDR Query API to adapt an existing SQL integration.
- Use the Search GraphQL API reference for operation contracts and types.