An alert is the operational case created when one asset fails a reconciliation rule. It brings together the latest evidence, current status, alert severity, reconciliation period, and a complete transition history.
Read evidence from a passing check#
A passing check does not open an alert. Its evidence is stored on the evaluation returned by POST /rules/{ruleID}/evaluate and available later from the evaluation endpoints.
Each checked asset appears in data.evidence with passed: true and a compact, self-contained proof. It contains the observed balances and the predicate inputs needed to verify the historical result, even if the rule is edited later. The proof shape depends on the template:
ledger_vs_pool_drift stores the raw Ledger and cash-pool balances with the sign and tolerance used by the check. In this example, the residual is 100 × 1 + (-95) = 5, which passes a tolerance of 5.
Proof amounts are integer strings in the asset's smallest unit; see Unambiguous Monetary Notation. Comparisons remain exact for arbitrarily large balances. PASS proofs omit generated expressions and derived fields, while retaining the inputs needed to verify the predicate; use pitPerSource for the source timestamps.
Investigate an alert#
Start with the alert's current state:
Review four things before acting:
- Rule and period: confirm which control and financial period the case belongs to.
- Evidence: compare the observed values, difference, and tolerance.
- Source timestamps: inspect the linked evaluation's
pitPerSourceto verify both sides were read at the intended instants. - Timeline: review earlier failures and manual decisions on the same case.
Alert lists are ordered by lastSeenAt descending, then by id descending when timestamps match. This stable order prevents alerts from moving across page boundaries while following a cursor.
Retrieve the append-only timeline with:
The timeline is cursor-paginated and ordered most recent first. It includes fail, pass, ack, resolve, accept, snooze, and unsnooze events. A failure whose previous status was RESOLVED is marked as a reopen. If the alert does not exist, the endpoint returns 404 rather than an empty timeline.
Build a chronological view#
Fetch every page, following cursor.next while cursor.hasMore is true. Concatenate the returned cursor.data arrays, then reverse the complete list because the API returns newest events first:
Each entry carries prevStatus and newStatus, so the timeline can show the state transition without inferring it from neighboring rows. Use isReopen: true to highlight a failure that followed a resolution.
| Event type | What to show |
|---|---|
fail | The discrepancy evidence in payload; follow evaluationID for that evaluation's source timestamps. |
pass | Automatic resolution; follow evaluationID for the passing proof and pitPerSource. |
ack | The operator, timestamp, and note in payload. |
resolve | The fixed_by_booking resolution, including its author, note, and transaction references. |
accept | The accepted_by_business resolution and its frozen evidence snapshot. |
snooze / unsnooze | When notification muting began, changed, or ended. |
Do not reconstruct history from the current alert row. Its ack, resolution, and snooze fields describe only the current state. The events endpoint is the source of truth for prior transitions and resolutions, including those cleared when an alert reopened.
Acknowledge ownership#
Acknowledge an alert when someone has started investigating it:
Acknowledgement changes OPEN to ACKNOWLEDGED. It does not make the period green and does not stop later evaluations. If another failure arrives, the alert returns to OPEN so the prior acknowledgement cannot hide new evidence.
Snooze notifications#
Use a snooze for a known, time-bounded situation such as a provider maintenance window or an in-flight migration:
A snooze mutes webhook notifications until until; it does not change the alert status. Evaluations continue, failures remain in the timeline, and the alert continues to count against the period's green status.
The first failure at or after the snooze expires clears it and notifies once. You can also lift it early:
Reconciliation automatically suppresses webhook delivery for repeated failures whose evidence is materially unchanged. The event is still recorded and occurrenceCount still increases. Changed evidence, reopens, and manual transitions continue to notify.
Record a corrective booking#
After correcting the financial state, close the alert and optionally link the Ledger transactions that made the correction:
This records a fixed_by_booking resolution. A later failing evaluation within the same period reopens the same alert; the earlier resolution remains in the event timeline.
An alert also closes automatically when a later evaluation passes. Automatic closure is recorded as an auto resolution.
Accept a known discrepancy#
Sometimes the observed difference is valid but should remain visible—for example, a confirmed settlement timing difference at period close. Accept it with an explicit business decision:
Acceptance requires an author and non-empty note. Reconciliation freezes the alert's current evidence into the accepted_by_business resolution so later evidence cannot rewrite what was approved.
Acceptance closes the operational case; it does not change Ledger or external balances. Apply your organization's approval policy before treating an accepted alert as reconciled.
Use webhook events#
Reconciliation publishes alert transitions through the Formance event bus for delivery by the Webhooks module. Subscribe only to the transitions your workflow needs:
| Event | Meaning |
|---|---|
reconciliation.opened_alert | A new asset and period failed. |
reconciliation.updated_alert | An active discrepancy changed materially. |
reconciliation.acknowledged_alert | An operator took ownership. |
reconciliation.resolved_alert | The control passed or an operator recorded a fix. |
reconciliation.accepted_alert | An authorized user accepted the discrepancy. |
reconciliation.reopened_alert | A resolved case failed again in the same period. |
reconciliation.snoozed_alert | Notifications were muted until a future time. |
reconciliation.unsnoozed_alert | A mute was lifted early. |
Each payload contains the current alert and the event that caused the transition. Use the alert-event ID as the downstream idempotency key: webhook delivery can be retried and should not be treated as exactly once.
Separate financial and operational failures#
If a source read or evaluation cannot complete, Reconciliation stores an ERROR evaluation and opens an alert with fingerprint engine.error and label kind=engine.error. Route this signal to the platform team rather than treating it as a confirmed financial discrepancy.
Resolve the source or execution problem, then run the rule again. A successful evaluation closes the operational error path and produces the normal financial verdict.