Read the audit trail
GET /scenarios/{scenario_id}/audit-trail
returns the governance history of a single automation, newest first. It answers
"who changed this scenario's compliance posture, when, and what happened" —
the evidence you export for an audit, or render as an activity feed next to a
canvas.
Results come from FlowBeacon's append-only, hash-chained governance event log. Rows are never updated or deleted in place, so a trail you fetched yesterday still reads the same today.
What the trail contains
One entry per chained governance event recorded against the scenario:
event_type | What it records |
|---|---|
policy_evaluation | A governance evaluation ran. summary.results_summary carries the pass/fail/warn/n-a counts. |
policy_assignment_change | A policy was assigned to, or removed from, this automation. |
remediation_attempt | A remediation was applied. summary.changes_summary names the policies that moved, e.g. 1 policy improved (SEC-5: fail → pass). |
remediation_sync | A remediation was synced back to the source platform. |
blueprint_uploaded | The automation was first imported into FlowBeacon. |
blueprint_updated | A new revision of the automation was ingested. |
Every entry carries id, event_type, created_at, actor, and summary.
Security events (cross-org access attempts, org-header mismatches) are on a
separate chain and are never returned here.
What is not in the trail
- Regulation-change ratifications are excluded. When FlowBeacon ratifies an
updated regulatory citation, that is recorded as global telemetry with no
organization or automation linkage — there is no join today from a ratified
citation to the automations it affects. Filtering by
event_type=regwatch.ratifytherefore returns an emptyeventsarray rather than an error. If you need regulation-change provenance per automation, track thepolicy_codevalues inpolicy_evaluationentries and map them yourself. - Raw blueprint snapshots and per-policy evidence are not exposed. The
summaryobject is an allowlist. Blueprintparametersandmappervalues can contain credentials and webhook URLs, so they are structurally excluded. For current violation detail, callGET /scenarios/{scenario_id}/results. - Nothing from another organization. The scenario id is resolved inside your
API key's organization only. An id that belongs to someone else returns the
same
404 Scenario not foundas an id that does not exist.
Ordering and retention
- Ordering is
created_at DESC, id DESC— newest first, with the event id as a deterministic tie-breaker so two events written in the same microsecond never swap places between pages. created_atis an ISO 8601 UTC timestamp (2026-08-20T10:30:00+00:00).- Retention is 1 year for governance events by default. Organization lifecycle and RBAC events are retained for 7 years, and low-value informational telemetry for 90 days — but those classes do not appear in a per-automation trail. Export anything you need to keep beyond a year.
idis stable and unique. Use it to de-duplicate if you re-fetch overlapping windows.
Paging with a cursor
Pagination is keyset, not offset. Offset paging on an append-only stream skips and duplicates rows whenever a write lands between two of your requests.
- Call the endpoint with no
cursor. - Read
data.next_cursor. - If it is non-
null, call again with?cursor=<that value>. - Stop when
next_cursorisnull.
Treat the cursor as opaque — do not parse, construct, or reuse one across
different filter values. A cursor FlowBeacon did not issue returns 422.
{
"ok": true,
"data": {
"scenario_id": "4729318",
"blueprint_id": "dddddddd-dddd-dddd-dddd-dddddddddddd",
"events": [
{
"id": "eeeeeeee-eeee-eeee-eeee-eeeeeeeeeeee",
"event_type": "remediation_attempt",
"created_at": "2026-08-20T10:30:00+00:00",
"actor": { "name": "Ada Lovelace", "email": "ada@example.com" },
"summary": {
"policies_evaluated": 3,
"policies_passed": 2,
"policies_failed": 1,
"overall_result": "improved",
"notes": "Auto-remediation applied",
"changes_summary": "1 policy improved (SEC-5: fail → pass)",
"compliance_transition": {
"from": "non_compliant",
"to": "compliant",
"became_compliant": true
},
"policy_code": "SEC-5"
}
}
],
"next_cursor": "eyJjcmVhdGVkX2F0IjoiMjAyNi0wOC0yMFQxMDozMDowMCswMDowMCJ9"
},
"meta": { "watermark": "wm_a1b2c3d4" }
}
Signing a paged request
Every authenticated request needs Authorization: Bearer and
X-FB-Signature. The canonical signing string is
{timestamp}.{METHOD}.{path}.{body} and the path excludes the query string
(see Authentication) — so every page of the
trail signs the same path, and adding ?cursor=… does not change the
signature you compute.
API_KEY="fb_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
REQ_PATH="/api/public/v1/scenarios/4729318/audit-trail"
TS=$(date +%s)
SIG=$(printf '%s' "$TS.GET.$REQ_PATH." | openssl dgst -sha256 -hmac "$API_KEY" -hex | awk '{print $NF}')
curl -s "https://api.flowbeacon.ai$REQ_PATH?limit=50" \
-H "Authorization: Bearer $API_KEY" \
-H "X-FB-Signature: t=$TS,v1=$SIG"
CURSOR="eyJjcmVhdGVkX2F0IjoiMjAyNi0wOC0yMFQxMDozMDowMCswMDowMCJ9"
curl -s -G "https://api.flowbeacon.ai$REQ_PATH" \
--data-urlencode "limit=50" \
--data-urlencode "cursor=$CURSOR" \
-H "Authorization: Bearer $API_KEY" \
-H "X-FB-Signature: t=$TS,v1=$SIG"
$TS must be within 300 seconds of server time, so recompute TS and SIG
per request in a real client rather than reusing them across a long page walk.
Filtering
curl -s -G "https://api.flowbeacon.ai$REQ_PATH" \
--data-urlencode "event_type=policy_evaluation" \
--data-urlencode "from=2026-08-01T00:00:00Z" \
--data-urlencode "to=2026-08-08T00:00:00Z" \
-H "Authorization: Bearer $API_KEY" \
-H "X-FB-Signature: t=$TS,v1=$SIG"
An unusable filter is rejected, never dropped: an unknown event_type, an
unparseable from/to, a foreign cursor, or a limit outside 1–200 all
return 422. A bad value can never silently widen the window behind a 200.
Verifying the chain yourself
Add include_chain=true to attach each event's hash-chain evidence — seq,
hash_version, prev_hash, row_hash — for archival. It is off by default:
it is verification machinery, not application data, and it roughly doubles the
response size.
{
"id": "eeeeeeee-eeee-eeee-eeee-eeeeeeeeeeee",
"event_type": "remediation_attempt",
"created_at": "2026-08-20T10:30:00+00:00",
"actor": { "name": "Ada Lovelace", "email": "ada@example.com" },
"summary": { "…": "…" },
"chain": {
"seq": 41,
"hash_version": 3,
"prev_hash": "abab…",
"row_hash": "cdcd…"
}
}