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:
| Event | Triggered by |
|---|
created | A new entity is created |
updated | Any field on an entity is changed |
deleted | An entity is soft-deleted |
restored | A soft-deleted entity is restored |
Audit record structure
Each audit entry captures:
| Field | Description |
|---|
event | created, updated, deleted, or restored |
auditable_type | The model that changed (e.g., App\Models\Certificate) |
auditable_id | The ID of the changed record |
user_type + user_id | The authenticated user who made the change |
tenant_id | The tenant the change occurred in |
old_values | JSON object with the previous values of changed fields |
new_values | JSON object with the new values of changed fields |
url | The API endpoint that was called |
ip_address | IP address of the client |
user_agent | HTTP client identifier |
created_at | Timestamp 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 (draft → issued → revoked) 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)