Record history and audit
Moltaro keeps an auditable history for record types that enable the audit trail: who changed what, when, and through which surface. This page covers the three developer touchpoints — reading history over the API, configuring audit per record type, and emitting business events from workspace C# code. For the user-facing view see Audit trail and History and audit.
All examples were executed against a real Moltaro installation; response bodies are real, trimmed for length.
Reading the record change feed
Section titled “Reading the record change feed”GET /api/workspace/entity/{entityIdOrKey}/instances/{instanceId}/changes
(operation)
returns the change history of one record, newest first, paged with
page/pageSize. The caller needs read access to the record and the
Read changes history permission — history can expose values the current
record state no longer shows:
curl -s "https://ops.example.com/api/workspace/entity/SupportTicket/instances/98520ecb203d4188abf10298a5a638e2/changes?page=1&pageSize=25" \ -H "Authorization: Bearer <token>"{ "Data": { "Items": [ { "Id": "1e0b029f00ad49e7a3f193050414efd6", "Operation": 1, "ChangedAt": "2026-07-22T15:51:22.950314+00:00", "Actor": { "Id": "3aba23d9-ef9b-4df8-a1cb-69a29781d5c4", "Name": "owner" }, "RecordContext": { "EntityDefinitionName": "SupportTicket", "DisplayNameSingular": "Support ticket" }, "FieldChanges": [ { "Key": "ModifiedAt", "DisplayName": "Modified", "SystemField": 4, "BeforeValue": null, "AfterValue": "2026-07-22T15:51:22.950314+00:00" }, { "Key": "Priority", "DisplayName": "Priority", "SystemField": null, "BeforeValue": "High", "AfterValue": "Medium", "FieldId": "l1eqb13B03NG" } ], "TableChanges": [], "AssignmentChanges": [], "BusinessEvent": null }, { "Id": "f2992e9199d94ecb8c1bb6bc00533442", "Operation": 0, "ChangedAt": "2026-07-22T15:51:20.332602+00:00", "Actor": { "Id": "3aba23d9-ef9b-4df8-a1cb-69a29781d5c4", "Name": "owner" }, "FieldChanges": [ { "Key": "Number", "DisplayName": "Number", "SystemField": 0, "BeforeValue": null, "AfterValue": "1" }, { "Key": "Title", "DisplayName": "Title", "SystemField": null, "BeforeValue": null, "AfterValue": "Printer in hall B is jammed" }, { "Key": "Priority", "DisplayName": "Priority", "SystemField": null, "BeforeValue": null, "AfterValue": "High" } ] } ], "TotalCount": 2, "Page": 1, "PageSize": 25 }, "Success": true}Each item carries the operation kind, the actor, the record context, and
per-field BeforeValue/AfterValue pairs — for user-facing field kinds the
values are display values (the Select field above reads "High", not the
option key). System columns (number, created/modified stamps) appear as
SystemField-tagged changes next to schema fields. Child-table row changes,
assignment changes, and — when the entry was written by code rather than a
field edit — a BusinessEvent payload (see below) complete the shape.
Deleted and archived records keep their history within the definition’s
retention settings.
Two module surfaces have their own history reads with the same philosophy:
board items expose
history
and
audit-trail,
and Entitlement Operations keeps quantity truth in the
append-only ledger.
Configuring audit per record type
Section titled “Configuring audit per record type”Audit is a per-definition setting, and new definitions start with it on
with unlimited retention.
PUT /api/workspace/admin/entity-definitions/{entityDefinitionId}/audit-settings
(operation)
changes it:
curl -s -X PUT https://ops.example.com/api/workspace/admin/entity-definitions/pYZqCLZWb0K1/audit-settings \ -H "Authorization: Bearer <token>" -H "Content-Type: application/json" \ -d '{ "AuditTrailEnabled": true, "AuditTrailRetentionMode": 1, "AuditTrailRetentionDays": null, "RowVersion": "a244a235-1dc6-4e8b-81cf-2db6b972cd55" }'AuditTrailRetentionMode is 0 disabled, 1 keep forever, 2 keep a
rolling window of AuditTrailRetentionDays days. The definition detail
exposes the current state as AuditTrailEnabled — the
Integration quickstart
discovery response shows it per record type, so an agent knows up front
whether a record carries history.
Audit from C# project code
Section titled “Audit from C# project code”Workspace C# logic (the Net Operation Project) has an explicit relationship with the audit trail:
- Record saves made by function code do not write automatic field-level audit. Automatic save auditing is a host-runtime concern; for project code it is off and cannot be switched on per save. What users change through the product surfaces is audited by the platform; what your code changes is yours to narrate.
- The supported emit path is a business event.
MoltaroDbContextexposesAddBusinessEventAsync, which appends a display-safe event to the record’s audit trail — it requires the definition to have the audit trail enabled:
await Context.AddBusinessEventAsync<SupportTicket>( ticketId, new MoltaroBusinessEvent( Title: "Escalated to on-site service", Message: "SLA breach predicted; field engineer dispatched.", Values: [ new MoltaroBusinessEventValue("engineer", "Engineer", "K. Malek"), new MoltaroBusinessEventValue("eta", "ETA", "2026-07-23") ]), cancellationToken);- Business events surface in the change feed. The entry arrives with the
acting user and shows up in the
changesendpoint as aBusinessEventpayload and in the WebApp record history — one narrative for humans and agents. - Reading audit from C# goes through the API, not the DbContext. The
generated workspace contract does not expose audit rows as queryable
DbSets; read history through the
changesendpoint above. - Boards and Entitlement application automation has fixed attribution.
IBoardAutomationCommandServiceandIEntitlementAutomationCommandServicepersist asmoltaro-system-automation. Their origin metadata retains the original user,FunctionRunId, function identity/version, andFunctionContext.CorrelationId, so operators can join a function run to Boards history/resource events or the Entitlement audit/ledger. Automation request DTOs intentionally cannot replace that actor.
Where to go next
Section titled “Where to go next”- Access and governance — roles, entity access models, and the permissions that gate history reads.
- The workspace activity feed — cross-record activity for dashboards and monitoring.
- C# business logic — the full programming model around the code shown here.
- Reliable API automation - the cross-surface table for automatic record audit, explicit business events, Boards history, Entitlement ledger truth, and project publication state.