Skip to main content
Every transaction submitted to Didit is evaluated against all active rules for your application. Rules define conditions, velocity checks, and actions that determine the transaction’s final status and score. This chapter of the Didit Academy fraud rule engine lesson picks up at creating a rule. The rule-engine Academy lesson creates a rule on camera at 7:54: trigger, conditions, actions and scoring, then back-testing before deploy.
Rules can be managed from the Business Console, the Management API, and the Didit MCP. Use the console when a human on your compliance team should review every change; use the API or MCP when rules are created and tuned programmatically - for example when migrating a rule set from another provider. See the API reference and the managing rules via API and MCP guide. Rules are evaluated on every transaction submitted via POST /v3/transactions/, and the result appears in the transaction’s rule_runs[] array (see response schema).

Built-in rule bundles

Didit provides a pre-configured rule library covering common regulatory typologies. Install the presets (or whole bundles) you want from the library - in the console, via the install API, or with the MCP tools - and control each installed preset’s mode. For the complete catalogue of every preset rule with thresholds and actions, see the Rules library.

Rule sources

Every rule has a source that indicates who manages it:

Rule anatomy

Each rule consists of:

Actions

When a rule matches a transaction, one or more actions are executed. Each rule can have multiple actions that are all applied together: Most preset rules combine add score with change status — for example, a sanctions counterparty rule adds 90 points to the score and immediately declines the transaction.

Requiring user verification (AWAITING_USER)

A change status → AWAITING_USER action does more than set a status: Didit automatically creates a hosted verification session for the transaction’s subject (same vendor_data) the moment the rule fires. The session comes back in the transaction’s action_required block (and in the remediation object) of the create response and every subsequent read, and in both transaction webhooks - so you can redirect the user immediately, see required user actions. Custom rules must name the workflow on the action itself (workflow_id) - both the console rule builder and the rules API require it. Built-in library rules don’t carry a workflow; for them the session workflow is resolved in this order:
  1. The remediation workflow configured in your transaction settings.
  2. Your application’s Biometric Authentication workflow, when the subject already has a stored reference face from an approved verification.
  3. Your application’s default workflow.
This means AWAITING_USER library rules always produce an actionable session out of the box - a biometric step-up for users you already verified, a full verification otherwise. Travel Rule transactions are excluded from this automatic fallback: their AWAITING_USER wait is for wallet-ownership proof, which has its own flow. The strongest choice for high-risk transactions is a Biometric Authentication workflow: because the subject is the user you already KYC’d, Didit reuses the verified reference face from their onboarding (the approved liveness selfie, passport chip photo, or document portrait) - the user just takes one live selfie, and Didit runs liveness plus a 1:1 face match against the identity that opened the account. Stolen credentials, phished OTPs, and SIM swaps all fail at this gate. Full walkthrough: step-up biometrics for a high-value withdrawal. When the session reaches a decision, the transaction follows it automatically and a transaction.status.updated webhook fires: an approved session approves the transaction (decision_reason_code: user_action_approved), a declined session declines it (user_action_declined), and a session that ends in review sends the transaction to IN_REVIEW (user_action_in_review). An expired or abandoned session keeps the transaction in AWAITING_USER.
Any workflow type except KYB can be used as the remediation action. Biometric Authentication workflows (and workflows where face match runs before ID verification) additionally require a stored reference face for the subject: an approved liveness selfie, passport chip photo, document portrait, or manually enrolled profile face. If none exists, the user is asked to complete your application’s default workflow instead - which also enrolls their face for next time - and a note on the transaction records the substitution. Only when no suitable default workflow exists either is the session skipped, with the note explaining why.

Scoring

When a transaction matches one or more rules, the scores are combined:
  1. Each rule match contributes to the transaction’s overall risk score via the add_score action
  2. The final score determines the transaction status based on your application’s score thresholds
  3. If any rule has a change_status action, that status is applied directly — DECLINED always takes priority
Default score thresholds (configurable in the console):

Creating custom rules

Custom rules can be created from the Business Console or through the Management API (also reachable from the Didit MCP and any MCP-connected AI assistant).
  1. Go to Transactions > Rules in the console
  2. Click Create Rule
  3. Define the rule title, description, and category
  4. Set the mode - Active to run live, or Test to evaluate without affecting transactions
  5. Choose the evaluation mode - All (every condition must match) or Any (at least one)
  6. Set the scope - which transaction types or directions the rule applies to
  7. Add conditions - field comparisons like amount thresholds, country codes, custom property checks
  8. Optionally add aggregation - velocity checks over a time window (count, sum, distinct count, and more)
  9. Define one or more actions - add score, change status, add tags, add notes, add to list, or open a case
  10. Save and enable the rule
Rules in Active mode take effect immediately for all new transactions. Titles are unique per application.

Backtesting

Before activating a rule, you can validate it against historical data:
  • Set a rule to Test mode — the rule is evaluated on every new transaction, but results don’t affect the transaction’s status or score. Execution statistics (matched count, affected entities) accumulate so you can assess impact before going live.
  • Use the backtest feature - in the console or via POST /v3/transactions/rules/backtest/ - to retroactively evaluate a rule’s conditions and aggregation against transactions from a specified time period. The backtest returns the number of transactions evaluated, matched, and the affected entities - without modifying any historical data. Send the same conditions, aggregation, evaluation_mode and scope as the rule you intend to activate: an omitted scope means no restriction, so the backtest would count transactions the saved rule skips.

Velocity windows (aggregation)

Velocity rules aggregate historical transaction data over a time period to detect patterns that single-transaction checks would miss: Each aggregation specifies:
  • A time window: <N>m (minutes), <N>h (hours), or <N>d (days) - e.g. 30m, 6h, 7d, 30d. Careful: m is minutes, not months.
  • Filters to narrow which historical transactions are included. Keys are field paths from the field catalog; the special value "__current__" resolves to the same field’s value on the transaction being evaluated (e.g. "subject_vendor_data": "__current__" scopes the window to the same subject), and a list value means membership. Filters compare by equality or membership only - there is no lt/gte filter, so a range like transactions under 10,000 is not something a filter can express. Put the range on the metric instead (max below 10,000, min above 1,000), and remember that a condition constrains the transaction being evaluated, never the window.
  • An operator and threshold (eq, ne, gt, gte, lt, lte against value, e.g. count >= 20)

Example patterns

Field catalog

Conditions and aggregation filters reference transaction fields by path:

Condition operators

Rules support the following comparison operators for conditions:

Condition value types

An optional value_type on a condition changes how value is interpreted:

Grouped conditions

A flat condition list combines per the rule’s evaluation_mode (ALL/ANY). For mixed logic, give conditions a group_index: conditions sharing an index form a group, group_logic (AND/OR, default AND) combines conditions within a group, and groups_logic on the first condition (AND/OR, default OR) combines the group outcomes. When any condition carries a group_index, grouped evaluation replaces evaluation_mode.

Referencing custom properties

Every key submitted in the custom_properties object of POST /v3/transactions/ is stored on the transaction as custom_values and can be used in conditions with the field path custom_values.<key>. For example, a transaction submitted with "custom_properties": {"channel": "mobile_app"} matches the condition custom_values.channel eq "mobile_app". All operators above work with custom properties, and they can also be compared against other fields or used in velocity filters. In the Console rule builder, keys observed on recently ingested transactions appear automatically in the condition field selector under Custom Properties. You can also reference a key before any transaction carries it: choose Enter custom property in the same group and type the key exactly as your integration sends it (keys are case-sensitive). The rule simply evaluates as not-matching until transactions carrying that key arrive.

Automatic blocklist decline

Before any rules are evaluated, Didit checks the transaction’s entities against your application’s blocklists. If any match is found, the transaction is immediately declined — rules are not evaluated. The following entities are checked: When a blocklist match occurs:
  • Transaction status is set to DECLINED
  • Decision reason is set to blocklisted
  • An activity record is created for audit tracking
Blocklist checks run before rule evaluation. A blocklisted entity will always be declined regardless of rule configuration or score thresholds.

Transaction screening

Didit integrates with external AML and blockchain analytics providers to enrich transactions with risk intelligence. When a transaction is submitted, the system can:
  • Screen counterparties against global sanctions and watchlist databases
  • Evaluate wallet addresses (for crypto transactions) against blockchain intelligence data, including mixer exposure, sanctioned entity connections, and high-risk service interactions
  • Check applicant AML status by cross-referencing the transaction’s linked user against their latest AML screening results
Screening results are attached to the transaction and factor into the rule engine’s scoring. If a counterparty or wallet matches a sanctions list, the corresponding rule automatically flags or declines the transaction.

Next steps

Submitting transactions

How transactions are structured for rule evaluation.

Crypto screening

Crypto screening results and how preset rules use them.

Settings

Configure score thresholds and remediation workflows.

API reference

Create Transaction API endpoint.