Skip to content

Audit log Pro

The audit log records every sensitive action taken on a project — who did it, when, against what, and from which IP. Available on Pro and Team. Without a Pro license the endpoint and UI tab are hidden, and the underlying actions still happen, they just aren't recorded.

What gets recorded

CategoryActions
Project lifecycleproject.create, project.update, project.delete
SMTP & deliverability configsmtp.update, bounce_imap.update, bounce_token.rotate
API keysapi_key.create, api_key.revoke
Webhookswebhook.create, webhook.delete
Suppressionssuppression.add, suppression.delete
Workspace (Team)workspace.create, workspace.rename, workspace.delete, workspace.member_added, workspace.member_removed, workspace.member_role_changed, workspace.user_created
Sendsbroadcast.send

Each entry stores:

  • timestamp (UTC, ISO 8601),
  • actor — user id and email of the user who took the action,
  • action — the string from the table above,
  • target — the entity affected (project id, api key id, etc.),
  • metadata — action-specific JSON (e.g. for smtp.update you get smtp_host, smtp_user, from_email — never the password),
  • request context — IP address and User-Agent of the request that triggered it.

Where to see it

In the project sidebar, open Audit Log. Filter by action, by actor, or by date range. Each entry expands to show the metadata JSON.

API

bash
curl -H "Authorization: Bearer sk_..." \
  "https://your-instance.com/api/v1/projects/{project_id}/audit-log?limit=50&action=smtp.update"

Query parameters:

  • limit — max rows (default 50, max 500).
  • action — filter by exact action string.
  • actor_id — filter by user id.
  • from, to — RFC 3339 timestamps to bound the window.

Response:

json
{
  "entries": [
    {
      "id": "01H...",
      "created_at": "2026-04-30T14:22:11Z",
      "actor_id": "01H...",
      "actor_email": "alice@acme.com",
      "action": "smtp.update",
      "target_type": "project",
      "target_id": "01H...",
      "metadata": {
        "smtp_host": "smtp.mailgun.org",
        "smtp_user": "postmaster@acme.com",
        "from_email": "hello@acme.com"
      },
      "ip": "203.0.113.42",
      "user_agent": "Mozilla/5.0 ..."
    }
  ],
  "next_cursor": null
}

What it doesn't record

The audit log is for administrative actions, not data-plane traffic. It does not record:

  • Individual /send calls (those are in the email log — millions of rows).
  • Open or click events (those are in the analytics tables).
  • Read operations (GET /subscribers, etc.).
  • Login attempts (logged separately at the auth layer; surfaced in v0.7+).

If you need a full request log, use your reverse proxy's access log — Nginx, Caddy and Traefik all log per-request and are the right tool for that. The audit log is the curated subset of events worth showing in a "Who changed our SMTP password?" investigation.

Retention

Entries are kept indefinitely by default. There's no built-in pruning — it's a small append-only table and on a typical install 12 months of changes is on the order of a few thousand rows. If you want a rolling window you can run a DELETE FROM audit_log WHERE created_at < now() - interval '180 days' from psql.

See also

  • Webhooks — webhook create/delete is in the audit log.
  • Suppressions — suppression add/remove is in the audit log.
  • Workspaces — workspace and member changes (Team) are in the audit log.

Released under the AGPL-3.0 License.