> ## Documentation Index
> Fetch the complete documentation index at: https://docs.open.cx/llms.txt
> Use this file to discover all available pages before exploring further.

# Audit Logs API

> Read your workspace audit trail over the API: sign-ins, sign-outs and every change, with filters and stable cursor paging. Use it to export or monitor activity.

The Audit Logs API returns your workspace's audit trail, newest first. It covers teammate sign-ins and sign-outs, and every change made in the dashboard, over the API, or by automations. See [Audit logs overview](https://docs.open.cx/security/audit-logs.md) for what the log records.

## Key Concepts

* **Scope required** — `audit-logs:read`
* **Event** — `event_type` says what happened (`login`, `logout`, `create`, `update`, `api_key_create`, …). `entity_type` and `entity_id` say what it happened to
* **Actor** — `actor_type` is `user`, `system` or `api`. For an API key, `api_key` names the key and who created it
* **Changes** — `changes.before` and `changes.after` hold the fields that changed, when the event has them
* **Read-only** — entries can't be edited or deleted

## Sign-ins and sign-outs

A sign-in is an event with `entity_type: "user"` and `event_type: "login"`. `metadata.method` says how the teammate signed in: `google`, `microsoft`, `sso`, `partner`, `password` or `other`. For `sso`, `metadata.sso_provider_id` names the connection.

A sign-out has `event_type: "logout"`. `metadata.reason` says why it ended:

| `reason` | Meaning |
| - | - |
| `signed_out` | The teammate signed out. `actor_type` is `user` |
| `expired` | The sign-in expired. Recorded the next time that browser loaded the dashboard |
| `revoked` | The sign-in was ended before it expired, including by the teammate's removal from another workspace |
| `removed_from_org` | An admin of this workspace removed the teammate. `metadata.revoked_sessions` counts the sign-ins ended |
| `deprovisioned` | This workspace's identity provider deprovisioned the teammate |
| `deactivated` | The teammate was deactivated in every organization they belong to, by an admin or the identity provider |
| `idle_timeout` | The teammate didn't use the dashboard for longer than allowed. A live call or dictation counts as use |

An Open support teammate who stays inactive in your workspace leaves it instead of being signed out: `event_type: "idle_exit"`, `entity_type: "user"`, with `metadata.idle_minutes` set to the limit that applied.

`metadata.user_email` always names the teammate, including when the system ended the sign-in. `ip_address` and `user_agent` are the request that signed in or out, when there was one.

## Contact channel restrictions

Every change to a contact's [restricted channels](https://docs.open.cx/contacts/manage-contacts.md#restricted-channels) writes one event with `entity_type: "consumer"`, `entity_id` set to the contact ID, `event_type: "contact_channel_restrictions_update"` and `event_category: "data"`. `changes.before.restricted_channels` and `changes.after.restricted_channels` hold the lists. Setting the list a contact already has writes nothing.

`metadata.source` says where the change came from: `dashboard`, `api`, `mcp` or `workflow`. A change through an API key has `actor_type: "api"` and names the key. A workflow change has `actor_type: "system"`, with `metadata.workflow_id` and `metadata.workflow_run_id`. To follow one contact, filter with `entityType=consumer&entityId=<contact id>`.

## Filtering

Every filter is optional, and filters combine. `eventType`, `entityType` and `eventCategory` accept one value, or the same parameter repeated to match any of several:

```bash theme={"dark"}
curl "https://api.open.cx/audit-logs?eventType=login&eventType=logout&startDate=2026-09-01T00:00:00Z" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

Use `entityId` to follow one thing, for example a workflow with `entityType=workflow&entityId=<workflow id>`. Use `userId` to follow one teammate: everything they did, plus the sign-outs the system ended for them.

## Paging

Responses carry `pagination` (`total`, `page`, `limit`, `totalPages`) and `next_cursor`.

* **Cursor paging (recommended)** — pass `next_cursor` back as `cursor` until it is `null`. Events written while you page never shift the pages, so nothing is skipped or read twice. When `cursor` is set, `page` is ignored
* **Page numbers** — `page` and `limit` keep working. Pages can shift if new events arrive between requests

`limit` is 20 by default and at most 100. `page` must be at least 1, and `cursor` must come from this workspace. Anything else is a `400`.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.