Scout Trails Docs

API reference

This page lists every endpoint of the Scout Trails query API. All endpoints use the base URL https://api.scoutmonitoring.io, accept GET only, require Authorization: Bearer <api-key> (except /healthz), and return JSON. Authentication, pagination, timestamps and the error format are described in the API overview.

EndpointReturns
GET /v1/pingService name and version; checks a key
GET /v1/sessionsSessions, newest activity first
GET /v1/sessions/facetsValues for the session filters
GET /v1/sessions/{id}One session with its tool calls, risk flags and domains
GET /v1/tool-callsTool calls, newest first
GET /v1/tool-calls/facetsValues for the tool-call filters
GET /v1/tool-calls/{id}One tool call with its arguments and environment
GET /v1/insights/activityTool-call volume and errors over time
GET /v1/insights/top-toolsMost-used tools
GET /v1/insights/outliersSessions with unusually many tool calls
GET /v1/insights/costModel tokens and cost
GET /v1/insights/riskRisk flags raised on tool calls
GET /v1/insights/domainsExternal domains agents reached
GET /healthzLiveness, no key needed

Shared concepts

Outcome

Every tool call has an outcome:

ValueMeaning
okThe tool ran and succeeded.
errorThe tool ran and failed.
rejectedThe call was denied by a permission rule, a hook or a person, and the tool never ran.

A rejected call has null for duration_ms, success and result_size_bytes, because it never ran. Error counts in every endpoint count only error, so a rejected call is never counted as a failure. The dashboard shows rejected calls with the status denied.

Filtering by actor or team

GET /v1/sessions and GET /v1/tool-calls accept two filters that narrow results to particular actors:

  • actor: one actor’s telemetry id, matched exactly.
  • team: a set of actor telemetry ids. Repeat the parameter (team=a&team=b) or separate ids with commas (team=a,b); both forms can be mixed, and duplicates and blank entries are ignored.

These take actor telemetry ids, which are listed in the Telemetry id column of Manage > Actors & ingest keys and returned as actor_id in responses. The team filter does not take a dashboard team name: to see one team’s data, pass the telemetry ids of the actors in that team. Both filters only narrow results inside your organization.

Insight windows

All /v1/insights/ endpoints take the same two parameters and return the same envelope.

ParameterValuesDefault
window7d, 30d, 90d: how far back from now to look7d
granularitydaily or weekly: the size of each time-series bucketdaily

weekly is accepted only with 30d and 90d; window=7d&granularity=weekly returns 400. Values are case-insensitive. Buckets are labelled with their start time in UTC; daily buckets start at midnight UTC and weekly buckets start on Sunday.

{
  "window": {
    "window": "30d",
    "granularity": "weekly",
    "start": "2026-09-05T20:26:54.469217Z",
    "end": "2026-10-05T20:26:54.469217Z"
  },
  "summary": { ... },
  "series": [ ... ],
  "breakdown": [ ... ]
}
FieldDescription
windowThe resolved window: the window and granularity values used and the exact start (inclusive) and end (exclusive) of the range.
summaryHeadline figures for the whole window.
seriesPoints ordered by bucket, oldest first. Buckets with no data are omitted. null for endpoints that have no time series.
breakdownPer-key rows. null for endpoints that have no breakdown.

Error responses for bad window values:

{"error":{"code":"invalid_request","message":"invalid window: \"14d\" (allowed: 7d, 30d, 90d)"}}
{"error":{"code":"invalid_request","message":"invalid granularity: \"hourly\" (allowed: daily, weekly)"}}
{"error":{"code":"invalid_request","message":"granularity not allowed for this window: weekly is only valid for 30d/90d windows"}}

GET /v1/ping

Returns the service name and version. Use it to check that a key is accepted.

curl -s https://api.scoutmonitoring.io/v1/ping \
  -H "Authorization: Bearer $TRAILS_API_KEY"
{"service":"<service name>","version":"0.1.0"}

GET /v1/sessions

Lists sessions, ordered by most recent activity (last_seen) first. A session is one run of a coding agent, made up of the tool calls it reported.

Query parameters

ParameterTypeDescription
limitintegerPage size, 1 to 500. Default 50.
cursorstringnext_cursor from the previous page.
afterRFC 3339 timestampOnly tool calls at or after this time.
beforeRFC 3339 timestampOnly tool calls at or before this time.
agentstringOnly tool calls from this agent, matched exactly against agent_system. Get the values from /v1/sessions/facets.
actorstringOnly this actor’s telemetry id. See Filtering by actor or team.
teamstring, repeatableOnly these actors’ telemetry ids.
domainstringOnly sessions that reached this external domain, matched exactly, for example github.com.
tagstringNot supported; any value returns 501.

The time, agent, actor and team filters select tool calls, and each session is built from the tool calls that match. A session that started before after therefore appears with first_seen, tool_call_count and the other counts covering only the calls inside the range. cost_usd is the exception: it always covers the whole session, regardless of filters.

Example

curl -s "https://api.scoutmonitoring.io/v1/sessions?limit=2&after=2026-09-20T00:00:00Z" \
  -H "Authorization: Bearer $TRAILS_API_KEY"
{
  "data": [
    {
      "session_id": "5e551011-0000-4000-8000-000000000001",
      "actor_id": "Q2xhdWRlQ29kZS1sYXB0b3AtMDAwMDAwMDAwMDAwMDAw",
      "first_seen": "2026-09-24T15:57:39.647Z",
      "last_seen": "2026-09-25T15:27:56.67Z",
      "tool_call_count": 68,
      "agent_system": "claude-code",
      "agent_version": "2.1.281",
      "model": "",
      "error_count": 0,
      "success_count": 68,
      "total_duration_ms": 84617023,
      "cost_usd": 6.997629,
      "tags": []
    },
    {
      "session_id": "341e6a93-2505-40d4-8bb2-03286d6b3360",
      "actor_id": "Q2xhdWRlQ29kZS1sYXB0b3AtMDAwMDAwMDAwMDAwMDAw",
      "first_seen": "2026-09-23T17:57:00.215Z",
      "last_seen": "2026-09-23T17:57:00.215Z",
      "tool_call_count": 1,
      "agent_system": "claude-code",
      "agent_version": "2.1.280",
      "model": "",
      "error_count": 0,
      "success_count": 1,
      "total_duration_ms": 0,
      "cost_usd": 0.2071738,
      "tags": []
    }
  ],
  "next_cursor": "eyJ0IjoiMjAyNi0wOS0yM1QxNzo1NzowMC4yMTVaIiwiaSI6IjM0MWU2YTkzLTI1MDUtNDBkNC04YmIyLTAzMjg2ZDZiMzM2MCJ9"
}

Session fields

FieldTypeDescription
session_idstringThe session’s id, as reported by the agent.
actor_idstringTelemetry id of the actor that sent the session.
first_seentimestampTime of the session’s first matching tool call.
last_seentimestampTime of the session’s last matching tool call.
tool_call_countintegerTool calls in the session, including rejected ones.
agent_systemstringThe agent that reported the session, for example claude-code.
agent_versionstringThe agent’s version, or "" when not reported.
modelstringThe model recorded on the session’s tool calls, or "" when the agent does not report one there.
error_countintegerTool calls with outcome error.
success_countintegerTool calls with outcome ok.
total_duration_msintegerMilliseconds between the first and last tool call.
cost_usdnumberTotal model cost of the whole session in US dollars, regardless of filters. 0 when the agent reports no cost.
tagsarrayAlways [].

GET /v1/sessions/facets

Returns the values the session filters accept, sorted alphabetically, across all of your organization’s data. Each list holds at most 1,000 values. Takes no parameters.

{
  "domains": ["github.com", "pypi.org"],
  "agents": ["claude-code"]
}
FieldUse as
domainsdomain on /v1/sessions
agentsagent on /v1/sessions

GET /v1/sessions/{id}

Returns one session with its full tool-call timeline, its risk flags and the external domains it reached.

curl -s https://api.scoutmonitoring.io/v1/sessions/5e551011-0000-4000-8000-000000000001 \
  -H "Authorization: Bearer $TRAILS_API_KEY"
{
  "session": {
    "session_id": "5e551011-0000-4000-8000-000000000001",
    "actor_id": "Q2xhdWRlQ29kZS1sYXB0b3AtMDAwMDAwMDAwMDAwMDAw",
    "first_seen": "2026-09-24T15:57:39.647Z",
    "last_seen": "2026-09-25T15:27:56.67Z",
    "tool_call_count": 68,
    "agent_system": "claude-code",
    "agent_version": "2.1.281",
    "model": "",
    "error_count": 0,
    "success_count": 68,
    "total_duration_ms": 84617023,
    "cost_usd": 6.997629,
    "tags": []
  },
  "tool_calls": [
    {
      "id": "390eb4a4-90df-4d6d-a3b9-56058138c499",
      "timestamp": "2026-09-24T15:57:39.647Z",
      "tool_name": "Agent",
      "tool_type": "builtin",
      "category": "code_exec",
      "duration_ms": 12,
      "success": true,
      "outcome": "ok",
      "decision": "accept",
      "decision_source": "config"
    }
  ],
  "risk_flags": [
    {
      "timestamp": "2026-09-24T16:02:11.031Z",
      "tool_call_id": "toolu_01AbCdEfGhIjKlMnOpQrStUv",
      "tool_name": "Bash",
      "flag": "destructive_operation",
      "evidence": "rm recursive/force"
    }
  ],
  "external_domains": [
    {"domain": "github.com", "scheme": "https", "hits": 2}
  ]
}

The session object has the session fields, covering the whole session. The other fields:

FieldDescription
tool_callsThe session’s tool calls, oldest first. Each has id, timestamp, tool_name, tool_type, category, duration_ms, success, outcome, and, when present, error_message, decision and decision_source. See tool-call fields.
risk_flagsRisk flags raised on the session’s tool calls, oldest first: timestamp, tool_call_id, tool_name, flag and evidence (a short description of what matched: the path for sensitive_path, the kind of command for destructive_operation, or the kind of credential and its first few characters for credential_detected). See risk flag kinds.
external_domainsDomains the session reached, one row per domain and scheme, with the number of hits, most hits first.

Each list holds at most 5,000 entries; use /v1/tool-calls?session_id= to page through a longer session. The three lists are [] when empty.

Returns 404 with {"error":{"code":"not_found","message":"session not found"}} when the session does not exist in your organization.

GET /v1/tool-calls

Lists individual tool calls, newest first.

Query parameters

ParameterTypeDescription
limitintegerPage size, 1 to 500. Default 50.
cursorstringnext_cursor from the previous page.
afterRFC 3339 timestampOnly calls at or after this time.
beforeRFC 3339 timestampOnly calls at or before this time.
session_idstringOnly calls in this session.
actorstringOnly this actor’s telemetry id. See Filtering by actor or team.
teamstring, repeatableOnly these actors’ telemetry ids.
tool_namestringExact tool name, for example Bash or Edit.
tool_typestringExact tool type, for example builtin or mcp.
categorystringExact category: code_exec, file_read, file_write, web_fetch, mcp or other.
outcomestringok, error or rejected (case-insensitive). See Outcome. Any other value returns 400.

The parameter success is not accepted; sending it returns 400 with the message the success filter is replaced by outcome: ok, error or rejected. Use outcome instead.

Example

curl -s "https://api.scoutmonitoring.io/v1/tool-calls?limit=2&outcome=ok" \
  -H "Authorization: Bearer $TRAILS_API_KEY"
{
  "data": [
    {
      "id": "fd58fb29-fa37-4c3d-8c38-8087710df8b0",
      "timestamp": "2026-09-25T15:27:56.67Z",
      "session_id": "5e551011-0000-4000-8000-000000000001",
      "actor_id": "Q2xhdWRlQ29kZS1sYXB0b3AtMDAwMDAwMDAwMDAwMDAw",
      "tool_name": "Read",
      "tool_type": "builtin",
      "category": "file_read",
      "duration_ms": 189,
      "success": true,
      "outcome": "ok",
      "decision": "accept",
      "decision_source": "config",
      "agent_system": "claude-code"
    },
    {
      "id": "6d0f1620-9c1b-4eb8-9315-073b14a96cba",
      "timestamp": "2026-09-25T15:27:56.18Z",
      "session_id": "5e551011-0000-4000-8000-000000000001",
      "actor_id": "Q2xhdWRlQ29kZS1sYXB0b3AtMDAwMDAwMDAwMDAwMDAw",
      "tool_name": "Grep",
      "tool_type": "builtin",
      "category": "file_read",
      "duration_ms": 190,
      "success": true,
      "outcome": "ok",
      "decision": "accept",
      "decision_source": "config",
      "agent_system": "claude-code"
    }
  ],
  "next_cursor": "eyJ0IjoiMjAyNi0wOS0yNVQxNToyNzo1Ni4xOFoiLCJpIjoiNmQwZjE2MjAtOWMxYi00ZWI4LTkzMTUtMDczYjE0YTk2Y2JhIn0"
}

Tool-call fields

Fields marked optional are left out of the response when they are empty.

FieldTypeDescription
idstringThe tool call’s id. Use it with /v1/tool-calls/{id}.
timestamptimestampWhen the call happened.
session_idstringThe session the call belongs to.
actor_idstringTelemetry id of the actor that sent it.
tool_namestringThe tool, for example Bash, Read, or an MCP tool’s name.
tool_typestringbuiltin for the agent’s own tools, mcp for tools served by an MCP server.
categorystringcode_exec, file_read, file_write, web_fetch, mcp or other.
duration_msinteger or nullHow long the tool ran. null for a rejected call.
successboolean or nulltrue for ok, false for error, null for rejected.
outcomestringok, error or rejected.
error_messagestring, optionalThe error text of a failed call.
decisionstring, optionalThe permission decision the agent reported, for example accept or reject.
decision_sourcestring, optionalWhat made the decision, for example config for a permission rule.
agent_systemstringThe agent that reported the call.
modelstring, optionalThe model, when the agent reports it on tool calls.

GET /v1/tool-calls/facets

Returns the values the tool-call filters accept, sorted alphabetically, across all of your organization’s data. Each list holds at most 1,000 values. Takes no parameters.

{
  "tool_names": ["Bash", "Edit", "Grep", "Read", "WebFetch", "Write"],
  "tool_types": ["builtin", "mcp"],
  "categories": ["code_exec", "file_read", "file_write", "mcp", "other", "web_fetch"]
}
FieldUse as
tool_namestool_name on /v1/tool-calls
tool_typestool_type on /v1/tool-calls
categoriescategory on /v1/tool-calls

GET /v1/tool-calls/{id}

Returns everything recorded about one tool call, including its arguments.

curl -s https://api.scoutmonitoring.io/v1/tool-calls/f313eb76-9727-40ef-ba69-6d03dbdbb515 \
  -H "Authorization: Bearer $TRAILS_API_KEY"
{
  "id": "f313eb76-9727-40ef-ba69-6d03dbdbb515",
  "timestamp": "2026-09-23T17:57:00.215Z",
  "session_id": "341e6a93-2505-40d4-8bb2-03286d6b3360",
  "actor_id": "Q2xhdWRlQ29kZS1sYXB0b3AtMDAwMDAwMDAwMDAwMDAw",
  "prompt_id": "2eeec48f-78b3-49ea-85cf-527fff0e261c",
  "agent_system": "claude-code",
  "agent_version": "2.1.280",
  "tool_name": "Bash",
  "tool_type": "builtin",
  "tool_call_id": "toolu_01XrWPS2d9PQcB3kWyX1XNMu",
  "tool_use_id": "toolu_01XrWPS2d9PQcB3kWyX1XNMu",
  "source": "otlp",
  "arguments": "{\"bash_command\":\"echo\",\"full_command\":\"echo hello\",\"description\":\"Print a string\"}",
  "result_size_bytes": 12,
  "duration_ms": 517,
  "success": true,
  "outcome": "ok",
  "os_type": "darwin",
  "host_arch": "arm64",
  "terminal_type": "ghostty",
  "category": "code_exec"
}

The response has the tool-call fields plus the following. Fields other than id, timestamp, session_id, agent_system, tool_name, tool_type, result_size_bytes, duration_ms, success and outcome are left out when empty.

FieldDescription
prompt_idThe user prompt that led to the call.
agent_versionThe agent’s version.
agent_name, provider_nameThe agent and model provider names, when reported.
tool_call_id, tool_use_idThe agent’s own ids for the call.
tool_descriptionThe tool’s description, when reported.
sourceHow the call reached Scout Trails.
argumentsThe tool’s input as a JSON-encoded string. Parse it a second time to get an object. Present only when the agent is configured to send tool arguments; see Agents.
resultThe tool’s output, when the agent sends it.
result_size_bytesSize of the tool’s output. null for a rejected call.
error_typeThe kind of error, for a failed call.
mcp_server_name, mcp_server_scopeThe MCP server that served the tool, and its configured scope, for MCP tools.
os_type, host_arch, terminal_typeThe operating system, CPU architecture and terminal of the machine that ran the agent.
cwdThe working directory the agent ran in, when reported.
trace_id, span_idTrace identifiers, when the agent sends traces.

Returns 404 with {"error":{"code":"not_found","message":"tool call not found"}} when the tool call does not exist in your organization.

GET /v1/insights/activity

Tool-call volume and errors over the window. Takes the insight window parameters. breakdown is null.

curl -s "https://api.scoutmonitoring.io/v1/insights/activity?window=30d&granularity=weekly" \
  -H "Authorization: Bearer $TRAILS_API_KEY"
{
  "window": {"window": "30d", "granularity": "weekly", "start": "2026-09-05T20:26:54.469217Z", "end": "2026-10-05T20:26:54.469217Z"},
  "summary": {"total_calls": 645, "error_count": 4, "session_count": 129},
  "series": [
    {"bucket": "2026-09-13T00:00:00Z", "calls": 316, "errors": 4},
    {"bucket": "2026-09-20T00:00:00Z", "calls": 329, "errors": 0}
  ],
  "breakdown": null
}
FieldDescription
summary.total_callsTool calls in the window, including rejected ones.
summary.error_countTool calls with outcome error.
summary.session_countDistinct sessions with at least one tool call in the window.
series[].calls, series[].errorsThe same counts per bucket.

GET /v1/insights/top-tools

The most-used tools in the window. Takes the insight window parameters; granularity is validated but has no effect. series is null.

{
  "window": {"window": "30d", "granularity": "daily", "start": "2026-09-05T20:26:54.516005Z", "end": "2026-10-05T20:26:54.516005Z"},
  "summary": {"total_calls": 645, "unique_tools": 14},
  "series": null,
  "breakdown": [
    {"tool_name": "Read", "tool_type": "builtin", "calls": 266, "errors": 0, "avg_duration_ms": 5.58},
    {"tool_name": "Grep", "tool_type": "builtin", "calls": 252, "errors": 0, "avg_duration_ms": 13}
  ]
}
FieldDescription
summary.total_callsTool calls in the window.
summary.unique_toolsDistinct tool names in the window.
breakdownUp to 50 rows, one per tool name and type, most calls first.
breakdown[].callsCalls to the tool, including rejected ones.
breakdown[].errorsCalls with outcome error.
breakdown[].avg_duration_msAverage run time. null when every call to the tool was rejected.

GET /v1/insights/outliers

Sessions whose tool-call count is above the 95th percentile of all sessions in the window. The threshold is computed from your own data for each request. Takes the insight window parameters; granularity is validated but has no effect. series is null.

{
  "window": {"window": "30d", "granularity": "daily", "start": "2026-09-05T20:26:54.552989Z", "end": "2026-10-05T20:26:54.552989Z"},
  "summary": {"p95_call_count": 5.6, "outlier_count": 7, "session_count": 129},
  "series": null,
  "breakdown": [
    {
      "session_id": "5e551011-0000-4000-8000-000000000001",
      "call_count": 68,
      "first_seen": "2026-09-24T15:57:39.647Z",
      "last_seen": "2026-09-25T15:27:56.67Z",
      "agent_system": "claude-code",
      "model": "",
      "error_count": 0
    }
  ]
}
FieldDescription
summary.p95_call_countThe 95th-percentile tool-call count per session. Sessions above it are outliers.
summary.outlier_countSessions above the threshold.
summary.session_countSessions in the window.
breakdownUp to 50 outlier sessions, most tool calls first, with their call_count, first_seen, last_seen, agent_system, model and error_count within the window.

GET /v1/insights/cost

Model usage reported by your agents: token counts and cost. Takes the insight window parameters.

{
  "window": {"window": "30d", "granularity": "weekly", "start": "2026-09-05T20:26:54.608333Z", "end": "2026-10-05T20:26:54.608333Z"},
  "summary": {
    "input_tokens": 450394,
    "output_tokens": 129679,
    "cache_read_tokens": 8695167,
    "cache_creation_tokens": 593730,
    "cost_usd": 10.9496248,
    "cost_available": true,
    "call_count": 163
  },
  "series": [
    {"bucket": "2026-09-13T00:00:00Z", "input_tokens": 326196, "output_tokens": 56916, "cost_usd": 2.194},
    {"bucket": "2026-09-20T00:00:00Z", "input_tokens": 124198, "output_tokens": 72763, "cost_usd": 8.7556248}
  ],
  "breakdown": [
    {"provider_name": "", "model": "claude-opus-4-6", "input_tokens": 269472, "output_tokens": 41488, "cost_usd": 1.72596, "call_count": 40},
    {"provider_name": "", "model": "claude-sonnet-4-5", "input_tokens": 172204, "output_tokens": 31704, "cost_usd": 1.230328, "call_count": 36}
  ]
}
FieldDescription
summary.input_tokens, output_tokens, cache_read_tokens, cache_creation_tokensToken totals across all model calls in the window.
summary.cost_usdTotal cost in US dollars, as reported by the agents.
summary.cost_availabletrue when the window contains any reported cost. When false, cost_usd values are 0 because no agent reported cost, not because usage was free.
summary.call_countModel calls in the window.
series[]Input tokens, output tokens and cost per bucket.
breakdownUp to 50 rows, one per provider and model, ordered by input plus output tokens. Model calls that report no model count toward summary but are not listed. provider_name is "" when the agent does not report it.

GET /v1/insights/risk

Risk flags Scout Trails raised on tool calls in the window. Takes the insight window parameters.

Flag kinds:

flagRaised when a tool call
credential_detectedContains what looks like a secret or credential.
destructive_operationRuns a destructive command, such as a recursive delete or a force push.
sensitive_pathTouches a sensitive file or directory, such as a .env file or SSH keys.
{
  "window": {"window": "7d", "granularity": "daily", "start": "2026-09-28T20:30:00Z", "end": "2026-10-05T20:30:00Z"},
  "summary": {"total_flags": 3, "sessions_flagged": 2, "distinct_flag_kinds": 2},
  "series": [
    {"bucket": "2026-10-01T00:00:00Z", "flag": "destructive_operation", "flags": 2},
    {"bucket": "2026-10-03T00:00:00Z", "flag": "sensitive_path", "flags": 1}
  ],
  "breakdown": [
    {"flag": "destructive_operation", "flags": 2, "sessions": 1, "tools": 1},
    {"flag": "sensitive_path", "flags": 1, "sessions": 1, "tools": 1}
  ]
}
FieldDescription
summary.total_flagsFlags raised in the window.
summary.sessions_flaggedDistinct sessions with at least one flag.
summary.distinct_flag_kindsDistinct flag kinds raised.
series[]One point per bucket and flag kind: bucket, flag, and the number of flags. Pivot on flag to chart one line per kind.
breakdown[]One row per flag kind, most flags first: flags raised, distinct sessions and distinct tools involved.

Use /v1/sessions/{id} to see the individual flags and their evidence for a session.

GET /v1/insights/domains

External domains found in your agents’ tool-call arguments: URLs in curl and wget commands, web fetches, and URL arguments of MCP tools. Takes the insight window parameters.

{
  "window": {"window": "30d", "granularity": "weekly", "start": "2026-09-05T20:26:54.676699Z", "end": "2026-10-05T20:26:54.676699Z"},
  "summary": {"total_hits": 12, "unique_domains": 1, "sessions": 6},
  "series": [
    {"bucket": "2026-09-13T00:00:00Z", "hits": 8, "unique_domains": 1},
    {"bucket": "2026-09-20T00:00:00Z", "hits": 4, "unique_domains": 1}
  ],
  "breakdown": [
    {"domain": "github.com", "scheme": "https", "hits": 12, "sessions": 6}
  ]
}
FieldDescription
summary.total_hitsReferences to external domains in tool-call arguments in the window.
summary.unique_domainsDistinct domains reached.
summary.sessionsDistinct sessions that reached any external domain.
series[]Hits and distinct domains per bucket.
breakdown[]Up to 50 rows, one per domain and scheme, most hits first, with the number of distinct sessions.

GET /healthz

Needs no key. Returns 200 with {"status":"ok"} while the service is up.

In this section