---
title: "Incremental audit export"
method: GET
path: "/v1/audit/tools/export"
tags: ["System"]
---

# Incremental audit export

`GET /v1/audit/tools/export`

## Request

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

Pull-only collector surface. Returns records with seq greater than `since` in ascending order; loop `since = nextSince` until an empty page for a gap-free, duplicate-free drain. Team-gated (the `enterprise` entitlement) — draining a shared box into org storage is the multi-user product, while reading your own box's trail is free.

## Query parameters

- `since` integer
- `limit` integer
- `include` 'actionDetail'

## Response `200`

Ascending-seq export page

- 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.
  - `nextSince` integer, required: Cursor for the next call — the last returned seq, or the caller's own cursor when the page is empty.
  - `trailId` string, required: Identity of the cursor space. Regenerates when the trail's records file is deleted; on mismatch a collector restarts from since=0.
  - `limit` 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)
