One endpoint. Send the signal vector, get a verdict.
No SDK required — a plain HTTPS POST with a JSON body. Pay per call against an API key, or machine-to-machine over x402.
api.straja.app is not open to public sign-up. Keys are issued with a pilot, and the reference below is the contract you'll integrate against — complete and stable, but live only for pilot partners today. Request access.
Two ways in.
API key
Standard bearer token, issued per account. Billed monthly against your plan.
Authorization: Bearer sk_live_••••••••
Content-Type: application/jsonx402 — pay per call
No account, no key. An agent gets a 402, pays, and retries. Built for machine buyers that can't hold a contract.
402 Payment Required
X-Payment-Price: $0.10POST /v1/verdict
Send whatever slice of the signal vector you have. Missing fields are treated as unknown, not as zero — a signal you can't measure never counts against a user.
# One call, one verdict
curl https://api.straja.app/v1/verdict \
-H "Authorization: Bearer sk_live_••••••••" \
-H "Content-Type: application/json" \
-d '{
"amount_eur": 4800,
"signals": {
"idle_gaps_over_60s": 4,
"tab_switches": 3,
"address_entry_method": "pasted",
"deposit_escalation": [200, 1000, 4800]
}
}'const res = await fetch("https://api.straja.app/v1/verdict", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.STRAJA_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
amount_eur: 4800,
signals: {
idle_gaps_over_60s: 4,
tab_switches: 3,
address_entry_method: "pasted"
}
})
});
const verdict = await res.json();import requests
response = requests.post(
"https://api.straja.app/v1/verdict",
headers={"Authorization": f"Bearer {STRAJA_KEY}"},
json={
"amount_eur": 4800,
"signals": {
"idle_gaps_over_60s": 4,
"tab_switches": 3,
"address_entry_method": "pasted"
}
}
)
verdict = response.json()Response
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]
}
}