Skip to main content

Audit Log

DokStamp automatically logs every write operation on every entity. The audit log provides a complete, tamper-evident history of changes: who made them, when, from which IP and URL, and exactly what changed (field-level diffs with old and new values).

What is logged

Every POST, PATCH, PUT, DELETE, and restore operation triggers an audit entry. The following events are recorded:
EventTriggered by
createdA new entity is created
updatedAny field on an entity is changed
deletedAn entity is soft-deleted
restoredA soft-deleted entity is restored

Audit record structure

Each audit entry captures:
FieldDescription
eventcreated, updated, deleted, or restored
auditable_typeThe model that changed (e.g., App\Models\Certificate)
auditable_idThe ID of the changed record
user_type + user_idThe authenticated user who made the change
tenant_idThe tenant the change occurred in
old_valuesJSON object with the previous values of changed fields
new_valuesJSON object with the new values of changed fields
urlThe API endpoint that was called
ip_addressIP address of the client
user_agentHTTP client identifier
created_atTimestamp of the change
Timestamps (created_at, updated_at) are intentionally excluded from audit diffs. Only meaningful field changes appear in old_values / new_values.

Example audit entries

Certificate issued

{
  "event": "created",
  "auditable_type": "App\\Models\\Certificate",
  "auditable_id": 142,
  "user_id": 3,
  "tenant_id": 1,
  "old_values": {},
  "new_values": {
    "status": "issued",
    "student_id": 88,
    "course_id": 12,
    "institution_id": 1,
    "issued_at": "2024-12-01 00:00:00"
  },
  "url": "https://api.dokstamp.eu/certificates",
  "ip_address": "203.0.113.42",
  "created_at": "2024-12-01T10:15:30Z"
}

Course name changed

{
  "event": "updated",
  "auditable_type": "App\\Models\\Course",
  "auditable_id": 12,
  "user_id": 2,
  "tenant_id": 1,
  "old_values": {
    "name": "Bachelor of Computer Science"
  },
  "new_values": {
    "name": "Bachelor of Computer Science and Engineering"
  },
  "url": "https://api.dokstamp.eu/courses/c3d4e5f6-a7b8-9012-cdef-123456789012",
  "ip_address": "203.0.113.10",
  "created_at": "2025-03-15T09:05:00Z"
}

Certificate revoked

{
  "event": "updated",
  "auditable_type": "App\\Models\\Certificate",
  "auditable_id": 142,
  "user_id": 1,
  "tenant_id": 1,
  "old_values": {
    "status": "issued",
    "revoked_at": null,
    "revocation_reason": null
  },
  "new_values": {
    "status": "revoked",
    "revoked_at": "2025-06-01 14:22:00",
    "revocation_reason": "Issued in error"
  },
  "url": "https://api.dokstamp.eu/certificates/a1b2c3d4-.../revoke",
  "ip_address": "203.0.113.10",
  "created_at": "2025-06-01T14:22:05Z"
}

Tenant isolation

Audit records are scoped to the tenant. Each tenant’s administrators can only see audit entries for their own data. There is no cross-tenant audit access.

Use cases for integrations

Debugging sync issues: If your system believes it sent an update but DokStamp shows a different value, the audit log will show exactly when the value changed and which user/IP caused it. Compliance: For regulated environments, the audit log provides evidence that certificate issuance and revocation followed an authorized workflow. Detecting conflicts: If two systems are writing to DokStamp simultaneously and overwriting each other’s changes, the audit log will reveal the conflict pattern through the old_values / new_values sequence. Tracing certificate history: Every status transition a certificate goes through (draftissuedrevoked) is recorded as a separate audit entry, providing a complete history.

Accessing the audit log

The audit log is currently accessible through the DokStamp admin dashboard (Nova panel). It is not available as a public API endpoint. To query audit history for a specific entity, access the dashboard and navigate to the entity’s detail view — an Audit tab shows the complete change history for that record.

What is NOT logged

  • Timestamp fields (created_at, updated_at) — these are system fields excluded by design
  • Array/JSON fields are not individually diffed — the entire JSON value is captured
  • Read operations (GET requests) — only writes are audited
  • Background system jobs (e.g., token refresh, internal cache operations)