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

# Audit logs

Audit logs provide a queryable record of all actions in your organization: who performed an operation, on which resource, and when. Use them for security monitoring, compliance reporting, and troubleshooting.

> [!NOTE]
>
> Available on the Enterprise plan. [Contact sales](https://ona.com/contact/sales) to learn more.

## Access requirements

Organization admins and members with the [Audit Log Reader](https://ona.com/docs/ona/organizations/organization-roles.md#audit-log-reader) role can access audit logs. Regular members cannot access audit logs, even for resources they own.

## Entry structure

Each entry contains:

* **Actor**: Who (user, service account, runner, or system)
* **Subject**: What resource, with its public type when one exists
* **Action**: Operation performed (e.g., "Environment created")
* **Timestamp**: When
* **Organization**: Which org
* **Kind**: The coarse event family used for querying and rendering

## What gets logged

Audit logs focus on security-relevant and human-meaningful activity. This includes approved resource lifecycle and administration changes, relevant credential activity, and security activity reported from environments.

| Category | Resources |
| - | - |
| Infrastructure | Environments, Runners, Projects, Environment Classes |
| Execution | Tasks, Services, Workflows, Agents, and their executions |
| Security | Users, Service Accounts, Tokens, Secrets, SSO configuration, and security policies |
| Organization | [Policies](https://ona.com/docs/ona/organizations/policies/overview.md), Domain Verification, Custom Domains, Billing |
| Integrations | SCM/LLM integrations and Prompts |

Routine phase, status, heartbeat, reconciliation, bookkeeping, duplicate, and cascade activity is omitted. Not every database update produces an audit entry.

New entries use one of these kinds:

* `AUDIT_LOG_ENTRY_KIND_RESOURCE_CHANGE`: resource lifecycle and administration
* `AUDIT_LOG_ENTRY_KIND_CREDENTIAL_ACCESS`: relevant credential issuance, retrieval, replacement, or propagation
* `AUDIT_LOG_ENTRY_KIND_ENVIRONMENT_VETO`: activity reported by Veto from inside an environment

> [!NOTE]
>
> Veto Exec enforcement entries are in preview and only appear for organizations where this preview is enabled.

Veto Exec events appear as environment audit entries when enabled. Blocked and audited executions both use `AUDIT_LOG_ENTRY_KIND_ENVIRONMENT_VETO`; the action and `details.vetoExec.action` distinguish the outcome.

The action includes the kernel-resolved filename and full executable digest when reported:

* Filename and digest: `Veto Exec blocked: <filename> (<hash>)`
* Filename only: `Veto Exec blocked: <filename>`
* Digest only: `Veto Exec blocked: <hash>`
* Neither: `Veto Exec blocked an executable`

Audited events use `audited` in place of `blocked`. The entry timestamp records when Ona received the event. Veto Exec details include the reported event data except `process.cmdline`, which is omitted because it may contain credentials or other sensitive data.

**Actor types:**

| Type | Description |
| - | - |
| `PRINCIPAL_USER` | Human users |
| `PRINCIPAL_SERVICE_ACCOUNT` | Service accounts |
| `PRINCIPAL_RUNNER` | Runner infrastructure |
| `PRINCIPAL_ENVIRONMENT` | Environment processes |
| `PRINCIPAL_RUNNER_MANAGER` | Runner management systems |
| `PRINCIPAL_ACCOUNT` | Account-level operations |

## Querying audit logs

### CLI

The `ona` CLI (pre-installed in all environments) is the simplest way to query audit logs.

```bash theme={null}
# View recent entries (default: 100)
ona audit-logs

# Specify limit
ona audit-logs --limit=500
```

**Filter by actor:**

```bash theme={null}
# By user ID
ona audit-logs --actor-id="d2c94c27-3b76-4a42-b88c-95a85e392c68"

# By actor type
ona audit-logs --actor-principal="user"
ona audit-logs --actor-principal="service_account"
```

**Filter by subject:**

```bash theme={null}
# By resource ID
ona audit-logs --subject-id="01951d94-d6ac-7edf-9021-a044cfd1908f"

# By resource type
ona audit-logs --subject-type="environment"
ona audit-logs --subject-type="project"
```

**Filter by time range:**

```bash theme={null}
# Logs from a specific date onward
ona audit-logs --from="2025-01-01T00:00:00Z"

# Logs within a date range
ona audit-logs --from="2025-01-01T00:00:00Z" --to="2025-01-31T23:59:59Z"
```

**Combine filters:**

```bash theme={null}
ona audit-logs --subject-type="environment" --actor-principal="user" --limit=500
```

**Export formats:**

```bash theme={null}
# JSON
ona audit-logs --format=json --limit=1000 > audit-logs.json

# YAML
ona audit-logs --format=yaml --limit=1000 > audit-logs.yaml
```

**Example output:**

```
SUBJECT ID                           SUBJECT TYPE              ACTOR ID                             ACTOR PRINCIPAL    ACTION                                                    CREATED AT
01951d94-d6ac-7edf-9021-a044cfd1908f RESOURCE_TYPE_ENVIRONMENT d2c94c27-3b76-4a42-b88c-95a85e392c68 PRINCIPAL_USER     started environment                                         2025-02-21T12:10:05Z
0194f5dd-01ca-75f4-a200-74381ed43f86 RESOURCE_TYPE_PROJECT     d2c94c27-3b76-4a42-b88c-95a85e392c68 PRINCIPAL_USER     Project created                                           2025-02-21T11:45:22Z
```

### API

For programmatic access and SIEM integration, use the REST API.

```bash theme={null}
export GITPOD_API_KEY="your-personal-access-token"
```

The examples use `https://app.gitpod.io`. If your organization uses a custom domain, replace this origin with your organization's dashboard domain.

**Basic request:**

```bash theme={null}
curl https://app.gitpod.io/api/gitpod.v1.EventService/ListAuditLogs \
     -H 'Content-Type: application/json' \
     -H "Authorization: Bearer $GITPOD_API_KEY" \
     -d '{"pagination": {"pageSize": 100}}'
```

**Filter by actor:**

```bash theme={null}
curl https://app.gitpod.io/api/gitpod.v1.EventService/ListAuditLogs \
     -H 'Content-Type: application/json' \
     -H "Authorization: Bearer $GITPOD_API_KEY" \
     -d '{
       "filter": {
         "actorIds": ["d2c94c27-3b76-4a42-b88c-95a85e392c68"],
         "actorPrincipals": ["PRINCIPAL_USER"]
       },
       "pagination": {"pageSize": 100}
     }'
```

**Filter by subject:**

```bash theme={null}
curl https://app.gitpod.io/api/gitpod.v1.EventService/ListAuditLogs \
     -H 'Content-Type: application/json' \
     -H "Authorization: Bearer $GITPOD_API_KEY" \
     -d '{
       "filter": {
         "subjectTypes": ["RESOURCE_TYPE_ENVIRONMENT", "RESOURCE_TYPE_PROJECT"]
       },
       "pagination": {"pageSize": 100}
     }'
```

**Pagination:**

```bash theme={null}
# First request - save token
curl https://app.gitpod.io/api/gitpod.v1.EventService/ListAuditLogs \
     -H 'Content-Type: application/json' \
     -H "Authorization: Bearer $GITPOD_API_KEY" \
     -d '{"pagination": {"pageSize": 100}}' \
     | jq -r '.pagination.nextToken' > next_token.txt

# Subsequent request - use token
curl https://app.gitpod.io/api/gitpod.v1.EventService/ListAuditLogs \
     -H 'Content-Type: application/json' \
     -H "Authorization: Bearer $GITPOD_API_KEY" \
     -d "{\"pagination\": {\"pageSize\": 100, \"token\": \"$(cat next_token.txt)\"}}"
```

**Response format:**

```json theme={null}
{
  "entries": [
    {
      "id": "01951d94-d6ac-7edf-9021-a044cfd1908f",
      "actorId": "d2c94c27-3b76-4a42-b88c-95a85e392c68",
      "actorPrincipal": "PRINCIPAL_USER",
      "subjectId": "0194f5dd-01ca-75f4-a200-74381ed43f86",
      "subjectType": "RESOURCE_TYPE_ENVIRONMENT",
      "action": "started environment",
      "kind": "AUDIT_LOG_ENTRY_KIND_RESOURCE_CHANGE",
      "createdAt": "2025-02-21T12:10:05Z"
    }
  ],
  "pagination": {
    "nextToken": "eyJpZCI6IjAxOTUxZDk0LWQ2YWMtN2VkZi05MDIxLWEwNDRjZmQxOTA4ZiJ9"
  }
}
```

`ListAuditLogs` returns summary fields and the kind. Historical Veto Exec entries retain their deprecated blocked or audited kind. Other historical entries with a missing or unrecognized stored kind are returned as `AUDIT_LOG_ENTRY_KIND_UNSPECIFIED`; they are not removed from pagination. An entry whose internal subject has no public resource-type mapping uses `RESOURCE_TYPE_UNSPECIFIED` while retaining its subject ID. The response does not include the `details` payload.

**Retrieve one entry with typed details:**

```bash theme={null}
curl https://app.gitpod.io/api/gitpod.v1.EventService/GetAuditLog \
     -H 'Content-Type: application/json' \
     -H "Authorization: Bearer $GITPOD_API_KEY" \
     -d '{"auditLogEntryId": "01951d94-d6ac-7edf-9021-a044cfd1908f"}'
```

For a Veto Exec entry, the response contains a `vetoExec` details case:

```json theme={null}
{
  "entry": {
    "id": "01951d94-d6ac-7edf-9021-a044cfd1908f",
    "actorId": "0193e2f2-d0b5-7d52-87eb-235deadaf625",
    "actorPrincipal": "PRINCIPAL_ENVIRONMENT",
    "subjectId": "0193e2f2-d0b5-7d52-87eb-235deadaf625",
    "subjectType": "RESOURCE_TYPE_ENVIRONMENT",
    "action": "Veto Exec blocked: /usr/bin/curl (sha256:abcdef)",
    "createdAt": "2026-07-17T12:00:02Z",
    "kind": "AUDIT_LOG_ENTRY_KIND_ENVIRONMENT_VETO"
  },
  "details": {
    "vetoExec": {
      "environmentId": "0193e2f2-d0b5-7d52-87eb-235deadaf625",
      "executable": "sha256:abcdef",
      "filename": "/usr/bin/curl",
      "action": "KERNEL_CONTROLS_ACTION_BLOCK",
      "process": {
        "pid": 1234,
        "tid": 1234,
        "name": "curl",
        "startedAt": "2026-07-17T12:00:00Z",
        "ppid": 1000,
        "pgid": 1000,
        "sid": 1000
      },
      "timestamp": "2026-07-17T12:00:01Z"
    }
  }
}
```

The `details` field is optional. Clients must handle entries without details and unknown future detail types.

## Real-time event monitoring

For real-time notifications instead of historical queries, use the **WatchEvents API**. This streaming endpoint pushes events as they occur. Use it for dashboards, automation triggers, and live monitoring.

### Key differences

| Feature | ListAuditLogs API | WatchEvents API |
| - | - | - |
| **Purpose** | Historical analysis | Real-time monitoring |
| **Access** | Organization Admins and Audit Log Readers | Users with read access to resources |
| **Data** | Full audit trail with actor info | Resource changes only |
| **Format** | Paginated queries | Streaming events |
| **Use Case** | Compliance, security review | Dashboards, automation |

### WatchEvents with Python

Install the official SDK:

```bash theme={null}
pip install gitpod-sdk
```

> [!NOTE]
>
> The `GITPOD_API_KEY` environment variable should contain your [Personal Access Token](https://ona.com/docs/ona/integrations/personal-access-token.md). You only receive events for resources you have read access to.

**Watch organization events:**

```python theme={null}
import os
from gitpod import Gitpod

client = Gitpod(bearer_token=os.environ.get("GITPOD_API_KEY"))

# Stream organization-wide events (projects, runners, environments)
for event in client.events.watch(organization=True):
    print(f"{event.operation} on {event.resource_type}: {event.resource_id}")
```

**Watch environment-specific events:**

```python theme={null}
# Stream events for a specific environment (includes tasks, services)
for event in client.events.watch(environment_id="01951d94-d6ac-7edf-9021-a044cfd1908f"):
    print(f"Environment event: {event.operation} on {event.resource_type}")
```

**Async usage:**

```python theme={null}
import asyncio
from gitpod import AsyncGitpod

client = AsyncGitpod(bearer_token=os.environ.get("GITPOD_API_KEY"))

async def watch_events():
    async for event in await client.events.watch(organization=True):
        print(f"{event.operation} on {event.resource_type}")

asyncio.run(watch_events())
```

### Event operations

* `RESOURCE_OPERATION_CREATE` - Resource created
* `RESOURCE_OPERATION_UPDATE` - Resource modified
* `RESOURCE_OPERATION_UPDATE_STATUS` - Status changed only
* `RESOURCE_OPERATION_DELETE` - Resource deleted

### Other languages

For languages without an official SDK, use gRPC/Connect-compatible clients:

**Endpoint:** `POST https://app.gitpod.io/api/gitpod.v1.EventService/WatchEvents`

**Headers:**

* `Content-Type: application/json`
* `Accept: application/jsonl`
* `Authorization: Bearer YOUR_API_KEY`

**Request body (organization scope):**

```json theme={null}
{"organization": true}
```

**Request body (environment scope):**

```json theme={null}
{"environmentId": "01951d94-d6ac-7edf-9021-a044cfd1908f"}
```

See the [WatchEvents API reference](https://ona.com/docs/api-reference/resources/events/methods/watch/) for details.

## Common use cases

### Security monitoring

```bash theme={null}
# Monitor secret operations
ona audit-logs --subject-type="secret" --subject-type="user_secret" --subject-type="organization_secret"

# Track SSO changes
ona audit-logs --subject-type="sso_config"

# Review token management
ona audit-logs --subject-type="personal_access_token"
```

### Compliance reporting

```bash theme={null}
# Export user actions
ona audit-logs --actor-principal="user" --format=json --limit=10000 > user-actions.json

# Track group changes
ona audit-logs --subject-type="group" --format=json > group-changes.json
```

### Troubleshooting

```bash theme={null}
# Recent environment changes
ona audit-logs --subject-type="environment" --limit=500

# Project configuration updates
ona audit-logs --subject-type="project" --actor-principal="user" --limit=500

# Workflow execution history
ona audit-logs --subject-type="workflow_execution" --limit=500
```

### Resource lifecycle tracking

```bash theme={null}
# Runner lifecycle
ona audit-logs --subject-type="runner" --limit=500

# Environment creation/deletion patterns
ona audit-logs --subject-type="environment" --limit=1000
```

## Best practices

**Regular monitoring**

* Export audit logs periodically to external storage for long-term retention
* Integrate with your SIEM for centralized security monitoring
* Establish baseline patterns and investigate anomalies

**Access control**

* Grant Organization Admin role only to users who need audit log access
* Use dedicated service accounts for automated log collection
* Rotate Personal Access Tokens regularly

**Filtering & analysis**

* Prioritize monitoring security-sensitive resource types
* Combine multiple filter criteria to narrow results
* Export to JSON/YAML for integration with analysis tools

## Limitations

* **Retention**: Audit logs are retained according to your organization's data retention policy
* **Rate limits**: API requests subject to standard rate limiting
* **Filter limits**: Maximum 25 values per filter type per request
* **Pagination**: Maximum 100 entries per page


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