Skip to content
MeridFlow AiFlow v8.x • self-hosted

Audit log

A single read-only endpoint over every recorded admin action on the deployment: who created, updated, deleted, or otherwise changed what, and when.

What gets logged

An entry is written whenever an admin creates, edits, or deletes: an agent, a context document, a custom tool, a Trigger, an API key, another admin user (see Team management), an MCP server connection, a delegation link, a webhook subscription, or an Orchestrator. It also covers a small number of system actions that no admin initiated, most notably the outcome of a silent agent_task Trigger run (see Triggers). Those entries are logged with no admin attached, since nothing about the action was a human decision (see admin_id below).

Endpoint

GET /api/v1/audit-log

Authentication and roles

Takes an admin session token (see Authentication), not an API key. Requires Owner or Admin. Editor and Viewer cannot call this endpoint at all.

Query parameters

Parameter Type Required Default Description
resource_type string No none (unfiltered) Restrict results to entries with this exact resource_type, e.g. trigger, admin_user, data_subject. Matched as an exact string, not a prefix or pattern.
admin_id integer No none (unfiltered) Restrict results to entries written by this specific admin's id.
limit integer No 100 Maximum number of entries to return. Capped server-side at 500 regardless of what you pass, if you request limit=1000, you still get at most 500 rows back.

Results are always ordered newest first (by id descending). There's no cursor or offset parameter. If you need results older than the last page you received, filter by admin_id or resource_type to narrow the set, or retrieve a larger limit (up to the 500 cap) in one call.

curl "https://api.your-domain.com/api/v1/audit-log?resource_type=trigger&limit=50" \
  -H "Authorization: Bearer $ADMIN_TOKEN"
import httpx

response = httpx.get(
    "https://api.your-domain.com/api/v1/audit-log",
    headers={"Authorization": f"Bearer {admin_token}"},
    params={"resource_type": "trigger", "limit": 50},
)
response.raise_for_status()
entries = response.json()
const response = await fetch(
  "https://api.your-domain.com/api/v1/audit-log?resource_type=trigger&limit=50",
  { headers: { Authorization: `Bearer ${adminToken}` } },
);
const entries = await response.json();
[
  {
    "id": 981,
    "admin_id": 1,
    "action": "create",
    "resource_type": "trigger",
    "resource_id": "4",
    "detail": { "name": "Abandoned cart follow-up" },
    "created_at": "2026-01-15T10:12:00Z"
  },
  {
    "id": 980,
    "admin_id": null,
    "action": "agent_task_completed",
    "resource_type": "event_trigger",
    "resource_id": "7",
    "detail": {
      "event_id": 118,
      "call_id": 452,
      "trigger_name": "Verify refund and update CRM",
      "result": "Order A-1002 confirmed and marked refunded."
    },
    "created_at": "2026-01-15T09:58:41Z"
  }
]

Fields

Field Type Description
id integer The entry's id.
admin_id integer or null The admin who performed the action. null for a system-initiated entry with no human actor, such as an agent_task Trigger's own completion/failure record (see the example above, action: "agent_task_completed").
action string A short verb describing what happened. Not a fixed enum, values seen in practice include create, update, delete, deactivate, agent_task_completed, and agent_task_failed; the exact value depends on which action wrote the entry.
resource_type string What kind of thing was acted on, e.g. trigger, admin_user, data_subject, event_trigger. Also not a fixed enum, treat it as a label chosen by whichever route wrote the entry.
resource_id string or null The id of the affected resource, as a string (even when the underlying resource has an integer id). null when the action has no single resource to point at, for example the data-subject deletion endpoint, which affects an unbounded set of Call/OutboundMessage rows rather than one record.
detail object or null Arbitrary JSON with action-specific context, e.g. the changed fields on an update, or the outcome text for an agent_task run. Shape varies by action/resource_type, there's no fixed schema for this field.
created_at datetime When the entry was written.

Filtering by admin

To see everything a specific team member has done, pass their admin_id (found via GET /api/v1/admin-users):

curl "https://api.your-domain.com/api/v1/audit-log?admin_id=2" \
  -H "Authorization: Bearer $ADMIN_TOKEN"
import httpx

response = httpx.get(
    "https://api.your-domain.com/api/v1/audit-log",
    headers={"Authorization": f"Bearer {admin_token}"},
    params={"admin_id": 2},
)
response.raise_for_status()
entries = response.json()
const response = await fetch(
  "https://api.your-domain.com/api/v1/audit-log?admin_id=2",
  { headers: { Authorization: `Bearer ${adminToken}` } },
);
const entries = await response.json();

resource_type and admin_id can be combined in the same request (both apply as an AND, not an OR) to answer narrower questions, like what a specific admin has done to Triggers.

Next

  • Team management: admin accounts, the most common admin_id you'll filter by.
  • Triggers: the most common source of create, update, or delete entries with resource_type: "trigger".
  • Data retention: the data_subject deletion endpoint that also writes here.