Fraud & Fraud AI
Behavioural Risk Signals

Behavioural Risk Signals

How a user fills in a form carries as much information as what they fill in: a pasted card number, a session hopping between tabs, or a form completed without a single mouse movement is not evidence of a crime on its own — but it is a signal you can write a rule against.

⚠️

Lunixi has no endpoint that collects these signals for you. You measure them in your own interface and send them in the telemetry object of the decision call. Collection is on your side, evaluation is on ours.

How a signal flows

How a behavioural signal travelsData flow: you collect the signals in your own interface and send them in the telemetry object of the decision call. The server passes only five canonical fields and only numeric values; a non-canonical name or a non-numeric value is silently dropped and never reaches a rule.PASSEDDROPPEDYour interfaceyou collect the signalstelemetry: { … }inside the decision callCanonical filtername + numeric typeReaches the ruleSilently droppedno error returnedLEGENDYOUR SIDEWHERE SIGNALS ARE DROPPED
The drop is silent: a wrongly named or non-numeric field raises no error, the signal is simply ignored. Sending "42" as a string is therefore identical to not sending the field at all — your rule never fires and the response gives you no clue why.

The five canonical fields

The telemetry object carries only the fields below:

FieldTypeWhat it measures
mouseMovementCountnumberMouse movements in the session — typically very low under automation
copyPasteCountnumberPaste count — the most common trace of filling in stolen card data
tabSwitchCountnumberTab switches — copying data in from somewhere else
typingCadenceScorenumberTyping rhythm score — human or script
behavioralRiskScorenumberA composite score you compute yourself
{
  "telemetry": {
    "mouseMovementCount": 184,
    "copyPasteCount": 2,
    "tabSwitchCount": 1,
    "typingCadenceScore": 0.82,
    "behavioralRiskScore": 34
  }
}

The object travels in the decision call body alongside the others:

POST /api/v1/fraud/decisions/evaluate

The silent-drop rule

🚫

The server passes only the five names above and only numeric values. A non-canonical name or a non-numeric value is silently dropped — no error is returned, the field is simply ignored.

Two practical consequences:

  • Sending "copyPasteCount": "2" as a string is identical to not sending it. Your rule does not fire and the response tells you nothing about why.
  • You cannot invent your own signal names. A field like scrollDepth is not carried; to get such a signal into a rule, fold it into behavioralRiskScore on your side.

While integrating, send a deliberately extreme value once and confirm your rule fires. That is the only way to catch a silently dropped signal — hunting for "the rule never runs" in production costs far more.

Wiring a signal to a rule

These fields feed the rules inside a flow. You might define "if paste count is above 3 and mouse movements are under 20, review" in your flow and scope that flow to the relevant operation type.

How a flow resolves and which call triggers it: Flows and Resolution.

⚠️

Never make a behavioural signal a block reason on its own. A session with no mouse movement may be a legitimate user on a screen reader or navigating by keyboard. These signals are meant to shift a score alongside other evidence; a rule that penalises people using assistive technology is discriminatory.

Related