---
title: "Export the workspace audit log"
method: GET
path: "/v1/workspaces/{id}/audit"
tags: ["workspaces"]
---

# Export the workspace audit log

`GET /v1/workspaces/{id}/audit`

## Request

- Base URL: `https://api.hyperresearch.ai`
- URL: `https://api.hyperresearch.ai/v1/workspaces/{id}/audit`
- Auth: one of:
  - HTTP bearer
  - API key in cookie `hr_session`

Newest first, keyset-paginated on (ts, id). `format=ndjson` streams application/x-ndjson, one JSON object per line. The queried window is clamped to the workspace audit retention policy.

## Path parameters

- `id` string, required

## Query parameters

- `from` string
- `to` string
- `cursor` string
- `limit` integer
- `format` 'json' | 'ndjson'

## Response `200`

Audit page (json) or NDJSON stream

- AuditLogPage
  - `data` AuditLogEntry[], required
    - `id` string, required
    - `ts` string, required
    - `actor` string, required
    - `action` string, required
    - `target` string, nullable, required
    - `ip` string, nullable, required
    - `detail` unknown
    - `kind` 'activity' | 'adjustment', required: `adjustment` marks a correction an operator made to this account — a refund, a credit, anything with a `backfill:`-style actor. Everything the customer did themselves is `activity` (E2E2-07).
    - `display_reason` string, nullable, required: One sentence for this row, ready to print — for every action this platform writes. Null only for a row from a writer that predates its own mapping; a client that finds it null should say so rather than splitting `action` on a dot, which is how "Sign-in clerk exchange by usr_D4ETBWY7…" reached a customer (E2E4-13). The raw `actor`, `action`, `target` and `detail` are never paraphrased away.
    - `display_actor` string, required: Who did it, ready to print: the user's email where we know it, otherwise a plain label ("Hyperresearch support", "An API key"). A console action names the person — both for rows written since E2E5-09 and for historic rows, whose session is resolved to its user at read time. "A signed-in session" is the last resort, for a row whose session no longer exists. NEVER an opaque id — the raw id is still on `actor` for correlation (E2E4-13 / E2E5-09).
    - `user_email` string, nullable, required: The acting user’s email when the actor resolves to a person in this account, null otherwise (an API key, an agent connection, the platform). `display_actor` already prefers it; this is the same value on its own so a client can style a person differently without parsing prose (E2E5-09).
    - `display_target` string, nullable, required: What it was done to, ready to print: "Run: EU AI Act enforcement", "Key: e2e-pass-5", "Project: Grid curtailment". A target whose row is gone falls back to the generic noun for its kind ("An API key"), and anything unrecognised to "A platform record" — never the raw id, which stays on `target` for correlation (E2E5-08). Null when the row has no target.
  - `next_cursor` string, nullable, required
  - `has_more` boolean, required
  - `effective_from` string, required
  - `retention_days` integer, required

## Other responses

- `400`: Invalid request
- `401`: Authentication failed
- `403`: Insufficient scope or plan
- `404`: Not found
- `429`: Rate limited or over quota
- `500`: Internal error

---

[API](https://skmtc.dev/hyperresearch/apis/hyperresearch-cloud-api.md) · [All operations](https://skmtc.dev/hyperresearch/apis/hyperresearch-cloud-api/llms.txt) · [OpenAPI document](https://skmtc.dev/hyperresearch/apis/hyperresearch-cloud-api/revisions/726ef831ebf4?raw)
