> For AI agents: the complete Sanity documentation index is available at [https://www.sanity.io/docs/llms.txt](https://www.sanity.io/docs/llms.txt).

# Retrieve management events with the Activity Log API

Retrieve management activity events for Sanity users, projects, and organizations.

> [!NOTE]
> Need to access content activities?
> This API cannot be used to retrieve activities for content. Use the [History API](https://www.sanity.io/docs/http-reference/history) to retrieve transaction events for documents.

## Basic usage

The Activity Log API operates on the same [versioning](https://www.sanity.io/docs/content-lake/api-versioning) and [authentication](https://www.sanity.io/docs/content-lake/http-auth) system as as other APIs.

Base URL: `https://api.sanity.io`

### Version requirement

The Activity Log API requires API version `2021-02-01`.

### Token requirements

The Activity Log API requires an **Access Manager robot token**. User session cookies (`sanitySession`) will not work with this endpoint.

Your token only returns activity for organizations and projects that the robot token can access. If you do not pass `organizationId` or `projectId`, the API returns activity across your allowed organizations and projects.

Set your token before running the examples:

```bash
export SANITY_AUTH_TOKEN="<your-token>"
```

All requests use bearer token authentication:

```bash
curl -sS \
  -H "Authorization: Bearer $SANITY_AUTH_TOKEN" \
  "https://api.sanity.io/v2021-02-01/activity?limit=10"
```

### Available formats

Use the JSON endpoint for app integrations:

```text
GET /v2021-02-01/activity
```

Use the CSV endpoint for exports:

```text
GET /v2021-02-01/activity/export/csv
```

The CSV endpoint uses the same filters as the JSON endpoint.

## Get user activity

Use `actorId` for events performed by a user:

```bash
curl -sS \
  -H "Authorization: Bearer $SANITY_AUTH_TOKEN" \
  "https://api.sanity.io/v2021-02-01/activity?actorId=<sanity-user-id>&limit=25"
```

Use `userId` for events where the user is the target of the activity:

```bash
curl -sS \
  -H "Authorization: Bearer $SANITY_AUTH_TOKEN" \
  "https://api.sanity.io/v2021-02-01/activity?userId=<sanity-user-id>&limit=25"
```

You can combine these with `projectId` to get activity for a person within a
project:

```bash
curl -sS \
  -H "Authorization: Bearer $SANITY_AUTH_TOKEN" \
  "https://api.sanity.io/v2021-02-01/activity?actorId=<sanity-user-id>&projectId=<project-id>&limit=25"
```

## Get organization activity

Use `organizationId` for organization-level activity:

```bash
curl -sS \
  -H "Authorization: Bearer $SANITY_AUTH_TOKEN" \
  "https://api.sanity.io/v2021-02-01/activity?organizationId=<organization-id>&limit=25"
```

An `organizationId` query returns organization-level events. To retrieve project activity inside an organization, query the relevant projects with `projectId`. If you are using a user token and want all activity the user can see, omit both `organizationId` and `projectId`.

Do not combine `organizationId` and `projectId` to mean "organization activity plus project activity." Different filter names are combined, so the result must match both filters.

## Get project activity

Use `projectId` for project activity:

```bash
curl -sS \
  -H "Authorization: Bearer $SANITY_AUTH_TOKEN" \
  "https://api.sanity.io/v2021-02-01/activity?projectId=<project-id>&limit=25"
```

You can pass the same filter more than once to match any of the values:

```bash
curl -sS \
  -H "Authorization: Bearer $SANITY_AUTH_TOKEN" \
  "https://api.sanity.io/v2021-02-01/activity?projectId=<project-id-a>&projectId=<project-id-b>&limit=25"
```

## Paginate results

The JSON endpoint defaults to `limit=10`. Values above `100` are capped at
`100`.

Use `offset` to skip matching events:

```bash
# First page
curl -sS \
  -H "Authorization: Bearer $SANITY_AUTH_TOKEN" \
  "https://api.sanity.io/v2021-02-01/activity?projectId=<project-id>&limit=25&offset=0"

# Second page
curl -sS \
  -H "Authorization: Bearer $SANITY_AUTH_TOKEN" \
  "https://api.sanity.io/v2021-02-01/activity?projectId=<project-id>&limit=25&offset=25"
```

Offset pagination can shift if new events are created while you page through
results. For more stable exports or audits, use `startTime` and `endTime` to
work through fixed time windows.

```bash
curl -sS \
  -H "Authorization: Bearer $SANITY_AUTH_TOKEN" \
  "https://api.sanity.io/v2021-02-01/activity?projectId=<project-id>&startTime=2026-06-01T00:00:00Z&endTime=2026-06-09T23:59:59Z&limit=100"
```

## Export CSV

CSV exports use the same filters as JSON responses.

```bash
curl -sS \
  -H "Authorization: Bearer $SANITY_AUTH_TOKEN" \
  -o activity-log.csv \
  "https://api.sanity.io/v2021-02-01/activity/export/csv?projectId=<project-id>&limit=5000"
```

CSV limits are different from JSON limits:

- If `limit` is omitted, CSV exports default to `10000` events.
- Values above `50000` are capped at `50000`.
- Explicit values less than or equal to `10` use the CSV default of `10000`.
- For a small CSV test request, use `limit=11` or higher.

CSV headers are sorted alphabetically. Metadata keys appear as dynamic
`metadata.<key>` columns when present in the returned events.

## Filter results

Use the documented filters below to scope activity log results by user,
project, organization, activity type, and time range.

Repeated values for the same filter are matched as "any of these values." For
example, this returns events with either activity type:

```bash
curl -sS \
  -H "Authorization: Bearer $SANITY_AUTH_TOKEN" \
  "https://api.sanity.io/v2021-02-01/activity?action=project.name.edit&action=organization.name.edit&limit=25"
```

Different filter names are combined. For example, this returns project activity
with the matching action during the specified time window:

```bash
curl -sS \
  -H "Authorization: Bearer $SANITY_AUTH_TOKEN" \
  "https://api.sanity.io/v2021-02-01/activity?projectId=<project-id>&action=project.name.edit&startTime=2026-06-01T00:00:00Z&endTime=2026-06-09T23:59:59Z&limit=25"
```

### Common filters

| Filter | Use it to |
| --- | --- |
| actorId | Find events performed by a user. Use actorId=null for events without an actor. |
| userId | Find events where a user is the target. |
| projectId | Find project activity. |
| organizationId | Find organization-level activity. |
| action | Find specific activity types. |
| startTime / endTime | Restrict results to a time range. Use RFC 3339 timestamps. |
| limit / offset | Page through matching events. |

## Error responses

Error responses use this shape:

```json
{
  "code": 400,
  "status": "Bad Request",
  "message": "duplicate parameter: limit"
}
```

Common errors:

| Status | When it happens |
| --- | --- |
| 400 | Unknown filter, duplicate single-value filter, invalid timestamp, or invalid number. |
| 401 | Missing token, invalid token, or access to the requested activity data is not allowed. |
| 500 | The API could not complete the request. |
| 503 | The request timed out or was canceled. |

These documented filters cannot be repeated:

```text
limit
offset
startTime
endTime
```

For example, `limit=10&limit=20` returns `400`.

## Additional resources

For a full list of available options for the endpoints mentioned in this article, see the [Activity Log API reference documentation](https://www.sanity.io/docs/http-reference/activity-log).

