Audit Trail
Overview
The Audit Trail is a tamper-evident, append-only log of every significant action taken within your organization. Every time a member creates a project, invites a colleague, updates a template, or rotates an API token, Ocriva records an entry capturing who performed the action, what was changed, when it happened, and where the request originated.
Audit logs are written automatically — there is nothing to enable or configure. Every organization on Ocriva has a full audit history from the moment the organization is created.
Key benefits:
- Security investigation — trace unauthorized changes back to a specific actor and timestamp
- Compliance evidence — provide auditors with a verifiable record of access and configuration changes
- Team accountability — know exactly who changed what and when, across every project and resource
- Operational debugging — reconstruct the sequence of changes that led to an unexpected state
NOTE
Audit logs are scoped per organization. Members can only view the audit history of organizations they belong to. No cross-organization data is ever accessible.
Tracked Actions
Ocriva tracks 23 actions across 6 entity types. Every action follows the format entity.verb (e.g., project.created, member.removed).
Organization
| Action | Description |
|---|---|
organization.created | A new organization was created |
organization.updated | Organization settings or name were changed |
organization.deleted | The organization was deleted |
Member
| Action | Description |
|---|---|
member.invited | A new member was invited to the organization |
member.role_updated | An existing member's role was changed |
member.removed | A member was removed from the organization |
member.left | A member voluntarily left the organization |
invitation.accepted | An invited user accepted their invitation |
Project
| Action | Description |
|---|---|
project.created | A new project was created |
project.updated | Project settings were modified |
project.deleted | A project was deleted |
project.member.added | A member was added to a project |
project.member.updated | A project member's permissions were updated |
project.member.removed | A member was removed from a project |
Template
| Action | Description |
|---|---|
template.created | A new extraction template was created |
template.updated | A template was modified |
template.deleted | A template was deleted |
API Token
| Action | Description |
|---|---|
api_token.created | A new API token was created |
api_token.updated | An API token's settings were changed |
api_token.deleted | An API token was revoked and deleted |
api_token.regenerated | An API token's secret value was regenerated |
Webhook
| Action | Description |
|---|---|
webhook.created | A new webhook endpoint was registered |
webhook.updated | A webhook's URL, events, or settings were changed |
webhook.deleted | A webhook was removed |
Audit Log Fields
Each audit log entry contains the following fields:
| Field | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Unique identifier of the audit log entry |
organizationId | string | Yes | The organization this event belongs to |
actorId | string | Yes | User ID of the person who performed the action |
actorEmail | string | Yes | Email address of the actor at the time of the action |
action | string | Yes | The specific action performed (e.g., project.created) |
entityType | string | Yes | The category of the affected resource (organization, project, template, member, api_token, webhook) |
entityId | string | No | ID of the specific resource that was affected |
entityName | string | No | Human-readable name of the affected resource |
metadata | object | No | Sanitized request body fields (sensitive keys such as password, token, secret, and key are automatically stripped) |
ipAddress | string | No | IP address from which the request originated |
userAgent | string | No | Browser or client user-agent string |
statusCode | number | No | HTTP response status code of the request (e.g., 200, 201) |
createdAt | timestamp | Yes | When the event was recorded (ISO 8601) |
updatedAt | timestamp | Yes | When the record was last updated (ISO 8601) |
NOTE
Audit logs are written asynchronously after the API response is sent. In the unlikely event that a log write fails, the original request is not affected — only the log entry is skipped. Failures are recorded in server-side error logs.
Viewing Audit Logs
Access the audit trail for your organization through the dashboard:
- Open the Organization menu from the top navigation bar
- Select Audit Trail from the sidebar
- The log table displays entries in reverse-chronological order (newest first)
Each row in the table shows:
- Actor — the email of the member who performed the action
- Action — the event that occurred (e.g.,
template.updated) - Entity — the name of the resource that was affected
- IP Address — the origin IP of the request
- Date & Time — when the event was recorded
Click any row to expand it and view the full entry, including the metadata object and the raw userAgent string.
TIP
The audit trail is read-only. Log entries cannot be modified or deleted from the dashboard or the API. This is by design — the immutability of audit records is what makes them trustworthy as evidence.
Filtering & Searching
Use the filter controls above the log table to narrow down entries:
| Filter | Description |
|---|---|
| Action | Filter by a specific action type (e.g., api_token.regenerated) |
| Entity Type | Filter by resource category (organization, project, template, member, api_token, webhook) |
| Actor | Filter by the user ID of the person who performed the action |
| Date Range | Limit results to a specific time window using start and end dates |
Filters can be combined. For example, you can show all template actions performed by a specific actor within the last 30 days.
The default page size is 20 entries per page, up to a maximum of 100 per request.
API Access
Audit logs are available through the REST API for programmatic access, export pipelines, and SIEM integrations.
Endpoints
| Method | Path | Description |
|---|---|---|
GET | /audit-trail/organizations/:organizationId | Retrieve a paginated list of audit logs for an organization |
GET | /audit-trail/:id | Retrieve a single audit log entry by its ID |
All endpoints require a valid JWT access token or API token in the Authorization header.
Query Parameters
| Parameter | Type | Default | Maximum | Description |
|---|---|---|---|---|
page | number | 1 | — | Page number (1-indexed) |
limit | number | 20 | 100 | Number of entries per page |
action | string | — | — | Filter by action (e.g., project.deleted) |
entityType | string | — | — | Filter by entity type |
actorId | string | — | — | Filter by actor user ID |
startDate | string | — | — | ISO 8601 date string (inclusive lower bound) |
endDate | string | — | — | ISO 8601 date string (inclusive upper bound) |
Example: List Audit Logs
# Retrieve the first page of audit logs for an organization
curl -X GET \
"https://api.ocriva.com/audit-trail/organizations/ORG_ID?page=1&limit=20" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"Response:
{
"logs": [
{
"id": "664f1a2b3c4d5e6f7a8b9c0d",
"organizationId": "663a0b1c2d3e4f5a6b7c8d9e",
"actorId": "661b2c3d4e5f6a7b8c9d0e1f",
"actorEmail": "alice@example.com",
"action": "template.updated",
"entityType": "template",
"entityId": "662c3d4e5f6a7b8c9d0e1f2a",
"entityName": "Invoice Extraction",
"metadata": {
"name": "Invoice Extraction",
"fields": ["invoice_number", "total_amount", "due_date"]
},
"ipAddress": "203.0.113.42",
"userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)",
"statusCode": 200,
"createdAt": "2026-04-04T09:15:00.000Z",
"updatedAt": "2026-04-04T09:15:00.000Z"
}
],
"total": 142,
"page": 1,
"totalPages": 8
}Example: Filter by Action and Date Range
# Show all API token deletions in March 2026
curl -X GET \
"https://api.ocriva.com/audit-trail/organizations/ORG_ID?action=api_token.deleted&startDate=2026-03-01T00:00:00Z&endDate=2026-03-31T23:59:59Z" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"Example: Fetch a Single Entry
# Retrieve a specific audit log entry by ID
curl -X GET \
"https://api.ocriva.com/audit-trail/664f1a2b3c4d5e6f7a8b9c0d" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"WARNING
The audit trail API returns data for the authenticated user's organization only. Attempting to fetch logs for an organization you are not a member of will result in a 401 Unauthorized response.
Use Cases
Compliance Auditing
Regulatory frameworks such as PDPA (Thailand), ISO 27001, and SOC 2 require evidence that access to sensitive data and configuration changes is tracked. The Ocriva audit trail provides a ready-made log you can present to auditors:
- Export logs covering the audit period via the API
- Filter by entity type to show all configuration changes (templates, webhooks, API tokens)
- Cross-reference
actorEmailwith your HR records to confirm changes were made by authorized personnel
Security Investigation
When you suspect unauthorized access or an unexpected change, the audit trail helps you answer the key questions:
- Who made the change —
actorEmailandactorId - What was changed —
action,entityName, andmetadata - When it happened —
createdAt - Where the request came from —
ipAddressanduserAgent
Filter by actorId to see all actions performed by a specific user, or by entityType to see every change to a specific resource category.
Debugging Configuration Issues
If a project stops working after a recent change, search the audit trail for project.updated or template.updated events in the relevant time window. The metadata field stores the sanitized request body, so you can see exactly which fields were changed.
Team Accountability
In organizations with multiple admins, the audit trail provides a neutral record of all administrative actions — member invitations, role changes, project deletions, and API token creation. This removes ambiguity when tracing the origin of a configuration decision.
Best Practices
-
Review API token activity regularly — search for
api_token.createdandapi_token.regeneratedevents monthly. Tokens created by unknown actors should be treated as compromised and immediately revoked. -
Set up a SIEM export — use the paginated API to stream audit logs into a security information and event management (SIEM) system such as Datadog, Splunk, or Elastic. Poll on a schedule using
startDateandendDateto fetch only new entries. -
Alert on critical actions — build alerting around high-risk events such as
organization.deleted,member.role_updated, andapi_token.regenerated. Automated alerts reduce the time between an incident and detection. -
Cross-reference with IP whitelists — compare
ipAddressvalues in audit logs against your known server IPs. Requests from unexpected IP addresses may indicate a compromised credential. -
Preserve logs outside the platform — export audit logs to your own storage for long-term retention. Ocriva's built-in log history is designed for operational use; for multi-year compliance archives, maintain your own copy.
-
Verify actor emails — the
actorEmailfield records the email at the time of the action. If a member changes their email, historical logs still reflect the email used when the action was performed. Always correlateactorIdfor identity continuity.
TIP
When exporting logs for compliance purposes, use the startDate and endDate filters to pull records month by month. This keeps individual API responses small and avoids hitting the 100-entry per page maximum.
