A BEHAVIORAL FRAUD LAYER FOR THE CRYPTO ON-RAMP
API REFERENCE

One call from your server. The SDK handles the screens.

A plain HTTPS POST with a JSON body returns a tier for the checkout session. Only INTERVENE sessions go further, into a four-question probe the browser SDK runs for you.

FULL INTEGRATION GUIDE

This page is a summary. The integration guide specifies every endpoint, the error format, measured latency, the browser SDK, test mode and data handling. Keys are issued per integration — request access.

AUTHENTICATION

Two credentials, two places.

Secret key — your server

sk_live_ calls the model; sk_test_ returns deterministic results for free. Never in a browser.

Authorization: Bearer sk_live_••••••••
Content-Type: application/json

Client secret — the browser

Returned with every verdict. Valid for one hour, for that one decision, and only for the probe, pattern and outcome calls.

Authorization: Bearer cs_••••••••
// scoped to a single decision_id
ENDPOINT

POST /v1/verdict

All fifteen signal fields are required; two accept null where the value does not exist. Three of them — idle gaps, tab switches and how the address was entered — the browser SDK measures for you.

# Test key: free, with a forced tier
curl https://api.straja.lumosstudio.ro/v1/verdict \
  -H "Authorization: Bearer sk_test_••••••••" \
  -H "Content-Type: application/json" \
  -H "Straja-Test-Tier: INTERVENE" \
  -d '{
    "reference": "order_8f2c41",
    "signals": {
      "idle_gaps_over_60s": 4,
      "tab_switches": 3,
      "address_entry_method": "pasted",
      "amount_eur": 4800,
      "deposit_escalation": [200, 1000, 4800],
      …all fifteen fields
    }
  }'

Response

tier
"PASS" · "SOFT" · "INTERVENE"
string
probe_required
True only on INTERVENE — start the probe, or hand the verdict to Straja.present().
boolean
key_signals
Short phrases naming what moved the tier, e.g. 'idle_gaps + pasted address'.
string[]
reasoning
Plain-language explanation, written for a reviewer.
string
decision_id
The audit record's id, used by every follow-up call.
string
client_secret
Browser-safe credential for this decision's probe, pattern and outcome.
string

In the browser

checkout page
<script src="https://api.straja.lumosstudio.ro/sdk/v1/straja.js"></script>

const straja = Straja.collect({ addressInput: "#destination" });
// on confirm: send straja.signals() to your server → POST /v1/verdict
const result = await Straja.present(verdict, { transfer: "€4,800 in BTC" });
// result.action: "proceed" | "cancel" | "hold" | "error"

See the screens without writing code in the SDK playground, and the probe, pattern and outcome calls in the integration guide.

TRY IT

Playground

Pick a scenario and see the shape of a response. This returns a stored example — it isn't a live call to the model.

stored example — not a live call200 OK
// This playground returns a stored example.
// The live API runs the same engine on real signals.

{
  "tier": "INTERVENE",
  "reasoning": "Coached-session pattern: repeated idle gaps, pasted address, escalating deposits, destination created 2 days ago.",
  "decision_id": "d_8f21c0ab",
  "probe_required": true,
  "signals": {
    "idle_gaps_over_60s": 4,
    "tab_switches": 3,
    "address_entry_method": "pasted",
    "deposit_escalation": [200, 1000, 4800]
  }
}