---
title: "Search Audit Logs"
description: "Returns the activity of a workspace, newest first. Send the cursor from a response to get the next page, until hasMore is false. See the Audit Logs API…"
canonical: "https://docs.softr.io/softr-api/audit-logs-api/search-audit-logs"
updated: "2026-11-06"
---

# Search Audit Logs

Returns the activity of a workspace, newest first. Send the `cursor` from a response to get the next page, until `hasMore` is `false`. See the [Audit Logs API overview](/softr-api/audit-logs-api) for the token it needs, paging, polling and the actions per entity type.

```http
POST https://studio-api.softr.io/v1/api/workspaces/{workspaceId}/audit-logs/search
```

## Authorizations

- `Softr-Api-Key` (API key, in header, required)

## Path parameters

- `workspaceId` (`string`, required): The workspace ID. [Get Databases](/softr-api/softr-database-api/databases/get-databases) returns it as `workspaceId` on every database.

## Body

`application/json`

- `entityTypes` (`enum<string>[]`): Return only these entity types. Empty or missing means all of them.
- `userIds` (`string[]`, items: `≤ 50 items`): Return only activity by these users. At most 50 ids.
- `entityIds` (`Record<string, string[]>`): Return only activity on these entities, keyed by entity type. At most 50 ids per type.
- `startDate` (`string<date-time>`): Return only activity at or after this time (ISO 8601, inclusive).
- `endDate` (`string<date-time>`): Return only activity at or before this time (ISO 8601, inclusive).
- `cursor` (`string`): The `cursor` from the previous page. Leave it out for the first page. Keep the other fields the same while you page.
- `size` (`integer`, default: `50`, range: `1–50`): Entries per page. Values above 50 are lowered to 50.

## Response

**200**: A page of audit log entries.

- `entries` (`object[]`): Newest first.
- `entries.id` (`string`): The entry ID.
- `entries.entityType` (`enum<string>`, one of: `APP, DATABASE, WORKSPACE, WORKFLOW, AGENT, INTEGRATION`): The kind of thing the activity happened to.
- `entries.entityId` (`string`): The ID of the app, database, workflow, agent, integration or workspace.
- `entries.entityName` (`string | null`): The name of the entity.
- `entries.entityDeleted` (`boolean`): `true` when the entity no longer exists.
- `entries.action` (`string`): What happened, for example `APP_PUBLISHED`, `TABLE_CREATED` or `WORKFLOW_DISABLED`. See the overview for the actions per entity type. New values can appear at any time.
- `entries.userId` (`string | null`): The ID of the user who did it.
- `entries.userName` (`string | null`): The user's name.
- `entries.userEmail` (`string | null`): The user's email.
- `entries.details` (`Record<string, unknown>`): Extra information about the activity. Its shape depends on the action.
- `entries.createdAt` (`string<date-time>`): When it happened (ISO 8601, UTC).
- `cursor` (`string | null`): Pass it back to get the next page. `null` on the last page.
- `hasMore` (`boolean`): `true` when more entries exist after this page.

```json
{
  "entries": [
    {
      "id": "c4e8a1d2-6b3f-4f9a-a7e5-2d1c0b9a8f7e",
      "entityType": "APP",
      "entityId": "3f1c2a9e-8b4d-4e7a-9c21-5d6e7f8a9b0c",
      "entityName": "Client Portal",
      "entityDeleted": false,
      "action": "APP_PUBLISHED",
      "userId": "7a2b9c4d-1e3f-4a5b-8c6d-9e0f1a2b3c4d",
      "userName": "Ada Lovelace",
      "userEmail": "ada@example.com",
      "details": null,
      "createdAt": "2026-11-02T14:03:27Z"
    }
  ],
  "cursor": "eyJhcHAiOnsiY3JlYXRlZEF0IjoiMjAyNi0xMS0wMlQxNDowMzoyN1oifX0",
  "hasMore": true
}
```

**400**: The request body is invalid, for example an unknown entity type or more than 50 ids in a filter.

- `code` (`string`): The HTTP status name.
- `message` (`string`): What went wrong, in plain words.

```json
{
  "code": "Bad Request",
  "message": "userIds must not exceed 50 values"
}
```

**401**: The `Softr-Api-Key` header is missing, or the token is unknown, revoked or expired.

- `code` (`string`): The HTTP status name.
- `message` (`string`): What went wrong, in plain words.

```json
{
  "code": "Unauthorized",
  "message": "Invalid API key."
}
```

**403**: The token or its user cannot read this audit log: a legacy API key, a token without read access to applications, databases and workflows on the whole workspace, a user who is not an owner or admin, or a workspace without audit logs.

- `code` (`string`): The HTTP status name.
- `message` (`string`): What went wrong, in plain words.

```json
{
  "code": "Forbidden",
  "message": "Only workspace owners and admins can read the audit log."
}
```

**429**: Too many requests. Wait a moment and retry.

- `code` (`string`): The HTTP status name.
- `message` (`string`): What went wrong, in plain words.

```json
{
  "code": "Too many requests",
  "message": "Request limit exceeded!"
}
```

**503**: Part of the activity is temporarily unavailable. Retry the same request, with the same cursor.

- `code` (`string`): The HTTP status name.
- `message` (`string`): What went wrong, in plain words.

```json
{
  "code": "Service Unavailable",
  "message": "Some audit log activity is temporarily unavailable. Retry the request with the same cursor."
}
```

**Example request**

```bash
curl --request POST \
  --url 'https://studio-api.softr.io/v1/api/workspaces/<workspaceId>/audit-logs/search' \
  --header 'Softr-Api-Key: <api-key>' \
  --header 'Content-Type: application/json' \
  --data '{
  "entityTypes": [
    "APP"
  ],
  "userIds": [
    "<string>"
  ],
  "entityIds": {
    "APP": [
      "3f1c2a9e-8b4d-4e7a-9c21-5d6e7f8a9b0c"
    ]
  },
  "startDate": "2026-11-01T00:00:00Z",
  "endDate": "2026-11-02T00:00:00Z",
  "cursor": "<string>",
  "size": 50
}'
```
