Acumatica · Security

Acumatica Audit Trail Configuration

How to enable, configure, and use the Acumatica audit trail — what to track, what to ignore, and the reporting patterns that keep an auditor happy.

John Kihiu12 min read

An auditor asked a client of mine, mid-engagement, to prove exactly who changed a specific vendor's bank account details and when, with before-and-after values, not just a log entry saying "record updated." That is the moment audit trail configuration stops being a compliance checkbox and becomes something you actually have to get right, and Acumatica's field-level audit history can answer that question well, provided it was turned on for the right DACs before the change happened, not after.

Two mechanisms that both get called "audit trail," and they answer different questions

Acumatica actually has two largely separate audit capabilities that people conflate. The Audit History screen (SM202020, backed by field-level change tracking configured per DAC) records before-and-after values for specific fields on specific tables, answering "what changed on this record, and what was the old value." Separately, the platform's Trace and Login Audit facilities record who logged in, what screens they accessed, and what SQL executed, answering "who was in the system and what did they touch," a much broader but shallower record. A client asking for "an audit trail" usually means the first one, field-level history with before-and-after values, but I always confirm which question they actually need answered before configuring anything, because the two features live in completely different places and neither substitutes for the other.

Turning on field-level audit is per-DAC and per-field, not global

Audit History is enabled DAC by DAC through the Audit History screen, and within an audited DAC, individual fields can be included or excluded. This granularity is deliberate, auditing every field on a high-volume transactional table like SOLine would generate enormous history volume for fields nobody will ever ask about, so the practical exercise is identifying exactly which fields on which DACs carry real audit risk, financial amounts, approval statuses, bank details, credit limits, rather than defaulting to "audit everything" and paying for it in both storage and query performance later.

Decide what needs auditing before go-live, retroactive audit has no history to show

Audit History only captures changes made after auditing was enabled for that field. If an auditor asks for the change history on a field that was never configured for audit tracking, there is no way to reconstruct it after the fact, no hidden log to enable retroactively. Any client engagement with real compliance requirements, SOC 2, financial audit, regulatory reporting, needs an explicit audit-scope conversation during requirements gathering, not after the first audit request arrives.

Custom fields added via DAC extension are not audited automatically

A field you add through PXCacheExtension<T> does not automatically inherit audit tracking just because the base DAC has some fields audited. Custom fields need to be explicitly added to the Audit History configuration for that DAC, the same way any base field would be. This is a common gap on customized instances, a client adds a custom "Approval Override Reason" field to a screen specifically because of a compliance requirement, and nobody remembers to also register that new field for audit tracking, so the very field added for compliance reasons ends up outside the audit trail.

C#
// The field itself needs nothing special in code to be auditable,
// audit tracking is a configuration layer over the cache, not a
// DAC attribute. But it only takes effect once the field is
// explicitly added to that DAC's Audit History configuration.
[PXDBString(250, IsUnicode = true)]
[PXUIField(DisplayName = "Approval Override Reason")]
public string UsrApprovalOverrideReason { get; set; }
public abstract class usrApprovalOverrideReason : PX.Data.BQL.BqlString.Field<usrApprovalOverrideReason> { }

Querying audit history programmatically, not just through the UI screen

For integrations or custom reports that need to surface change history rather than send a user to the Audit History screen, the underlying audit tables are queryable through BQL like any other DAC, which is useful for building a compliance-facing report that shows exactly the fields an auditor cares about without making them navigate the generic audit UI:

C#
// Querying audit history for a specific record and field range,
// for a custom compliance report rather than the generic screen.
var history = PXSelect<PXAudit,
    Where<PXAudit.tableName, Equal<Required<PXAudit.tableName>>,
    And<PXAudit.recordID, Equal<Required<PXAudit.recordID>>>>>
    .Select(Base, "APVendor", vendorNoteID);

The exact audit table and field names vary by platform version, worth confirming against the SDK reference for the instance version you're targeting, but the pattern, treating audit history as queryable data rather than a UI-only feature, is what lets you build compliance reporting that matches exactly what an auditor is going to ask for instead of hoping the generic screen's export is good enough.

Audit history has a real storage and performance cost worth planning for

Every audited field change writes an additional audit record, on top of the transaction's normal persistence cost, and on a high-volume table with several audited fields, that adds up over years of operation. Clients rarely think about retention policy for audit data until the table is large enough to slow down the Audit History screen itself. Plan an explicit retention or archiving strategy for audit tables on high-volume DACs from the start, the same way you would for any other fast-growing table, rather than treating audit history as a feature you enable once and never revisit.

Wrapping up

Field-level audit trail in Acumatica is genuinely capable, before-and-after values, per-field granularity, queryable through BQL, but it only covers what was explicitly configured before the change happened, and custom fields added through DAC extensions need to be registered for audit tracking deliberately, they don't inherit it. Have the audit-scope conversation during requirements gathering rather than after the first compliance request, and plan retention for audit tables on high-volume DACs before they become a performance problem in their own right.

John Kihiu
Acumatica ERP Developer · Laravel Engineer

Independent software engineer in Nairobi specialising in Acumatica customisations, Laravel backends, and tax fiscalisation integrations across East and Southern Africa.