Audit logs overview
The audit log is the workspace's tamper-evident record of who did what, from where, and whether it succeeded. Use it for compliance reviews, access certifications, and security investigations, or point a SIEM or data warehouse at it for continuous export.
Every entry names an actor (who acted), a target (what they acted on), an event (what they did), an outcome (whether it succeeded), and a source (which surface the request came through). When the event changed something, old_value and new_value hold the state before and after.
Audit logs are read-only. There is no way to write, edit, or delete an entry through the API.
The audit log object
Attributes
idstring (uuid)Unique identifier for this audit log record. This is the id you pass to Get an audit log.
event_idstring (uuid)Identifier of the event the record describes, distinct from
id. Use it as the idempotency key when you ingest entries into another system so a re-read never double-counts.sequence_numberintegerAn ordering number assigned when the entry is written. Use it as a stable tiebreaker when two entries share the same
created_at.event_namestringThe specific event, for example
member.role_updated. Filter on it when you know exactly which action you're looking for.categorystringThe family the event belongs to. One of
auth,member,role,settings,integration,webhook,security, orinstance. Filter oncategorywhen you want a whole class of activity rather than one event name.outcomestringWhether the attempt succeeded. One of
successorfailure. Failed attempts are recorded too, so you can use the log to detect probing.sourcestringThe surface the request came through. One of
platform,api,graphql,auth,admin, orsystem.apimarks calls made with a token like yours;adminmarks actions taken through instance God Mode;systemmarks actions Plane took on its own.actor_typestringWhat kind of principal acted. One of
user,api_token,system, oranonymous.actor_idstring (uuid)The acting user. Nullable, because
systemandanonymousactors have no id. It matchesmember_idon the member rosters.actor_display_name,actor_emailstringThe actor's name and email captured at the time of the event. They are snapshots: a later rename or email change does not rewrite past entries.
target_typestringThe kind of thing that was acted on, for example
workspace_member.target_idstringIdentifier of the thing that was acted on.
target_display_namestringA human-readable label for the target, captured at the time of the event.
old_value,new_valueanyThe state before and after the change. Both are nullable: an event that changes nothing, such as a sign-in, has
nullin both.reasonstringA short explanation recorded alongside the event. Most informative on
outcome: failureentries.metadataanyAdditional structured context. The shape varies by
event_name, so don't assume a fixed structure when you parse it.ip_addressstringThe client IP the request came from. Nullable, because
systemevents have none.user_agentstringThe client's user agent string.
workspace_idstring (uuid)The workspace the event belongs to.
project_idstring (uuid)The project the event is scoped to, when it is scoped to one.
created_atstring (date-time)When the event was recorded. The date-range filters apply to this field.
{
"id": "5c7f1a08-2b64-4d39-9e17-0a3b8c6d2f41",
"event_id": "e0b41d97-6c23-4a8f-b512-9d7a0e3c5f68",
"sequence_number": 48213,
"event_name": "member.role_updated",
"category": "role",
"outcome": "success",
"source": "platform",
"actor_type": "user",
"actor_id": "16c61a3a-512a-48ac-b0be-b6b46fe6f430",
"actor_display_name": "Priya Raghavan",
"actor_email": "priya@example.com",
"target_type": "workspace_member",
"target_id": "3e8a5d17-9c40-4b2f-81d6-4a7f2b9e0c53",
"target_display_name": "Devansh Kapoor",
"old_value": { "role": "member" },
"new_value": { "role": "owner" },
"reason": "",
"metadata": { "workspace_slug": "my-team" },
"ip_address": "203.0.113.42",
"user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36",
"workspace_id": "d84c6f21-7a30-4e59-b6c8-1f9d5a2e7043",
"project_id": null,
"created_at": "2026-01-14T09:22:41.478363Z"
}{
"id": "9a2c4e76-1f58-4b03-8d69-5e0a7c3b1d24",
"event_id": "b7f3da41-8c05-4e92-a37d-2b6f1c9e5804",
"sequence_number": 48197,
"event_name": "auth.sign_in",
"category": "auth",
"outcome": "failure",
"source": "auth",
"actor_type": "anonymous",
"actor_id": null,
"actor_display_name": "",
"actor_email": "devansh@example.com",
"target_type": "user",
"target_id": "7f2b9e04-6c1d-4a58-9e3b-0d4c8a2f6b71",
"target_display_name": "Devansh Kapoor",
"old_value": null,
"new_value": null,
"reason": "invalid_credentials",
"metadata": { "attempt": 3 },
"ip_address": "198.51.100.7",
"user_agent": "curl/8.6.0",
"workspace_id": "d84c6f21-7a30-4e59-b6c8-1f9d5a2e7043",
"project_id": null,
"created_at": "2026-01-14T08:57:03.220914Z"
}Endpoints
| Method | Path | Description |
|---|---|---|
GET | /api/v2/workspaces/{slug}/audit-logs/ | List audit logs |
GET | /api/v2/workspaces/{slug}/audit-logs/{pk}/ | Get an audit log |
Both require the workspaces.audit_logs:read scope. There is no POST, PATCH, or DELETE. Plane writes the entries, and no caller can edit them.
Querying for an investigation
The list endpoint supports these filters, which combine with AND:
| Question | Query |
|---|---|
| What happened in this window? | ?created_after=2026-01-01T00:00:00Z&created_before=2026-02-01T00:00:00Z |
| What did this person do? | ?actor_id=16c61a3a-512a-48ac-b0be-b6b46fe6f430 |
| Every permission change this quarter | ?category=role&created_after=2026-01-01T00:00:00Z |
| Failed attempts only | ?outcome=failure |
| Everything touching one object | ?target_type=workspace_member&target_id=3e8a5d17-9c40-4b2f-81d6-4a7f2b9e0c53 |
| Activity from one address | ?ip_address=198.51.100.7 |
| One specific action | ?event_name=member.role_updated |
For a full export, add ?paginate=cursor and follow next_cursor. Cursor pagination skips the COUNT(*) on every page and stays stable as new entries arrive. See List audit logs for details.
Reading an entry
actor_display_name,actor_email, andtarget_display_nameare snapshots recorded at event time, not looked up when you read the entry. The entry still names the person as they were, even after a rename or offboarding, which is what makes the log usable as evidence.- Entries with
outcome: failureare often what a security review needs. A burst of them from oneip_addresswithcategory: authpoints to a credential-stuffing attempt. old_valueandnew_valueare free-form. They describe the change for thatevent_nameand don't follow a fixed schema, so you can display or diff them but shouldn't require particular keys.sourceseparates people from tokens.platformis the Plane app,apiis a REST client,adminis instance God Mode, andsystemis Plane acting on its own. Combinesource: apiwithactor_type: api_tokento isolate automated activity.
Correlate a 409 with a settings change
If clients suddenly start getting 409 work_item_types_managed_at_workspace or work_item_types_managed_at_project, someone toggled the work item type mode. Query ?category=settings around the time the failures started to find the change and the actor behind it. See Work item type modes and Update workspace features.
Related
- List audit logs
- Get an audit log
- Members overview: resolve
actor_idto a person - Pagination: cursor pagination for exports

