Sign Up

Audit Logs

View and monitor all user actions across your Daytona organization.

Audit logs provide a detailed record of user and system activity across your organization. Each entry records an action, the actor and credential behind it, the resource it targeted, and the result.

Reading audit logs requires the audit read organization permission. Administrators hold it, as does the dedicated Auditor role, which grants read access to the log without the ability to turn logging off. Contact your organization administrator to get access to audit logs.

Audit logs are retained for 365 days.

Use cases

Audit logs are used when an organization must know who did what, when, and with which credential.

  • Security audits. Unauthorized access or sandbox misuse is traced to a user, an API key, an IP address, and a time. The key prefix identifies the key without exposing it. Entries may also include the user agent of the request.

  • Debugging. Sandbox lifecycle problems, such as a failed start, are traced to the request that caused them. Each entry carries the HTTP status code and the error message. Entries for a failed action show the Error outcome, which covers 4xx and 5xx codes.

  • Compliance reviews. Actions across the organization stay on record for 365 days. Management-plane actions, such as changes to members and credentials, are always recorded and cannot be turned off. Earlier entries stay readable until retention ends, even after workload-plane capture is turned off.

  • Access reviews. Member role changes and removals, invitations, and the creation and role updates of service accounts are recorded with the previous and the new roles. A review shows who granted which access and when. Role changes that were only validated carry a dry run flag in their metadata.

  • Scripted reviews. The CLI and the API filter entries by action, target, actor, status code, and time range. A script pages through the results to collect the entries for a review. Each request accepts at most 10 filters and returns up to 200 entries per page.

Access from Dashboard

  1. Go to Daytona Dashboard ↗

Access the audit logs page directly from Daytona Dashboard ↗. The audit logs page displays a list of all audit logs for your organization, including the following columns:

ColumnDescription
TimeThe timestamp of the action.
ActorThe user or API key that performed the action.
ActionThe action performed.
TargetThe resource affected by the action.
OutcomesThe result of the action.

Select any row to open the full log entry, including its metadata. On plans other than Enterprise, the table is disabled and empty under an Enterprise notice.

To filter audit logs by time, use the date range picker in the top-left corner of the page. The filter menu next to it adds equality filters on action, target type, target ID, actor, and status code.

Real-time updates

Refresh the audit log list as new events occur.

  1. Go to Daytona Audit Logs ↗
  2. Use the refresh control in the top-right corner of the page

The refresh icon fetches the current page immediately. The interval selector repeats that fetch every 10s, 30s, 1m, or 5m, or on Auto, which polls every 30 seconds. Auto-refresh is Off by default.

Log structure

Each audit log entry contains the following fields:

FieldTypeDescription
idstringUnique log entry identifier
org_idstringID of the organization the action belongs to
project_idstring | nullID of the project the action belongs to, or null for organization-level actions
actor_kindstringCredential type of the actor: user, api_key, org_key, vm, or system
actor_user_idstring | nullID of the user who performed the action, or null for a machine credential
actor_emailstring | nullEmail of the user who performed the action
actor_key_idstring | nullID of the API key used, or null when the actor is a signed-in user
actor_key_prefixstring | nullPrefix of the API key used, for identifying a key without exposing it
actionstringOperation executed (e.g. create, start, stop)
target_typestringResource type affected (e.g. sandbox, snapshot)
target_idstring | nullID of the affected resource
status_codenumberHTTP status code of the result
error_messagestring | nullError message if the action failed, or null for a successful action
ip_addressstring | nullIP address of the request origin
user_agentstring | nullUser agent of the request origin
metadataobject | nullAdditional context about the action
created_atstringRFC 3339 timestamp of when the action occurred

Get audit logs for organization

Get audit logs for a specific organization, newest first.

daytona audit list --org {organizationId}

The response contains one page of entries and a cursor for the next page:

{
  "next_cursor": "MjAyNi0wOS0wOVQxMDoxMjozMy4xMjM0NTY3ODlafDAxOTliMmMx...",
  "audit_logs": [
    {
      "id": "{auditLogId}",
      "org_id": "{organizationId}",
      "project_id": "{projectId}",
      "actor_kind": "user",
      "actor_user_id": "{userId}",
      "actor_email": "user@example.com",
      "actor_key_id": null,
      "actor_key_prefix": null,
      "action": "create",
      "target_type": "sandbox",
      "target_id": "{sandboxId}",
      "status_code": 200,
      "error_message": null,
      "ip_address": "203.0.113.42",
      "user_agent": "daytona-sdk-python",
      "metadata": { "class": "linux", "region": "{regionId}" },
      "created_at": "2026-09-09T10:12:33.123456789Z"
    }
  ]
}

Query parameters

All filters are optional and combine with AND. A filter matches exactly unless it names an operator. A request accepts at most 10 filters.

daytona audit list --org {organizationId} --limit 100 --action create --target-type sandbox
FlagTypeDescription
--limitintSets the number of entries per page. The default is 100.
--cursorstringPasses a next_cursor value.
--allboolFollows every page until the last one.

List audit actions

List audit actions. The response lists every target type the audit log records and the actions possible for each, derived from the audited operations. Use it to build valid filters for audit log queries. The list is the same for every organization, and the request requires a credential.

from daytona import Daytona

daytona = Daytona()
actions = daytona.v2.list_audit_actions()

for target in actions.targets:
    print(target.target_type, target.actions)

The response contains one entry per target type:

{
  "targets": [
    {
      "target_type": "api_key",
      "actions": ["create", "delete"]
    },
    {
      "target_type": "checkpoint",
      "actions": ["create"]
    },
    {
      "target_type": "function",
      "actions": ["create", "delete", "update"]
    },
    {
      "target_type": "image",
      "actions": ["create", "delete"]
    },
    {
      "target_type": "org_api_key",
      "actions": ["create", "delete"]
    },
    {
      "target_type": "organization",
      "actions": ["create", "delete", "update"]
    },
    {
      "target_type": "organization_invitation",
      "actions": ["create", "decline", "delete", "update"]
    },
    {
      "target_type": "organization_user",
      "actions": ["delete", "update"]
    },
    {
      "target_type": "otel_config",
      "actions": ["delete", "update"]
    },
    {
      "target_type": "platform_token",
      "actions": ["create"]
    },
    {
      "target_type": "preview_endpoint",
      "actions": ["create", "delete", "expire", "update"]
    },
    {
      "target_type": "project",
      "actions": ["create", "delete", "update"]
    },
    {
      "target_type": "project_member",
      "actions": ["create", "delete"]
    },
    {
      "target_type": "project_service_account",
      "actions": ["create", "delete"]
    },
    {
      "target_type": "registry",
      "actions": ["delete", "update"]
    },
    {
      "target_type": "sandbox",
      "actions": ["create", "delete", "fork", "pause", "resume", "start", "stop", "update"]
    },
    {
      "target_type": "secret",
      "actions": ["delete", "update"]
    },
    {
      "target_type": "service_account",
      "actions": ["create", "delete", "update"]
    },
    {
      "target_type": "snapshot",
      "actions": ["create", "delete", "replicate"]
    },
    {
      "target_type": "volume",
      "actions": ["create", "delete"]
    }
  ]
}

Some pairs cover more than one operation:

  • organization update is recorded for changes to the organization itself, for the audit logging toggle, and for billing changes: wallet top-ups, the automatic top-up rule, coupon redemption, plan changes, the balance notification rule, and the billing contact email.
  • organization_invitation update is the invitee accepting the invitation. delete is the organization revoking it. decline is the invitee refusing it.
  • sandbox create is also recorded for every pre-signed file URL and every sandbox access token minted for the sandbox.
  • sandbox update covers label, network policy, secret, and lifecycle policy changes, and signing key rotation.
  • service_account delete archives the account and its keys; the record survives.

Metadata

The metadata field carries context that the handler for the action already resolved. It never contains secret values. Entries for pairs not listed here have empty or null metadata.

Target typeActionKeys
sandboxcreateclass, region
sandboxforkforked_from: ID of the source sandbox
snapshotcreatekind: disk or full
imagecreateregion
api_keycreateservice_account_id when the key was minted for a service account. Otherwise no metadata
projectupdateprevious_name, name
projectdeleterevoked_keys: number of API keys revoked with the project
project_membercreateuser_ids on a bulk add, where target_id is the project ID. A single add has no metadata and target_id is the user ID
project_memberdeleterevoked_keys: number of API keys revoked with the membership
project_service_accountdeleterevoked_keys: number of API keys revoked with the membership
organizationupdateaudit_logs_disabled (boolean) when the entry records the audit logging toggle. Other updates have no metadata
organizationdeleterevoked_keys: number of API keys revoked, revoked_org_keys: number of organization API keys revoked, projects: number of projects deleted with the organization
organization_userupdateprevious_roles, roles, and dry_run: true when the change was only validated
organization_userdeleteprevious_roles, roles (empty), self_removal (boolean)
organization_invitationcreateemail, previous_roles, roles
organization_invitationdeleteemail, previous_roles, roles (empty)
organization_invitationdeclineprevious_roles, roles (empty)
service_accountcreateprevious_roles (empty), roles
service_accountupdateprevious_roles, roles, and dry_run: true when the change was only validated
service_accountdeletealready_archived (boolean)

The roles and previous roles fields are arrays of role slugs.

Outcomes

The outcome field indicates the result of the action. Statuses follow standard HTTP semantics:

OutcomeDescription
InfoInformational (1xx codes)
SuccessAction succeeded (2xx codes)
RedirectRedirects (3xx codes)
ErrorClient/server error (4xx/5xx)
UnknownNo status code was recorded on the entry

Turn audit logging off

Audit logging is on by default. Organizations that do not want sandbox activity recorded can turn off capture on the workload plane. Management-plane actions, such as changes to the organization, its members, and its credentials, are always recorded and cannot be turned off. Neither can this setting itself: toggling it is recorded as an update on the organization target.

Turning capture off is not retroactive: earlier entries stay readable until retention ends.

No API key can change the setting, and the Auditor role can read the log but not disable it.

# Read the current setting
curl 'https://api.daytona.com/orgs/{organizationId}/audit-logs/config' \
  --header 'Authorization: Bearer YOUR_OIDC_TOKEN'

# Turn workload-plane capture off
curl 'https://api.daytona.com/orgs/{organizationId}/audit-logs/config' \
  --request PATCH \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer YOUR_OIDC_TOKEN' \
  --data '{ "disabled": true }'
FieldTypeDescription
disabledbooleanTurns workload-plane capture off with true and on with false. This field is required.

Both return the current state:

{
  "disabled": true
}

Permissions

Audit logs are scoped to the organization. Access is governed by two organization permissions, which you can grant through an organization role.

Administrators hold both permissions. The Auditor role holds only the read permission, so it can read the log but not turn logging off. An organization API key can hold the read permission but never the write permission.

PermissionGrants
read:auditQuery audit logs and get the audit logging setting
write:auditTurn audit logging on or off