---
title: "Tool dispatch audit log"
method: GET
path: "/v1/audit/tools"
tags: ["System"]
---

# Tool dispatch audit log

`GET /v1/audit/tools`

## Request

- Base URL: `http://localhost:9998`
- URL: `http://localhost:9998/v1/audit/tools`
- Auth: HTTP bearer

Paginated record of every tool this machine ran, newest first. Free at every tier — the trail is what answers a "your tool did X to my machine" claim. The `accountId` and `owner` fields are null without the `enterprise` entitlement.

## Query parameters

- `limit` integer
- `offset` integer
- `tool` string
- `owner` string
- `principal` string
- `outcome` 'allowed' | 'denied' | 'awaiting_approval'
- `recordClass` 'routine' | 'security'
- `since` string, date-time
- `until` string, date-time
- `include` 'actionDetail'

## Response `200`

Audit records

- object
  - `records` ToolAuditRecord[], required
    - `seq` integer, required
    - `ts` string, date-time, required
    - `accountId` string, nullable
    - `deviceId` string, nullable
    - `owner` string, nullable
    - `principal` string, required: Dispatching principal kind — a token kind, `ambient`, or `unauthenticated-loopback` for a same-UID caller that presented no credential.
    - `recordClass` 'routine' | 'security', required: Retention class. `security` covers any denial, call parked awaiting approval, unattributed principal, tainted session, or call reaching past tools:read; it survives a 12-month window and is evicted only after every routine record.
    - `tier` string, required
    - `tool` string, required
    - `method` string, required
    - `transport` string, required
    - `outcome` 'allowed' | 'denied' | 'awaiting_approval', required: The authorization verdict. A tool that ran and returned an error is `allowed`. `awaiting_approval` is a call parked on the REST approval channel: nothing ran and nobody refused it; the call re-presented with the approval records its own verdict. When the approval is refused (denied, expired at its hold deadline, or its client lost authority before answering) ToolPiper appends the parked call's resolution, a `denied` record with the same `invocationId`, so a refused call reads `awaiting_approval` and then one denial.
    - `denyReason` 'tier' | 'feature' | 'resolving' | 'policy' | 'forbidden' | 'posture', nullable
    - `argKeys` string[], nullable: Sorted argument key names. Never the values.
    - `argsDigest` string, nullable: SHA-256 over the dispatched argument payload, so two calls can be proven same-or-different without storing what they contained.
    - `invocationId` string, nullable: Server-generated UUID for this invocation. Hash-bound when present.
    - `parentInvocationId` string, nullable: Parent invocation UUID for a nested batch step. The parent record may arrive later or be absent from retained history.
    - `approvalId` string, nullable: The REST approval this call parked (on its `awaiting_approval` record), was refused by (on the parked call's resolution when the approval is denied, expires or loses its client's authority unanswered, which shares the parked call's `invocationId`) or re-presented (on the retry's record, allowed or refused), relating the invocations. Only an approval this server issued to the calling client. Hash-bound when present.
    - `untrustedContext` boolean, nullable: Had this session already ingested untrusted content? Tri-state: null means the caller presented no session id, so the question could not be asked — not that the call was clean.
    - `actionDetail` object, nullable: Present only on an `actionAuthorization` record and only with `include=actionDetail` (IToolAuditActionDetail). `evidence` says whether the decision record and every `actionExecution` record keyed to it verify and agree; every other field is null or empty unless it is `verified`.
      - `evidence` 'verified' | 'unsupported' | 'mismatched' | 'tampered', required
      - `operation` string, nullable
      - `decision` 'authorized' | 'ownerDenied' | 'expired' | 'cancelled' | 'authenticationNotCompleted' | 'stale' | 'deniedByPolicy' | 'reviewUnavailable' | 'unattended' | 'queueFull' | 'shutdown', nullable
      - `state` 'refused' | 'authorized' | 'dispatched' | 'succeeded' | 'failed' | 'outcomeUnknown', nullable: `authorized` and `dispatched` mean no completion was recorded, so the outcome is unknown.
      - `strength` 'automatic' | 'consent' | 'deviceOwner', nullable
      - `reasons` string[], required
      - `credentials` object[], required
        - `identityKey` string, required
        - `roleId` string, required
    - `prevHash` string, nullable
    - `hash` string, required: Tamper-evidence chain. An edit is always detectable; a deletion shows as a seq gap the box does not claim to distinguish from its own prune.
  - `total` integer, required
  - `limit` integer, required
  - `offset` integer, required

---

[API](https://skmtc.dev/modelpiper/apis/toolpiper-api.md) · [All operations](https://skmtc.dev/modelpiper/apis/toolpiper-api/llms.txt) · [OpenAPI document](https://skmtc.dev/modelpiper/apis/toolpiper-api/revisions/6722bf56385c?raw)
