---
title: "List what changed on the site, and who changed it"
method: GET
path: "/api/v1/sites/{slug}/activity"
tags: ["Draft & publish"]
---

# List what changed on the site, and who changed it

`GET /api/v1/sites/{slug}/activity`

## Request

- Base URL: `https://api.dotsy.ai`
- URL: `https://api.dotsy.ai/api/v1/sites/{slug}/activity`
- Auth: one of:
  - HTTP bearer
  - HTTP bearer

The site's activity log, newest first: each edit, publish and revert with who made it (a person or an AI agent, and the tool), the agent's own note, and whether it still waits for a person to publish. Anyone who can see the site can read it.

Send no filter to get the latest events, however old (up to the plan's retention). Send any of `who`, `state`, `actor`, `since`, `cursor` or `summary` to page through a window instead: `since` then defaults to 7 days and is never older than the plan keeps. Page with `limit` (1–50, default 25) and `cursor`; ask for `summary=1` on the first page for the header counts.

## Path parameters

- `slug` string, required

## Query parameters

- `who` 'all' | 'people' | 'agents'
- `state` 'needs_review' | 'reverted'
- `actor` string
- `since` string, date-time
- `action` string
- `limit` integer
- `cursor` string
- `summary` '1'

## Response `200`

One page of events.

- ActivityList
  - `enabled` boolean, required
  - `events` ActivityEvent[], required
    - `id` string, required: Stable event id — the `:id` of the diff and revert routes.
    - `actorType` string, required: `user`, `key`, `editor-handoff` or `system`.
    - `actorId` string, nullable, required
    - `actorLabel` string, nullable, required: A person's email or an API key's label. Null when not known.
    - `actorChannel` string, required: How the change reached Dotsy: `dashboard-session`, `mcp-oauth`, `api-key`, `editor-handoff`, `anonymous` or `unknown`.
    - `client` string, nullable, required: The tool that made the request, as it announced itself (display only).
    - `tool` string, nullable, required: The MCP tool or CLI command (display only).
    - `note` string, nullable, required: The agent's own note for this change (up to 280 characters). Visible to everyone on the site.
    - `state` 'pending' | 'published' | 'reverted', nullable, required: `pending`: staged, not published. `published`: it went live. `reverted`: undone. Null for events that are not draft changes (settings, members, domains).
    - `summary` ChangeSummary, nullable, required
      - `counts` ChangeCounts, required: What a change touched, by kind. `deleted` counts the pages and files it removed.
        - `pages` integer, required
        - `layouts` integer, required
        - `fragments` integer, required
        - `menus` integer, required
        - `routes` integer, required
        - `deleted` integer, required
      - `keys` string[], required: The first five content keys of the change.
      - `n` integer, required: How many content keys the change touched in all.
      - `truncated` boolean, required: True for a very large change: it has counts but no per-file diff or revert.
    - `reverted` RevertedInfo, nullable, required: Who undid this change, and why.
      - `by` object, required
        - `id` string, nullable, required
        - `label` string, nullable, required: A person's email, or the label of the API key.
        - `channel` string, required
      - `reason` string, nullable, required
      - `at` integer, required: Unix ms.
    - `revertOf` string, nullable, required: On a revert event: the id of the change it undid.
    - `action` string, required
    - `target` string, nullable, required
    - `editCount` integer, required: Edits folded into this row (repeated edits to one page within 10 minutes merge).
    - `firstAt` integer, required
    - `createdAt` integer, required: Unix ms of the latest edit in this row.
    - `keyCreatedBy` string, nullable, required: For an API key's change: the name (or email) of the person who created the key. Null for older keys and for everything else.
    - `diffAvailable` boolean, required: True when `GET …/activity/{id}/diff` can show this change.
    - `counts` PublishCounts, nullable: Publish rows only.
      - `pages` integer, required
      - `menus` integer, nullable, required
      - `agentChanges` integer: How many agent changes this publish put live.
  - `nextCursor` string, nullable, required: Pass as `cursor` for the next page; null on the last page.
  - `summary` ActivitySummary: Present only with `summary=1`.
    - `changes` object, required: Events in the range, counted up to 1,000.
      - `n` integer, required
      - `more` boolean, required: True when the real number is higher than `n`.
    - `actors` object, required: Distinct actors among the newest events in the range, up to 20.
      - `n` integer, required
      - `more` boolean, required: True when the real number is higher than `n`.
    - `needsReview` object, required: Agent changes still waiting for a person to publish, up to 100.
      - `n` integer, required
      - `more` boolean, required: True when the real number is higher than `n`.
    - `actorList` object[], required: The most recent distinct actors, for a picker; pass an `id` as `actor`.
      - `id` string, required
      - `label` string, nullable, required
      - `channel` string, required
      - `client` string, nullable, required
    - `retentionDays` integer, required: How far back this site's plan keeps activity (90 on Free, 365 on paid).

## Other responses

- `400`: A filter is not valid (`invalid_request`, with `issues`), or `cursor` is not one this API issued (`invalid_cursor`).
- `401`: Missing or invalid credentials.
- `404`: No such site, or it is not visible to this account.

---

[API](https://skmtc.dev/dotsy/apis/dotsy-api.md) · [All operations](https://skmtc.dev/dotsy/apis/dotsy-api/llms.txt) · [OpenAPI document](https://skmtc.dev/dotsy/apis/dotsy-api/revisions/4272ed3b85d7?raw)
