Reference
Event catalog
Every Connect event type, when it fires, and what its payload carries.
This is the catalog of events a Connect endpoint (or Zapier trigger / n8n
trigger node) can subscribe to. The machine-readable version — including a
full static sample payload per event — is served by
GET /v3/automation/events/.
Subscriptions accept exact keys, trailing wildcards (session.*, case.*),
or ["*"] for everything. All payloads use the
Connect envelope; the tables below
describe data.
Info
These keys are distinct from the classic tenant webhook's
identity.kyc.session.* / identity.verification.* event names — the two
pipelines coexist. New integrations should prefer Connect endpoints; the
classic pipeline remains for backwards compatibility.
Session lifecycle
data.session carries the standard session envelope (id, status, workflow,
vendor_data, contacts, metadata, risk score/level, hosted url,
timestamps, and the full decision object once terminal). Every event's
data.session also carries back_count — how often the applicant pressed
Back — and edited: true
once they changed a step after first submitting it (both additive; 0 /
false for a session that never went back).
| Event | Fires when |
|---|---|
session.created | A session is created — by API, console, or a hosted flow step. |
session.started | The applicant opens the flow and begins verifying. |
session.approved | Final APPROVED decision (automatic or via review). |
session.declined | Final DECLINED decision. |
session.completed | Any final outcome — fires alongside .approved/.declined so one subscription covers both; branch on data.session.status. |
session.in_review | The session routed to manual review (a case opens). |
session.reviewed | An operator resolved an in-review session; data.review carries the decision and reviewer. |
session.abandoned | Started but never finished; TTL elapsed mid-flow. |
session.expired | The link expired before the applicant started. |
session.resubmission_requested | An operator asked the applicant to redo part of the verification. |
Warning
session.in_review is not terminal — expect a later session.approved or
session.declined (and session.completed) once an operator decides.
Modules
The granular heart of Connect: one event per module outcome, before the session finishes.
| Event | Fires when |
|---|---|
module.completed | Any single module produced its result. data.module = {feature, node_id, status, score, warnings, data, version, edited} — e.g. the OCR'd document fields for ID_VERIFICATION, the screening summary for AML_SCREENING. version is the data version of the applicant's input steps (questionnaire, product selection, branch visit, confirm details): 1 for the first submission, plus one for each change the applicant makes after going Back — such a change fires module.completed again with "edited": true. version is null for every other module (ID, liveness, AML, …); a check that re-runs because of a change fires again with its new result. |
Use the endpoint's features filter to scope this to specific modules:
{ "events": ["module.completed"], "features": ["ID_VERIFICATION", "AML_SCREENING"] }Module keys: ID_VERIFICATION, NFC_VERIFICATION, LIVENESS, FACE_MATCH,
AML_SCREENING, IP_ANALYSIS, AGE_ESTIMATION, EMAIL_VERIFICATION,
PHONE_VERIFICATION, INFORMATION, CONFIRM_DETAILS, QUESTIONNAIRE,
DOCUMENT_AI, PROOF_OF_ADDRESS, BUSINESS_DOCUMENT, DATABASE_VALIDATION,
BRANCH_VISIT, VIDEO_CALL, PRODUCT_SELECTION.
Risk & compliance
| Event | Fires when |
|---|---|
aml.hit | AML screening confirmed one or more watchlist matches. data.aml = {risk_level, matches, possible_matches, matched_entities[], lists_checked}. |
blocklist.hit | The applicant matched a tenant block list entry. data.detail.kind is "value" or "face"; a value hit also carries match_type ("exact") and score (100). A near-miss on a Fuzzy list does not fire this event — it holds the verification for manual review instead. |
risk.scored | Risk rules produced a score + level for the session. |
duplicate.detected | The same face/identity was seen on a different profile. |
Review cases
data.case carries {id, status, case_type, priority, recommendation, resolution, resolution_reason, assigned_to, due_at, created_at, guardian_review, forced_stages}, alongside data.session.
guardian_review is the verification's guardian risk review (the
risk.guardian block — signals and their labels, tier maker_checker or
compliance, action, held), or null; forced_stages lists the approval
stages guardian risk made mandatory, [{key, label, reason: "guardian_risk", tier}] (empty when it forced none).
Every event's data.session also carries guardian_review: the same block,
set whenever a guardian risk signal on a Minor branch applies to the session
(a declined session and one an operator has decided included — held says
whether it stopped an automatic approval), null otherwise.
| Event | Fires when |
|---|---|
case.created | A manual-review case opens for a session. |
case.approved | A reviewer approved the case (final). |
case.declined | A reviewer declined the case (final). |
case.sent_back | A checker returned the case to the maker stage. |
case.overdue | The case blew past its SLA and was escalated. |
Applicant progress
| Event | Fires when |
|---|---|
contact.verified | The applicant proved ownership of an email or phone (OTP). |
document.uploaded | The applicant submitted an identity document image. |
step.reopened | The applicant went Back to an input step they had already finished (questionnaire, product, branch, confirm details) and changed it. Fires once per accepted change — opening a finished step, or Continue with nothing changed, fires nothing. The step got a new version; only the checks whose inputs the change touched (a Condition, a lookup, AML, …) run again (reset), and read-only answers prefilled from it are re-derived (derived). data.detail = {node_id, feature, screen, label, version, fields, reset, derived, dependents, count, max, message}: fields lists the changed fields' ids and labels — never the values; count is how many changes the step has had; max is always null (there is no limit). Verified data — documents, liveness, OTP-verified contacts — can't be changed through Back, so it never appears here. |
questionnaire.submitted | The applicant submitted a questionnaire — answers under data.questionnaire, in their stored shapes, with version (1 for the first submission, plus one for each change made after going Back) and edited (true for such a change). A change fires the event again; Continue with nothing changed does not. A field with field masking on carries its real value only in the first delivery attempt ("unmasked": true); retries, resends and every later event carry the masked value. |
Account
Session-less events (no data.session); never filtered out by
workflow_ids.
| Event | Fires when |
|---|---|
credits.added | Credits were added; data.credits = {delta, balance, reason}. |
credits.low | Balance crossed below the low-water threshold. |
credits.exhausted | Balance reached zero — verifications will be blocked. |
Transaction monitoring
Accounts with Transaction Monitoring enabled. Session-less (no data.session);
never filtered out by workflow_ids.
| Event | Fires when |
|---|---|
transaction.decided | The engine scored a transaction and reached a decision other than allow (every decision when the tenant's policy sets emit_all_decisions). data.transaction carries the score, risk_level, decision (review, challenge, hold, block), reasons and the live signals, plus the account and counterparty. |
alert.created | A new alert opened for an account and typology — data.alert = {id, typology, typology_label, category, severity, score, priority, status, title, summary, account, transaction_ids, rule_keys, detectors, due_at, …}. |
alert.updated | Another transaction folded into an open alert (data.merged_transaction_id), or its severity / score moved. |
alert.closed | An investigator closed the alert with a disposition (true_positive, false_positive, inconclusive, reported); reported carries the regulator filing reference in report_ref. |
playbook.fired | A response playbook matched a scored transaction or a new alert and ran its actions — data.playbook_run.results lists each action's result; when a KYC workflow was triggered for the customer, session carries the verification session and its link. |
playbook.outcome | A workflow a playbook (or an investigator) triggered reached a terminal status — data.playbook_run.outcome is approved, declined, expired, abandoned or kyc_expired — and the playbook's follow-up ran. |
Getting a sample payload
Three ways, most-real first:
GET /v3/automation/samples/<event>/— up to three recent real payloads delivered to your endpoints, falling back to the static sample.- The console Connect page's test-fire button — sends the sample through the real signed pipeline to your endpoint.
GET /v3/automation/events/— the static sample inline in the catalog.