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.
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.
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/jsonClient 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_idPOST /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
}
}'const res = await fetch("https://api.straja.lumosstudio.ro/v1/verdict", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.STRAJA_SECRET_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({ reference: order.id, signals }),
signal: AbortSignal.timeout(20_000),
});
const verdict = await res.json();import os, requests
response = requests.post(
"https://api.straja.lumosstudio.ro/v1/verdict",
headers={"Authorization": f"Bearer {os.environ['STRAJA_SECRET_KEY']}"},
json={"reference": order_id, "signals": signals},
timeout=20,
)
verdict = response.json()Response
In the browser
<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.
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.
// 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]
}
}