Verifications & Checks
Verifications & Checks
A verification check is a single step in a workflow — one unit of identity verification logic. Checks are executed by the workflow engine in the order defined by your workflow graph. Each check produces an independent pass/fail result.
Check lifecycle
Each check attempt is stored as an immutable record with an incrementing
attempt number. Retries create new records rather than overwriting the
original.
Check categories
Extraction
Biometric verification
Document evaluation
Compliance screening
Fraud detection
Decisioning
Proof of address
proof_of_address_check is the one check with a policy of its own. Rather than
a single threshold, it resolves a full proof-of-address policy and reports
every finding it made along the way.
Three-state outcome
Unlike other checks, a proof-of-address result is not just pass or fail:
review deliberately surfaces as passed: false, so integrations that only
read passed stay safe: they treat a borderline document as not-yet-approved
rather than silently approving it. Branch on details.outcome when you want
the three-way distinction.
Reasons
Every finding is collected into details.reasons — a list of
{code, severity, message} objects. Severity is fail, review, or info.
The check takes the worst severity present: any fail reason fails it,
otherwise any review reason routes it to review, otherwise it passes.
Codes are stable — pivot your UI and metrics off code, never off message.
Presets and policy precedence
A policy is resolved from four layers, each overriding the last:
Presets (us, uk, eu, in, mx, au, ca, za, or custom) are
regional starting points — the UK preset accepts council tax and rejects PO
boxes, the India preset accepts mobile phone bills and address-bearing IDs.
Anything a preset omits keeps the built-in default.
Organization settings live in the dashboard under Settings → Proof of address. A workflow node either says “use organization settings” — the default — or overrides individual fields for that one workflow. Node config wins wherever it sets a value; everything else falls through to the org.
The policy that actually ran is snapshotted into details.policy, so a
decision stays explainable after you change the settings.
Document types and recency windows
Each accepted subtype carries its own default window — 90 days for a utility
bill or bank statement, 180 for a mobile phone bill or insurance statement,
365 for council tax, tax documents, benefits letters, and mortgage statements.
Override them per type in max_age_days_by_type, and per country in
country_overrides — for example, utility bills issued in India are commonly
held to 60 days regardless of your preset.
Three subtypes are review-only: lease_agreement, institution_letter,
and other have no official issuer, so a pass on one of them still routes to a
human. id_with_address is not an independent source — it shares its issuer
with the ID document — and is only accepted when the policy sets
id_with_address_satisfies.
Issuing country
Pass poa_issuing_country (ISO 3166-1 alpha-2) with the upload when you know
it; otherwise the check falls back to the country of the ID document on the
session. The issuing country drives address normalisation (postcode formats,
region names versus codes, unit tokens), PO-box detection, and any per-country
window override. When it disagrees with the ID document’s country,
country_mismatch_action decides whether that is ignored, sent to review, or
failed.
Name and address matching
Name and address are scored separately, 0.0–1.0, and each is banded against two
thresholds. At or above *_match_pass the component passes; at or above
*_match_review it is partial and routes to review; below that it fails. The
default bands are 0.85 / 0.60 for names and 0.80 / 0.55 for addresses.
Name matching ignores titles and middle names, folds accents, understands common nicknames, and accepts any one of several joint holders printed on the document. Address matching compares components — line 1, city, region, postcode, unit — and treats a region code and its spelled-out name as equivalent.
By default the reference is the applicant’s declared address; set
address_source to id_document to compare against the address extracted from
the ID instead. The other source is still compared and reported under
details.secondary_cross_reference — a divergence there is a fraud signal
rather than a check failure. In an unguided flow
(require_declared_address: false) there is no reference at all: the address is
extracted, no score is produced, and address_not_compared is reported.
Example result
details.issuer, details.holder_names, and details.extracted_address are
personal data. They are returned only on PII-bearing surfaces, are subject to
your organization’s sensitive-data access window, and are never exposed through
the MCP server.
Auto-injected checks
Some checks are automatically added to every workflow run regardless of your workflow configuration:
watchlist_screening— Required for compliance. Always runs.risk_assessment— Required for fraud scoring. Always runs.identity_crossref— Runs for certain plan tiers to detect form/document mismatches.
You cannot remove auto-injected checks, but you can configure how their results affect the workflow outcome.
Check results in the session result
After a session completes, each check’s result is available in the
check_results object:
Configuring checks in workflows
Each check can be configured with parameters specific to its type. For example:
See Workflows for how to build verification graphs with checks, conditionals, and routing logic.
Standalone checks via API
You can also run checks independently of a session through the checks API:
This is useful for:
- Running AML screening on existing customers
- Adding phone or email risk checks after onboarding
- Re-screening identities on a schedule
See the API reference for the full list of check endpoints.
Related
- Workflows — Orchestrate checks into verification pipelines
- Screening & Reports — AML screening and continuous monitoring
- Fraud Signals — The 150+ signals behind risk assessment