Skip to main content

Workflow Manifest Reference

A workflow is defined by a declarative manifest (JSON). It lists the steps to run and maps named outcomes to actions. This page describes its shape.

Top-level structure​

FieldDescription
workflowNameUnique name within the tenant.
forked_fromName of the predefined workflow this was forked from (custom workflows only).
metaDisplay label and default locale.
steps[]Ordered list of steps to execute.
outcomesMap of named outcome → list of actions to run.

Step object​

Every step — capture or evaluation — has a uniform shape:

FieldDescription
orderNumeric position; drives execution sequence.
nameHuman-readable label.
actionThe building block to run (e.g. a capture component or an evaluation step).
paramsAction-specific settings (allowed documents, Trust Factor configuration, decision rules).

A decision step carries a rule table in its params: each rule has a when condition (CEL), an outcome name, and optionally terminate (end with an accept, review, reject or incomplete state) and a reason. An optional default handles the no-match case; without it, the workflow falls through to the next step.

Illustrative example​

A trimmed onboarding manifest — capture a document and a selfie, evaluate trust and uniqueness, then decide:

{
"workflowName": "onboarding_standard",
"meta": { "label": "Standard Onboarding", "localeDefault": "en" },
"steps": [
{ "order": 1, "name": "Document", "action": "document_capture",
"params": {
"allowedDocuments": [{ "type": "identity-card", "countries": ["SVK", "CZE"] }],
"captureBackPage": true
} },
{ "order": 2, "name": "Face capture", "action": "face_capture" },
{ "order": 3, "name": "Trust factor eval", "action": "tf_eval",
"params": { "trustFactorConfig": "onboarding_strict" } },
{ "order": 4, "name": "Face duplicity check", "action": "dedup_face" },
{ "order": 5, "name": "Document duplicity check", "action": "dedup_document" },
{ "order": 6, "name": "Combine duplicates", "action": "best_duplicate" },
{ "order": 7, "name": "Decide", "action": "decision",
"params": {
"rules": [
{ "when": "tf_eval.result == 'reject'", "outcome": "failed", "terminate": "reject" },
{ "when": "tf_eval.result == 'review'", "outcome": "needs_review", "terminate": "review" },
{ "when": "best_duplicate.type == 'blocklist'", "outcome": "blocked", "terminate": "reject" },
{ "when": "best_duplicate.outcome == 'full_hit'", "outcome": "returning", "terminate": "accept" },
{ "when": "best_duplicate.outcome != 'no_match'", "outcome": "needs_review", "terminate": "review" }
],
"default": { "outcome": "new_unique", "terminate": "accept" }
} }
],
"outcomes": {
"new_unique": { "actions": [
{ "action": "create_new_customer",
"params": { "external_id_template": "${document.personal_number}_${uuid}" } },
{ "action": "repoint_primary_DI" } ] },
"returning": { "actions": [ { "action": "add_new_DI_to_customer" } ] },
"blocked": { "actions": [ { "action": "1N_add_current_to_blocklist" } ] },
"needs_review": { "actions": [ { "action": "1N_move_to_review" } ] },
"failed": { "actions": [] }
}
}

Building blocks​

Capture steps​

Run on the device of the User, through the hosted app, the web components or the mobile SDK:

ActionCaptures
mobile_redirectHands a desktop session over to a phone (skippable).
document_captureIdentity document pages; allowedDocuments and captureBackPage in params.
nfc_captureThe chip of an electronic document.
face_captureSelfie with passive liveness.
smile_capture, multirange_captureSelfie with active liveness (smile, multi-range).
both_palms_captureLeft and right palm for enrolment — palm verification, tenants with palm enabled only.
single_palm_captureOne palm for authentication — palm tenants only.
external_captureData supplied by the integrator instead of a capture component.

Evaluation steps​

Run server-side:

ActionEvaluatesResult signal
tf_evalThe Trust Factor configuration named in params.trustFactorConfig.tf_eval.result
dedup_faceFace duplicity check (1:N).dedup_face.result
dedup_documentDocument duplicity check (1:N).dedup_document.result
best_duplicateCombines the two duplicity checks into one outcome. Takes no parameters.best_duplicate.outcome, .type, .hit
matching1:1 face comparison against a known Customer.matching.result
palm_matching1:1 palm comparison against a known Customer — palm tenants only.palm_matching.result
decisionThe rule table; ends the workflow or lets it continue.—

Decision signals​

Values a when condition can test:

SignalValues
tf_eval.resultaccept, review, reject
dedup_face.result, dedup_document.resultno_match, customer, blocklist, concurrent, review
best_duplicate.outcomeno_match, full_hit, similar_face, similar_name, face_missmatch, doc_missmatch, multiple_full_hits
best_duplicate.typecustomer, blocklist, concurrent, review
matching.result, palm_matching.resultmatch, no_match
document_capture.resultocr_quality_failed — present only when the OCR quality retake budget was exhausted

Outcome actions​

Run when the workflow ends in the named outcome:

ActionEffect
create_new_customerCreates a Customer from the identity and adds the person to the Customer watchlist. Accepts params.external_id_template.
create_blocked_customerCreates the Customer directly in blocked state. Accepts params.external_id_template.
update_identified_customerUpdates the data of the Customer the session was started for (personal data update, authentication).
add_new_DI_to_customerAttaches the identity to the matched Customer (merge).
repoint_primary_DIMakes this identity the primary identity of the Customer.
1N_add_current_to_watchlist, 1N_add_current_to_blocklist, 1N_move_to_reviewPlaces the person in the Customer, Blocklist or Review watchlist.
reject_concurrents, merge_rejected_concurrentsResolves other in-flight verifications of the same person that were held for review — rejects them, or rejects and merges them into the new Customer.
emit_eventSends a webhook event with a custom name and payload.

External identifier template​

create_new_customer and create_blocked_customer accept an optional external_id_template that composes the external_id of the new Customer — the identifier your systems use to refer to the person (see Customer API → External identifier). Without a template the external_id equals the Customer identifier, as before.

{ "action": "create_new_customer",
"params": { "external_id_template": "${document.personal_number}_${uuid}" } }
TokenValue
${document.personal_number}The personal number read from the document, exactly as printed (including separators).
${document.document_number}The document number.
${uuid}A freshly generated UUID.

Rules:

  • Only the tokens above are allowed. Fields that are not unique per person (names, date of birth, nationality) are deliberately unavailable — a template built from them could give two different people the same identifier.
  • The rendered value must match ^[a-zA-Z0-9._-]{1,64}$ and be unique within the tenant; otherwise the action fails.
  • If a token cannot be resolved at run time (for example the document carries no personal number), the workflow ends incomplete with the reason external_id_unresolved. There is no silent fallback to a UUID, because a record your systems cannot match is worse than a failed run.
  • Templates are validated when the manifest is saved.

A personal number embedded in an identifier is personal data: it is wiped on anonymization together with the rest of the record.

Validation​

On save/publish, a manifest is checked for: schema correctness; that every action, Trust Factor configuration, and document set resolves; that conditions parse and only use the decision signals above; that every outcome name used by a rule is defined in outcomes and every path reaches a valid terminal state; and that palm steps are only used by tenants with palm verification enabled. The dashboard exposes a Validate action that runs these checks on demand.

See also​