Audit Logs
Read the audit log of your Appmixer tenant: who changed what, and when. The endpoint is only accessible to users with the `admin` scope.
Appmixer records who changed what in your tenant, and when, in the audit log. Failed attempts are recorded too. See Logged Events for the list of recorded events; the Audit Logs page of the Backoffice shows the same entries.
Get Audit Log Entries
GET [TENANT_API_URL]/system/audits
Return the audit log entries that match the filters, newest first, one page at a time. Requires the admin scope.
curl "[TENANT_API_URL]/system/audits?externalUserId=staff-42&dateFrom=2026-09-01&size=50" \
-H "Authorization: Bearer [ACCESS_TOKEN]"Query Parameters
eventType
string
create, update or delete.
status
string
success or failure.
username
string
Username of the Appmixer user who made the change. Exact match, not case-sensitive.
userId
string
ID of the Appmixer user who made the change.
externalUserId
string
ID your application sent in the X-Appmixer-Audit-External-User-Id header. Exact match, case-sensitive.
flowId
string
ID of the flow the change concerns.
threadId
string
ID of the AI Copilot conversation that made the change.
dateFrom
string
Entries recorded at or after this date or time, in ISO 8601, for example 2026-09-01 or 2026-09-01T08:00:00Z. A date without a time means midnight UTC.
dateTo
string
Entries recorded on or before this day, for example 2026-09-30. Send a date without a time; the whole day (UTC) is included.
ts
number
Entries recorded at or before this time, as a Unix timestamp in milliseconds. See Page Through Entries.
search
string
Full-text search in action, flatDiff, status and the username. Matches whole words; with several words, entries that contain any of them.
sort
string
Property to sort by, for example created, eventType, action, status, flowId or flowName. Prefix it with - for descending order. Default is -created, newest first. source, threadId and externalUserId cannot be sorted by.
page
number
Page number, starting at 1. Default is 1. 0 returns all matching entries, without paging.
size
number
Number of entries per page, 1 to 100. Default is 10.
An entry must match all the filters you send. Leave out the filters you do not need.
The response has these properties:
data
The entries on this page.
contentRange
The part of the whole result this page holds, as <first>-<last>/<total> counted from zero: 0-49/120 is the first 50 of 120 matching entries. It is also sent in the Content-Range response header, which a browser cannot read in a cross-origin request.
appliedFilters
Names of the filter parameters that were applied. See Check That Your Filters Were Applied.
Each entry has these properties:
id
ID of the entry.
created
When the entry was recorded, in ISO 8601.
eventType
create, update or delete.
status
success or failure.
action
Description of the event, for example Update flow: Sync new bookings [9089f275-f5a5-4796-ba23-365412c5666e].
user
The Appmixer user who made the change: id, username and lowername (the username in lowercase). In a user group context, user is the group user, and originalUserId, contextType and groupId identify the person and the group. Can be null.
flowId, flowName
The flow the change concerns, or null.
diff
The changed properties, each with path, type (CREATE, CHANGE or REMOVE) and changes (before and after).
flatDiff
diff as a JSON string.
source
copilot on changes made by the AI Copilot. Present only on those entries.
threadId
ID of the AI Copilot conversation that made the change. Present only together with source.
externalUserId
ID sent in the X-Appmixer-Audit-External-User-Id header. Present only when the request carried a valid one.
Check That Your Filters Were Applied
An Appmixer version that does not know a filter ignores it and returns the entries as if you had not sent it. A request for the changes of one person then returns the changes of everybody. appliedFilters tells the two cases apart: it lists the filter parameters the server recognized and applied, in no particular order. sort, page, size and format are not filters and are never listed.
If your code relies on a filter, fail closed:
A response without
appliedFilterscomes from a version that predates it. Do not treat its entries as filtered.A filter you sent that is missing from
appliedFilterswas not applied. Do not treat the entries as filtered by it.
Page Through Entries
To read all matching entries, request page=1, page=2 and so on until you have read the total from contentRange. Send ts with the time of your first request in every request, so that entries recorded in the meantime do not shift the pages:
page=0 returns all matching entries in one response and ignores size; the Backoffice CSV export uses it. Narrow the result first, for example with a date range: the response holds every entry that matches.
CSV Export
With format=csv, the response is a CSV file (text/csv, downloaded as data.csv) instead of JSON. Filters, sort, page and size work as for JSON, so add page=0 to export all matching entries rather than one page. The first row names the columns, in this order:
id, flowId, flowName, action, created, eventType, user, status, flatDiff, source, threadId, externalUserId
The user column holds the username. A filter that matches nothing exports the header row alone.
The CSV has no appliedFilters. To check that the server applies your filters, send the same request without format=csv first.
Errors
The request fails with 400 Bad Request when:
pageis not a whole number of0or more.sizeis not a whole number from1to100. Withpage=0,sizehas no upper limit.eventType,statusorsourcehas a value other than those listed above.sortnames a property that cannot be sorted by.userIdis not a 24-character hexadecimal ID.dateFromordateTocannot be read as a date, for example because it is a Unix timestamp, ordateTois beforedateFrom.tsis not a whole number, or is too large for a date.
It fails with 401 Unauthorized without a valid access token, and with 403 Forbidden for a user without the admin scope.
Attribute Changes to Your Own Users
If your application works through one Appmixer user for many people, for example one virtual user per customer organization, every audit log entry names that one Appmixer user. To record which person in your application made a change, send their ID in the X-Appmixer-Audit-External-User-Id header of the request that makes it:
The entry of this change gets "externalUserId": "staff-42". Filter by it with externalUserId=staff-42; the CSV export has it in the last column.
With the Appmixer SDK, set its externalUserId option instead of sending the header yourself. The SDK then sends it with every request to the Appmixer API, including the requests of the Designer and the AI Copilot.
The value must be 1 to 128 characters long and use only letters, digits,
.,_and-, for example a UUID or a numeric ID. A value in any other format is ignored: the request still succeeds, and its entry is recorded withoutexternalUserId.You can send the header with every request. Requests that do not write an audit log entry ignore it.
Send it with AI Copilot chat requests too. The flows the Copilot creates or changes while answering are then recorded with the same
externalUserId.
Send an opaque ID, never a name, an email address or other personal data. Appmixer stores the value exactly as sent, returns it from this endpoint and exports it in the CSV until the entry expires (see Retention). Entries cannot be deleted earlier, and the people behind the IDs are not Appmixer users, so there is no way to erase the entries of one person on request.
The header is attribution, not authentication. Appmixer records the value it receives without verifying it, so any caller allowed to make a change can name anyone. Use externalUserId for reporting and investigations, never to decide who may access what.
From browser code, send the header only to Appmixer 6.5.6 or later. Older versions refuse it in the CORS preflight, so the browser blocks the whole request. Server-side requests are not affected.
Retention
By default, audit log entries are deleted 100 days after they were recorded. On Appmixer Self-Managed, set the number of days with the GARBAGE_COLLECTOR_AUDIT_LOGS_TTL environment variable on the Appmixer engine instances.
Last updated
Was this helpful?
