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).

EventFires when
session.createdA session is created — by API, console, or a hosted flow step.
session.startedThe applicant opens the flow and begins verifying.
session.approvedFinal APPROVED decision (automatic or via review).
session.declinedFinal DECLINED decision.
session.completedAny final outcome — fires alongside .approved/.declined so one subscription covers both; branch on data.session.status.
session.in_reviewThe session routed to manual review (a case opens).
session.reviewedAn operator resolved an in-review session; data.review carries the decision and reviewer.
session.abandonedStarted but never finished; TTL elapsed mid-flow.
session.expiredThe link expired before the applicant started.
session.resubmission_requestedAn 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.

EventFires when
module.completedAny 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

EventFires when
aml.hitAML screening confirmed one or more watchlist matches. data.aml = {risk_level, matches, possible_matches, matched_entities[], lists_checked}.
blocklist.hitThe 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.scoredRisk rules produced a score + level for the session.
duplicate.detectedThe 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.

EventFires when
case.createdA manual-review case opens for a session.
case.approvedA reviewer approved the case (final).
case.declinedA reviewer declined the case (final).
case.sent_backA checker returned the case to the maker stage.
case.overdueThe case blew past its SLA and was escalated.

Applicant progress

EventFires when
contact.verifiedThe applicant proved ownership of an email or phone (OTP).
document.uploadedThe applicant submitted an identity document image.
step.reopenedThe 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.submittedThe 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.

EventFires when
credits.addedCredits were added; data.credits = {delta, balance, reason}.
credits.lowBalance crossed below the low-water threshold.
credits.exhaustedBalance reached zero — verifications will be blocked.

Transaction monitoring

Accounts with Transaction Monitoring enabled. Session-less (no data.session); never filtered out by workflow_ids.

EventFires when
transaction.decidedThe 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.createdA 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.updatedAnother transaction folded into an open alert (data.merged_transaction_id), or its severity / score moved.
alert.closedAn investigator closed the alert with a disposition (true_positive, false_positive, inconclusive, reported); reported carries the regulator filing reference in report_ref.
playbook.firedA 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.outcomeA 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:

  1. GET /v3/automation/samples/<event>/ — up to three recent real payloads delivered to your endpoints, falling back to the static sample.
  2. The console Connect page's test-fire button — sends the sample through the real signed pipeline to your endpoint.
  3. GET /v3/automation/events/ — the static sample inline in the catalog.