Skip to main content

How it works

Request lifecycle​

  1. Event in. The body is validated. Unknown top-level properties, a NUL character or a full card number are refused with 400; context, user and payment accept extra fields.
  2. Enrichment. The server adds what it knows about the request: IP intelligence and geo, the device behind context.fp_id, email and phone checks. The outcome per provider is returned in enrichment_status.
  3. Aggregates and velocity. Counters over time windows (events per card token, accounts per IP or affiliate, and similar) and cross-account links are loaded for the rules.
  4. Rules. Evaluation order is fixed:
    • trust rules end evaluation with allow and score 0.
    • hard_block rules end evaluation with block; the score is then set to max_possible.
    • The declared flags (user.trusted, user.vip, is_known_fraud, chargeback_flag, name_blocked, sanctions_match) take effect through the preset's trust and hard-block rules that read them.
    • Scoring rules (high, medium, low) add or subtract points; monitoring rules only raise flags.
  5. Decision. risk_score >= block_threshold gives block, risk_score >= review_threshold gives review, otherwise allow. A review also opens a case.
  6. Delivery. The result is returned (sync) or stored (async), and a signed webhook is sent if the project has a webhook URL and secret.

Sync and async​

Sync (default)Async ("async": true)
Response200 with the full score and decision202 with a receipt (event_id, accepted_at)
Get the resultIn the responseGET /v1/scores/{event_id} (pending until scored), or the decision webhook
Use whenYou must act on the decision right now (payments, logins)You score in the background (batch checks, post-hoc review)

Async needs the ingestion queue; if it is down the call fails with 503 ASYNC_UNAVAILABLE. Async intake does not check ruleset availability; scoring happens afterwards.

Shadow rules​

A shadow rule runs on every event and its result is recorded, but it is not shown in the response breakdown, and its points never count and its actions never fire. Use shadow to measure a new rule on live traffic, then promote it to active. Rules are drafted, simulated against recent events and published through the rules API or the dashboard.

Fail-closed behaviour​

Defraudo prefers refusing to score over scoring with the wrong rules.

  • On a sync request, if no compiled ruleset is reachable (COMPILED_RULES_UNAVAILABLE) or the project's policy (thresholds) cannot be read (PROJECT_POLICY_UNAVAILABLE), POST /v1/events returns 503. Nothing is persisted; retry the same event_id and body.
  • If scoring succeeds but an active rule could not read a signal as written (a long-window count that overran its budget, Redis down with a failed database fallback, a regex that cannot run), the response carries a degraded array naming what was affected, for example rule:<rule_id>. The decision is still returned; treat it as lower confidence. The field is absent when scoring was healthy. It is only returned on the first sync response; GET /v1/scores/{event_id} and a repeated request do not include it, so store it if you need it.
  • If persisting a score (including its review case) fails, the response is 500 and the attempt is rolled back; retrying the same event_id and body is safe.