Audit log

One log of who did what across your organisation, to search, download as JSON Lines or CSV, and stream to Datadog, Splunk or your own endpoint as it happens.

A project’s history shows changes to its flags. The audit log is the whole organisation’s record, for security reviews and compliance: every change in every project and in the organisation itself, plus the security events that aren’t changes, such as sign-ins and API tokens.

featflags records every organisation’s events on every plan and keeps them as long as the plan keeps history: 7 days on Free, 1 year on Team, 3 years on Business. Reading, downloading and streaming them is on Business, so an upgrade shows the history you already have. Admins and owners read the log; owners manage where it streams.

What’s recorded

  • Every change, in every project and in the organisation: flags, targeting, segments, environments, SDK keys, triggers, release plans, experiments, members, invites, domains, SSO settings, the organisation itself. A change that waits for approval or a schedule is recorded at each step: requested, scheduled, approved, rejected, cancelled, failed and applied.
  • Sign-ins by your members, through Google, GitHub or SSO, including an owner signing in past enforced SSO. Refused sign-ins that concern you: a disabled user, someone blocked by your enforced SSO, or your identity provider asserting an email at a domain you haven’t verified.
  • API tokens created, given other roles and revoked, and AI assistant connections made and disconnected.
  • featflags support reading anything in your organisation. Its changes are recorded as changes, under its own name.
  • Exports of the organisation’s data and of the audit log itself.
  • Webhooks and audit destinations added, changed and removed.

Events carry no IP addresses: featflags doesn’t keep any with your data.

An event

Every event has the same shape in the app, the API, downloads and every destination:

{
  "id": 9812,
  "time": "2026-10-15T09:00:00Z",
  "organization": "acme",
  "actor": "token:ci-deploy",
  "person": "user:ana@acme.com",
  "action": "flag_state.updated",
  "target": { "type": "flag_state", "key": "new-checkout/production" },
  "project": "web",
  "environment": "production",
  "outcome": "success",
  "change": { "id": 412, "url": "https://app.featflags.io/api/orgs/acme/projects/web/changes/412" },
  "comment": "launch",
  "details": {}
}
Field What
id Increases in the order events happened. Use it to order them and to drop repeats.
actor Who did it: user:<email>, token:<name>, trigger:<name>, experiment:<key>, release-plan:<flag>/<env> for a guarded release, platform:<email> for featflags support.
person The person behind it: the token’s owner, the person who connected an AI assistant, or the actor again.
action What happened, as <type>.<what>: flag_state.updated, member.created, change.approved, session.signed_in, api_token.revoked…
outcome success, or failure for a refused sign-in or a held change that failed.
change The change it records, with a link to it and its diff in the API; null for events that aren’t changes.
details What the action carries, such as a sign-in’s provider or a token’s roles.

Search and download

Settings → Audit log lists events newest first. Filter by time, by who did it (an email finds that person’s own actions, their tokens’ and their AI assistant’s), by action or type of action (member finds every member event), and by project. Download JSONL and Download CSV export what the filters show, oldest first.

The same from the API, with an admin’s API token:

curl -H "Authorization: Bearer $TOKEN" "$API/audit-log?actor=ana@acme.com&action=flag_state&from=2026-10-01T00:00:00Z"   # newest first, paged with before=<id>
curl -H "Authorization: Bearer $TOKEN" "$API/audit-log/export?format=csv&from=2026-10-01T00:00:00Z" -o audit.csv   # or format=jsonl

In the CSV, a text field that starts with =, +, - or @ gets a leading ', so a spreadsheet never runs a comment as a formula.

Stream it

Owners send events to a log tool as they happen, under Settings → Audit destinations:

  • Datadog: your Datadog site and an API key; events arrive as logs from featflags.
  • Splunk: an HTTP Event Collector URL and token.
  • HTTPS: any endpoint of yours. Each POST carries { "events": [...] }, up to 100 events, signed like webhooks with a secret shown once.

A destination gets every event from the moment you add it, in order. If it’s down, events wait for it, retried at most an hour apart, and arrive when it’s back, for as long as your plan keeps them. Each destination shows whether it’s delivering, what’s waiting and its recent attempts, and Send test event checks the setup. Destinations only go to public internet addresses.

Over the API: POST $API/audit-destinations with, for Datadog, { "kind": "datadog", "name": "Datadog", "site": "datadoghq.eu", "api_key": "…" }.

If the organisation moves off Business, existing destinations keep streaming and can be changed or removed; reading the log and adding destinations need Business again.