get_audit_logs
Calls GET /api/audit-logs as the signed-in person · REST reference
List audit entries, newest first
Platform staff only (platformRead); there is no dedicated audit-query permission. Every filter is pushed down to the DAL, so totalCount is the true number of matches and not a per-page tally. Unparseable or negative query values are DROPPED rather than rejected - a bad limit silently becomes the default 50, and an unknown status is silently ignored, so a caller cannot tell a filtered result from an unfiltered one by the status code alone. limit is clamped to 1..200 by the service. Each row's timestamp is an ISO-8601 string converted from the DAL's epoch-millisecond timestamp, falling back to its createdAt; when neither is a finite number it is an empty string rather than a date coerced to 1970. Each row serves both JSON columns the DAL stores, details and metadata, decoded to objects (null when the row stores none or the column is not an object). The delivery trail (receipt and email deliveries, claim auto-approval decisions) records its evidence in metadata and leaves details empty, so a row's evidence is read from both.
Arguments
| Argument | Type | Description | |
|---|---|---|---|
userIdquery | string | ||
resourceIdquery | string | ||
sessionIdquery | string | The filter the impersonation audit-trail endpoint uses. | |
resourcequery | string | ||
actionquery | string | Exact action match. | |
actionPrefixquery | string | Prefix match on the action, for grouping a family of events. | |
severityquery | string | Lower-cased and sent to the DAL as riskLevel. Note the name differs on the wire from the field it filters, and matches the severity field on the response rows. | |
statusquery | "SUCCESS" | "FAILURE" | "PENDING" | "PARTIAL" | Upper-cased before matching. A value outside this set is silently ignored, not rejected. | |
startDatequery | string | ISO-8601 date or date-time, converted to epoch milliseconds for the DAL. A numeric epoch is not accepted - an epoch-millisecond string does not parse, and the filter is dropped, not rejected. | |
endDatequery | string | ISO-8601 date or date-time, converted to epoch milliseconds for the DAL. A numeric epoch is not accepted - an epoch-millisecond string does not parse, and the filter is dropped, not rejected. | |
limitquery | integer | Defaults to 50, clamped to 1..200. A non-numeric value is dropped, not rejected. | |
offsetquery | integer | Defaults to 0. A negative or non-numeric value is dropped, not rejected. |
Example call
A client sends this over the MCP session; Claude and other agents build it for you. The values are placeholders — the shape is real.
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "get_audit_logs",
"arguments": {}
}
}Result
On success (HTTP 200) the tool returns one text item holding the API's JSON, pretty-printed.
A page of audit entries plus the true filtered total.
{
"hasNextPage": true,
"logs": [
{
"action": "string",
"id": "string",
"resource": "string",
"status": "string",
"timestamp": "2026-01-15T12:00:00Z",
"userId": "string",
"details": {},
"ipAddress": "string",
"metadata": {},
"resourceId": "string",
"sessionId": "string",
"severity": "string",
"userAgent": "string",
"userEmail": "string"
}
],
"totalCount": 1
}Fields
| Field | Type | Description |
|---|---|---|
hasNextPage | boolean | |
logs | array of object | |
logs[].action | string | |
logs[].details | object | null | |
logs[].id | string | |
logs[].ipAddress | string | null | |
logs[].metadata | object | null | What the writer recorded under metadata, decoded like details. The delivery trail (receipt and email deliveries, claim auto-approval decisions) records each entry here and leaves details empty. Null when the row stores none. |
logs[].resource | string | |
logs[].resourceId | string | null | |
logs[].sessionId | string | null | |
logs[].severity | string | null | Lower-cased riskLevel, or null. |
logs[].status | string | |
logs[].timestamp | string (date-time) | ISO-8601. Empty string when the row carries no usable epoch. |
logs[].userAgent | string | null | |
logs[].userEmail | string | null | |
logs[].userId | string | |
logs[].userName | string | null | Null when the actor was deleted. |
totalCount | integer | Matches across the whole filtered set, not just this page. |
When it fails
A failed call returns isError: true with the API's message as text.
403Authenticated, but the caller holds none of the required permissions.
What the model is shown
This is the tool exactly as the server lists it in tools/list. The description starts with the REST call it makes.
{
"name": "get_audit_logs",
"description": "GET /api/audit-logs — Platform staff only (`platformRead`); there is no dedicated audit-query permission. Every filter is pushed down to the DAL, so `totalCount` is the true number of matches and not a per-page tally. Unparseable or negative query values are DROPPED rather than rejected - a bad `limit` silently becomes the default 50, and an unknown `status` is silently ignored, so a caller cannot tell a filtered result from an unfiltered one by the status code alone. `limit` is clamped to 1..200 by the service. Each row's `timestamp` is an ISO-8601 string converted from the DAL's epoch-millisecond `timestamp`, falling back to its `createdAt`; when neither is a finite number it is an empty string rather than a date coerced to 1970. Each row serves both JSON columns the DAL stores, `details` and `metadata`, decoded to objects (null when the row stores none or the column is not an object). The delivery trail (receipt and email deliveries, claim auto-approval decisions) records its evidence in `metadata` and leaves `details` empty, so a row's evidence is read from both.",
"inputSchema": {
"type": "object",
"properties": {
"userId": {
"type": "string"
},
"resourceId": {
"type": "string"
},
"sessionId": {
"type": "string",
"description": "The filter the impersonation audit-trail endpoint uses."
},
"resource": {
"type": "string"
},
"action": {
"type": "string",
"description": "Exact action match."
},
"actionPrefix": {
"type": "string",
"description": "Prefix match on the action, for grouping a family of events."
},
"severity": {
"type": "string",
"description": "Lower-cased and sent to the DAL as `riskLevel`. Note the name differs on the wire from the field it filters, and matches the `severity` field on the response rows."
},
"status": {
"type": "string",
"description": "Upper-cased before matching. A value outside this set is silently ignored, not rejected."
},
"startDate": {
"type": "string",
"description": "ISO-8601 date or date-time, converted to epoch milliseconds for the DAL. A numeric epoch is not accepted - an epoch-millisecond string does not parse, and the filter is dropped, not rejected."
},
"endDate": {
"type": "string",
"description": "ISO-8601 date or date-time, converted to epoch milliseconds for the DAL. A numeric epoch is not accepted - an epoch-millisecond string does not parse, and the filter is dropped, not rejected."
},
"limit": {
"type": "string",
"description": "Defaults to 50, clamped to 1..200. A non-numeric value is dropped, not rejected."
},
"offset": {
"type": "string",
"description": "Defaults to 0. A negative or non-numeric value is dropped, not rejected."
}
}
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": false
}
}