NetSuite System Notes Report with SuiteQL: Who Changed What and When
System notes record who changed which field on which record, when, in what context and from what value to what value. This generator writes SuiteQL against the systemnote table for a single record's history, one user's changes, or one field across transactions.
Fill in
Use block 1 to see the record type IDs present in your system notes.
Use block 1 to list the field IDs for the record type.
1. Discover record types and field IDs in the date range
SELECT
sn.recordtypeid,
BUILTIN.DF(sn.recordtypeid) AS record_type,
sn.field,
BUILTIN.DF(sn.field) AS field_label,
COUNT(*) AS changes
FROM systemnote sn
WHERE sn.date >= TO_DATE('2026-10-01', 'YYYY-MM-DD')
AND sn.date < TO_DATE('2026-10-21', 'YYYY-MM-DD') + 1
GROUP BY sn.recordtypeid, BUILTIN.DF(sn.recordtypeid), sn.field, BUILTIN.DF(sn.field)
ORDER BY changes DESC2. Full change history of one record
SELECT sn.date, BUILTIN.DF(sn.name) AS changed_by, BUILTIN.DF(sn.role) AS role, BUILTIN.DF(sn.context) AS context, BUILTIN.DF(sn.type) AS change_type, BUILTIN.DF(sn.field) AS field, sn.oldvalue, sn.newvalue FROM systemnote sn WHERE sn.recordtypeid = -30 AND sn.recordid = 4512 ORDER BY sn.date DESC
3. All changes by one user in the date range
SELECT
sn.date,
BUILTIN.DF(sn.recordtypeid) AS record_type,
sn.recordid,
BUILTIN.DF(sn.field) AS field,
sn.oldvalue,
sn.newvalue,
BUILTIN.DF(sn.context) AS context
FROM systemnote sn
WHERE sn.name = 17
AND sn.date >= TO_DATE('2026-10-01', 'YYYY-MM-DD')
AND sn.date < TO_DATE('2026-10-21', 'YYYY-MM-DD') + 1
ORDER BY sn.date DESC4. Changes to one field on transactions, with document number
SELECT
sn.date,
t.tranid,
BUILTIN.DF(t.type) AS tran_type,
BUILTIN.DF(sn.name) AS changed_by,
sn.oldvalue,
sn.newvalue
FROM systemnote sn
INNER JOIN transaction t ON t.id = sn.recordid
WHERE sn.recordtypeid = -30
AND sn.field = 'TRANDOC.KSTATUS'
AND sn.date >= TO_DATE('2026-10-01', 'YYYY-MM-DD')
AND sn.date < TO_DATE('2026-10-21', 'YYYY-MM-DD') + 1
-- AND sn.name = 17
ORDER BY sn.date DESCConfirm the systemnote columns (date, name, role, context, type, field, oldvalue, newvalue, recordid, recordtypeid) in Setup > Records Catalog for your account. Run block 1 first: it shows the recordtypeid and field values your account actually stores, which you then paste into the other blocks. Block 4 joins to transaction, so use it only with the transaction record type ID from block 1. Uncomment the user line to narrow by person.
Get an audit query pack for your account
Tell us which records and fields your auditors ask about and we will return tested system note queries and a saved search layout for your account.
Optional. The tool and every export work without this. No spam.
How to use it
Start with block 1 for your date range. It lists the record type IDs and field IDs present in system notes with a count, so you never guess the internal codes. Field IDs are stored as internal identifiers (for example a TRANDOC-style code for standard transaction fields or the custbody ID for custom ones), while BUILTIN.DF shows the label. Paste the record type ID and field ID you need into the other fields. Block 2 gives the full history of one record, block 3 everything a user changed, and block 4 every change to one field on transactions with the document number. Dates use TO_DATE and an exclusive upper bound of the day after, so the whole last day is included.
Where this lives in NetSuite
The same data appears on the System Information subtab (System Notes) of each record, and in saved searches of type System Note or through the System Notes fields join on a record search. SuiteQL exposes it as the systemnote table. The role running the query needs permission to see the underlying records, and administrators should confirm the table and columns in Setup > Records Catalog. For user access reviews, combine block 3 with the Login Audit Trail (Setup > Users/Roles > View Login Audit Trail), which records logins, roles used and IP addresses; system notes record data changes, not logins.
Worked example: who closed this sales order
A customer disputes that order SO-10442 was closed early. Run block 1 for the last 30 days to find the transaction record type ID and the field ID for status, then run block 2 with the order's internal ID. The output shows each change in date order with the user, role and context such as User Interface, CSV Import or a script, plus old and new values. If the context shows a script or web services, check the integration or script deployment that ran at that time. If the change was made in the UI, the user and role identify who to ask. Export the result as the audit record.
Gotchas and deleted records
System notes are a change log, not a backup; a deleted record cannot be restored from them. Deleted transactions and records are tracked separately, for example through a saved search of the Deleted Record type, which shows what was deleted, by whom and when, but not the full data, and there is no undelete in NetSuite. Old and new values for list fields may be stored as internal IDs or codes rather than labels, so decode them against the list. The table is large in busy accounts: always filter by date, record type or record ID, and page results with limit and offset when calling through REST.
Frequently Asked Questions
How do I run a system notes report in NetSuite?
For one record, open its System Information subtab. For many records, create a saved search of type System Note, or query the systemnote table in SuiteQL filtered by date, record type and user as this tool generates. Saved searches are easier for business users; SuiteQL is better for integrations and repeatable audit extracts.
Can I recover a deleted record in NetSuite?
No, NetSuite has no undelete. A Deleted Record saved search shows the record type, name, who deleted it, when and in what context, which helps you recreate it from exports, PDFs, emails or a sandbox copy refreshed before the deletion. To prevent repeats, restrict the delete permission on the roles involved.
How do I build a NetSuite user access report?
Combine three sources: the employee list with roles (Lists > Employees, Access subtab, or a search on employee with role), the Login Audit Trail for actual logins and roles used, and system notes for what each user changed. Block 3 of this tool gives the changes part for one user and date range.
Why are system note values numbers instead of names?
For select and list fields, system notes often store the internal ID or an internal code of the old and new value. Decode them by looking up the ID in the list or record, or by joining to that table in SuiteQL. Text, number and date fields show the actual values.
If you want auditors and admins to ask who changed what in plain English and get answers from NetSuite system notes on your own infrastructure, we can set that up.
Related Tools
NetSuite SuiteQL Trial Balance Query Generator
Fill in subsidiary, periods and accounting book to get SuiteQL that totals debits, credits and net by account, by account and department, or across two periods.
NetSuiteNetSuite SuiteQL Custom List and Custom Record Query Generator
Enter a custom list or custom record script ID and its fields to get SuiteQL for its values, its records, a join from transactions, and a ready REST call.
NetSuiteNetSuite Role Permission Matrix Worksheet
An editable worksheet that records which role holds which permission level on each record area and scores the access risk for review.
NetSuiteNetSuite User Access Request Form Template
A fill-in access request form for new, changed or removed NetSuite users, with role, subsidiary, segregation of duties review and approval lines.
More NetSuite tools
See all- NetSuite Saved Search Formula Generator
- NetSuite CSV Import Template Guide
- NetSuite Inventory Costing Method Reference
- NetSuite Month End Close Checklist
- NetSuite License Cost Estimator
- NetSuite Custom Record Design Spec Template
- NetSuite SuiteScript Deployment Handover Template
- NetSuite Sandbox and Release Change Log Worksheet
- NetSuite Script and Workflow Inventory Worksheet
Keep exploring
Free tools
- NetSuite SuiteQL Transaction Query GeneratorPick a transaction type, date range and row limit and get ready-to-run SuiteQL for headers, lines and the REST call that executes it.
- NetSuite SuiteQL Custom List and Custom Record Query GeneratorEnter a custom list or custom record script ID and its fields to get SuiteQL for its values, its records, a join from transactions, and a ready REST call.
- SuiteQL Query GeneratorFill in a table, columns, filter and sort and get a SuiteQL statement ready for the N/query module, the REST SuiteQL endpoint or the SuiteAnalytics Workbook.
ERP fixes and how-tos
- How to write and run SuiteQL queries in NetSuiteRun SuiteQL from Analytics > SuiteQL Query Tool or via N/query in SuiteScript. Syntax basics, joins, pagination and real examples for NetSuite reporting.
- How to use formula fields in a NetSuite saved searchHow to build formula (text), formula (numeric) and formula (date) fields in a NetSuite saved search, with CASE WHEN, DECODE and NVL examples that actually work.
- N/query versus N/search: choosing the right SuiteScript data access moduleCompare NetSuite's N/query (SuiteQL) and N/search modules for performance, governance cost and capability, and decide which to use for joins, aggregation, sublist reads and large exports in SuiteScript 2.1.
AI on your ERP
- AI agents for NetSuite manufacturing operationsAI agents for NetSuite manufacturing: WIP tracking, routing exceptions, and work order status grounded in SuiteQL, with human approval on anything that writes back.
- AI for NetSuite, Beyond the Built-In Text ToolsNetSuite's built-in AI covers text generation, not grounded answers on your own data. See how a private LLM over SuiteQL adds real Q&A and controls.
Integrations
- How to build an MCP server for Oracle NetSuiteDesign an MCP server for Oracle NetSuite: which tools to expose, SuiteQL and RESTlet backing, OAuth scoping, transports, audit, and read-only first.
- How to add AI agents to Oracle NetSuiteHow to add AI agents to Oracle NetSuite: SuiteQL and REST tool layer, RESTlet writes, role-scoped tokens, human approval, and where a private model fits.