Audit Log

The audit log records security-relevant changes to your Zammad system: who changed what, and when. The audit log is read-only.

List

Required permission: admin.audit_log

GET-Request sent: /api/v1/audit_logs

The endpoint supports pagination. The default page size is 500. Entries are returned ordered by id (ascending). Pass ?sort_by=id and ?order_by=DESC to return the newest entries first.

Response:

# HTTP-Code 200 Ok

[
  {
    "id": 1,
    "user_id": 3,
    "user_fullname": "Christopher Miller",
    "action_type": "create",
    "auditable_type": "ChecklistTemplate",
    "auditable_id": 1,
    "auditable_name": "Onboarding",
    "value_from": {},
    "value_to": {
      "name": "Onboarding",
      "active": true,
      "sorted_item_names": [
        "Buy chair",
        "Coffee briefing",
        "Create accounts"
      ]
    },
    "source_ip": "172.19.0.1",
    "preferences": {},
    "created_at": "2026-07-23T09:14:51.650Z",
    "updated_at": "2026-07-23T09:14:51.650Z"
  },
  {
    "id": 2,
    "user_id": 3,
    "user_fullname": "Christopher Miller",
    "action_type": "update",
    "auditable_type": "Setting",
    "auditable_id": 280,
    "auditable_name": "ai_provider",
    "value_from": {
      "area": "AI::Provider",
      "name": "ai_provider",
      "title": "AI provider",
      "options": {},
      "frontend": true,
      "description": "Defines if the AI provider is configured.",
      "state_current": {
        "value": true
      },
      "state_initial": {
        "value": false
      }
    },
    "value_to": {
      "area": "AI::Provider",
      "name": "ai_provider",
      "title": "AI provider",
      "options": {},
      "frontend": true,
      "description": "Defines if the AI provider is configured.",
      "state_current": {
        "value": false
      },
      "state_initial": {
        "value": false
      }
    },
    "source_ip": "172.19.0.1",
    "preferences": {
      "changed_attributes": [
        "state_current"
      ]
    },
    "created_at": "2026-07-23T09:14:59.501Z",
    "updated_at": "2026-07-23T09:14:59.501Z"
  },
  {
    "id": 3,
    "user_id": 3,
    "user_fullname": "Christopher Miller",
    "action_type": "update",
    "auditable_type": "Role",
    "auditable_id": 2,
    "auditable_name": "Agent",
    "value_from": {},
    "value_to": {
      "permissions": [
        "admin.text_module"
      ],
      "group_permissions": {
        "2nd Level": [
          "full"
        ],
        "Service Desk": [
          "full"
        ]
      }
    },
    "source_ip": "172.19.0.1",
    "preferences": {},
    "created_at": "2026-07-23T09:16:30.188Z",
    "updated_at": "2026-07-23T09:16:30.188Z"
  },
  {
    "id": 4,
    "user_id": 3,
    "user_fullname": "Christopher Miller",
    "action_type": "update",
    "auditable_type": "Setting",
    "auditable_id": 265,
    "auditable_name": "pgp_integration",
    "value_from": {
      "area": "Integration::Switch",
      "name": "pgp_integration",
      "title": "PGP integration",
      "options": {
        "form": [
          {
            "tag": "boolean",
            "name": "pgp_integration",
            "null": true,
            "display": "",
            "options": {
              "true": "yes",
              "false": "no"
            }
          }
        ]
      },
      "frontend": true,
      "description": "Defines if PGP encryption is enabled or not.",
      "state_current": {
        "value": false
      },
      "state_initial": {
        "value": false
      }
    },
    "value_to": {
      "area": "Integration::Switch",
      "name": "pgp_integration",
      "title": "PGP integration",
      "options": {
        "form": [
          {
            "tag": "boolean",
            "name": "pgp_integration",
            "null": true,
            "display": "",
            "options": {
              "true": "yes",
              "false": "no"
            }
          }
        ]
      },
      "frontend": true,
      "description": "Defines if PGP encryption is enabled or not.",
      "state_current": {
        "value": true
      },
      "state_initial": {
        "value": false
      }
    },
    "source_ip": "172.19.0.1",
    "preferences": {
      "changed_attributes": [
        "state_current"
      ]
    },
    "created_at": "2026-07-23T09:17:20.469Z",
    "updated_at": "2026-07-23T09:17:20.469Z"
  }
]

Show

Required permission: admin.audit_log

GET-Request sent: /api/v1/audit_logs/{id}

Response:

# HTTP-Code 200 Ok

{
    "id": 3,
    "user_id": 3,
    "user_fullname": "Christopher Miller",
    "action_type": "update",
    "auditable_type": "Role",
    "auditable_id": 2,
    "auditable_name": "Agent",
    "value_from": {},
    "value_to": {
      "permissions": [
        "admin.text_module"
      ],
      "group_permissions": {
        "2nd Level": [
          "full"
        ],
        "Service Desk": [
          "full"
        ]
      }
    },
    "source_ip": "172.19.0.1",
    "preferences": {},
    "created_at": "2026-07-23T09:16:30.188Z",
    "updated_at": "2026-07-23T09:16:30.188Z"
}

Field Reference

id

Integer primary key of the audit log entry.

user_id

ID of the user that triggered the change. null when the entry was written by a background job without a current user.

user_fullname

Full name of the user at the time the entry was written. Stored separately so it remains readable after the user account is removed.

action_type

Type of the recorded change. One of:

  • create - a record was added.

  • update - an existing record was modified.

  • destroy - a record was removed.

  • switch_to - a user took over another user’s session via View from user's perspective

  • switch_back_to - the original session was resumed.

auditable_id

ID of the record that was changed.

auditable_type

Class name of the record that was changed (e.g. Role, User, Setting, KnowledgeBase, ChecklistTemplate).

auditable_name

Display name of the changed record at the time the entry was written. Stored separately so it remains readable after the record itself is gone.

value_from

Object (JSON) holding the previous state of the audited attributes. Empty ({}) on create entries.

value_to

Object (JSON) holding the new state of the audited attributes. Empty ({}) on destroy entries.

source_ip

IP address that issued the underlying request. Rails console or Rails runner is stored when the entry was written from a maintenance script.

preferences

Object (JSON) holding additional per-entry metadata. For update entries this contains a changed_attributes array listing the attributes that actually changed.

created_at

Timestamp at which the entry was written. Audit log entries are append-only.

updated_at

Same as created_at for audit log entries. Audit log entries are append-only.

Lifecycle

A scheduled task removes entries older than 12 months every day. Use the AuditLog.cleanup in the Rails console to trigger a cleanup manually.