---
title: "List the workspace activity"
description: "List who changed what in the workspace: resources, sites, assistants, widgets, tags and members' access, with the actor and the door used. Kept a year. Free."
canonical: "https://lookio.app/docs/api/logs/list-log-activity"
updated: "2026-10-18"
---

# List the workspace activity

Requires `admin`.

Who changed what, latest first: resources added, edited, re-indexed or deleted, site rules and syncs, assistants and widgets created, edited, paused or deleted, tags renamed or deleted, and members' access changed. You page with `cursor`, an opaque string: pass `next_cursor` back unchanged. See [Pagination](/docs/api/conventions#pagination).

Each line has the `actor` (a member, an API key, or Lookio itself for a scheduled sync), the `origin` (the door used: `app`, `api`, `cli`, `mcp`, `agent` for Lookio AI, or `system`), the `target` with its name at the time of the change, and `details`: the names of the fields that changed, counts or a sync's figures. It never holds content.

Narrow the list with `actor_id`, `origin` (comma-separated), `target_type` (`resource`, `assistant`, `widget`, `tag` or `member`), `target_id`, `action` (an exact action such as `assistant.updated`, or a kind such as `assistant` for every action on it), `q` (words in the name of what changed) and `from` and `to`. Use `target_id` to answer "who changed this assistant?" and `actor_id` to answer "what did this key do?".

Admins only. The caller must be an admin connected as a person (OAuth: the CLI login or an MCP client) with the `admin` scope; an API key never has it, and the call fails with `permission_denied`. Entries are kept a year. See [Logs](/docs/platform/logs).

```http
GET https://api.lookio.app/v1/logs/activity
```

## Authorizations

- `Authorization` (bearer, in header, required)

## Query parameters

- `actor_id` (`string`, length: `1–64 chars`): Only what this member (user id) or API key (key id) did.
- `origin` (`string`, length: `≥ 1 chars`): Only changes made through these doors, comma-separated: `app`, `api`, `cli`, `mcp`, `agent` (Lookio AI), `system` (Lookio itself, such as a scheduled sync).
- `target_type` (`enum<string>`, one of: `resource, assistant, widget, tag, member`): Only changes to this kind of thing.
- `target_id` (`string`, length: `1–64 chars`): Only changes to this resource, assistant, widget or member.
- `action` (`string`, pattern: `^[a-z_]+(\.[a-z_]+)?$`): An exact action (`assistant.updated`) or every action on a kind (`assistant`).
- `q` (`string`, length: `1–200 chars`): Words in the name of what changed.
- `from` (`string`): Only changes since this ISO 8601 date or timestamp.
- `to` (`string`): Only changes until this ISO 8601 date or timestamp.
- `cursor` (`string`, length: `1–200 chars`): Pass `next_cursor` from the previous page, unchanged.
- `limit` (`integer`, range: `1–100`): Number of items to return. Values outside 1-100 are clamped, and the response reports the limit actually applied.

## Response

**200**: List the workspace activity

- `data` (`object[]`, required)
- `data.id` (`string`, required)
- `data.action` (`string`, required): `<kind>.<verb>`, such as `resource.created`, `assistant.updated`, `widget.paused`, `site.synced`, `member.access_updated`.
- `data.summary` (`string`, required): The change in a few words, such as "Edited Support".
- `data.actor` (`object`, required)
- `data.actor.type` (`enum<string>`, required, one of: `member, api_key, system`)
- `data.actor.id` (`string,null`, required)
- `data.actor.name` (`string,null`, required)
- `data.actor.email` (`string,null`): Members only.
- `data.origin` (`string`, required): `app`, `api`, `cli`, `mcp`, `agent` (Lookio AI) or `system`.
- `data.target` (`object`, required)
- `data.target.type` (`string`, required)
- `data.target.id` (`string,null`, required)
- `data.target.name` (`string,null`, required): Its name at the time of the change.
- `data.details` (`Record<string, object>`, required): What changed, briefly: the fields edited (names only), counts, a sync's figures. Never content.
- `data.created_at` (`string`, required)
- `has_more` (`boolean`, required): True when another page follows: pass `next_cursor` back as `cursor`.
- `next_cursor` (`string,null`, required): Pass it back unchanged as `cursor`. Null on the last page.
- `limit` (`integer`, required): The page size actually applied.
- `request_id` (`string`, required)

```json
{
  "data": [
    {
      "id": "<string>",
      "action": "<string>",
      "summary": "<string>",
      "actor": {
        "type": "member",
        "id": null,
        "name": null,
        "email": null
      },
      "origin": "<string>",
      "target": {
        "type": "<string>",
        "id": null,
        "name": null
      },
      "details": {},
      "created_at": "<string>"
    }
  ],
  "has_more": true,
  "next_cursor": null,
  "limit": 123,
  "request_id": "<string>"
}
```

**400**: Possible codes: invalid_request, unknown_field, invalid_parameter, invalid_cursor

- `error` (`object`, required)
- `error.type` (`string`, required)
- `error.code` (`string`, required)
- `error.message` (`string`, required)
- `error.param` (`string`)
- `error.docs_url` (`string`, required)
- `error.action_url` (`string<uri>`)
- `request_id` (`string`, required)

```json
{
  "error": {
    "type": "<string>",
    "code": "<string>",
    "message": "<string>",
    "param": "<string>",
    "docs_url": "<string>",
    "action_url": "<string>"
  },
  "request_id": "<string>"
}
```

**401**: Possible codes: authentication_required, invalid_api_key, api_key_expired, api_key_revoked, invalid_access_key

- `error` (`object`, required)
- `error.type` (`string`, required)
- `error.code` (`string`, required)
- `error.message` (`string`, required)
- `error.param` (`string`)
- `error.docs_url` (`string`, required)
- `error.action_url` (`string<uri>`)
- `request_id` (`string`, required)

```json
{
  "error": {
    "type": "<string>",
    "code": "<string>",
    "message": "<string>",
    "param": "<string>",
    "docs_url": "<string>",
    "action_url": "<string>"
  },
  "request_id": "<string>"
}
```

**403**: Possible codes: insufficient_scope, feature_not_available, admin_required, permission_denied

- `error` (`object`, required)
- `error.type` (`string`, required)
- `error.code` (`string`, required)
- `error.message` (`string`, required)
- `error.param` (`string`)
- `error.docs_url` (`string`, required)
- `error.action_url` (`string<uri>`)
- `request_id` (`string`, required)

```json
{
  "error": {
    "type": "<string>",
    "code": "<string>",
    "message": "<string>",
    "param": "<string>",
    "docs_url": "<string>",
    "action_url": "<string>"
  },
  "request_id": "<string>"
}
```

**429**: Possible codes: rate_limited

- `error` (`object`, required)
- `error.type` (`string`, required)
- `error.code` (`string`, required)
- `error.message` (`string`, required)
- `error.param` (`string`)
- `error.docs_url` (`string`, required)
- `error.action_url` (`string<uri>`)
- `request_id` (`string`, required)

```json
{
  "error": {
    "type": "<string>",
    "code": "<string>",
    "message": "<string>",
    "param": "<string>",
    "docs_url": "<string>",
    "action_url": "<string>"
  },
  "request_id": "<string>"
}
```

**500**: Possible codes: internal_error

- `error` (`object`, required)
- `error.type` (`string`, required)
- `error.code` (`string`, required)
- `error.message` (`string`, required)
- `error.param` (`string`)
- `error.docs_url` (`string`, required)
- `error.action_url` (`string<uri>`)
- `request_id` (`string`, required)

```json
{
  "error": {
    "type": "<string>",
    "code": "<string>",
    "message": "<string>",
    "param": "<string>",
    "docs_url": "<string>",
    "action_url": "<string>"
  },
  "request_id": "<string>"
}
```

**Example request**

```bash
curl --request GET \
  --url 'https://api.lookio.app/v1/logs/activity' \
  --header 'Authorization: <api-key>'
```
