POST /api/public/v1/evaluate

Score a single action. Returns a decision, a risk score, and the signals behind it.

Endpoint

http
POST https://YOUR-APP.lovable.app/api/public/v1/evaluate
Authorization: Bearer vl_live_…
Content-Type: application/json

Request body

FieldTypeRequiredDescription
userIdstringoptionalYour own user ID. Strongly recommended — enables per-user behavior profiles.
ipstringoptionalClient IP (IPv4). Used for novelty, geo-jump, and VPN/Tor heuristics.
deviceIdstringoptionalStable device identifier from your client.
actionenumrequiredlogin, api_call, payment, admin_action
userAgentstringoptionalUsed for bot detection.

Response

FieldTypeDescription
eventIduuidUse this to send feedback later.
riskScore0–100Higher = riskier.
decisionenumALLOW · REVIEW · STEP_UP_AUTH · BLOCK
confidence0–100How much the engine trusts this score — grows with data.
reasonSignalsstring[]Which signals fired.
signalContributionsobjectPer-signal intensity, 0–1, used by feedback to target adjustments.
modelVersionstringWorkspace model version at scoring time, e.g. workspace-v14.

Examples

curl

bash
curl -X POST https://YOUR-APP.lovable.app/api/public/v1/evaluate \
  -H "Authorization: Bearer vl_live_…" \
  -H "Content-Type: application/json" \
  -d '{"userId":"u_42","ip":"203.0.113.7","deviceId":"d_xyz","action":"login"}'

Browser fetch

javascript
const res = await fetch(
  "https://YOUR-APP.lovable.app/api/public/v1/evaluate",
  {
    method: "POST",
    headers: {
      "Authorization": "Bearer vl_live_…",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      userId: "u_42",
      ip: "203.0.113.7",
      deviceId: "d_xyz",
      action: "login",
    }),
  },
);
const data = await res.json();
console.log(data.decision, data.riskScore);

Node (server)

javascript
import { request } from "undici";

const { body } = await request(
  "https://YOUR-APP.lovable.app/api/public/v1/evaluate",
  {
    method: "POST",
    headers: {
      authorization: `Bearer ${process.env.VERILOOP_KEY}`,
      "content-type": "application/json",
    },
    body: JSON.stringify({ userId, ip, deviceId, action: "login" }),
  },
);
const data = await body.json();

Python

python
import requests, os

r = requests.post(
    "https://YOUR-APP.lovable.app/api/public/v1/evaluate",
    headers={
        "Authorization": f"Bearer {os.environ['VERILOOP_KEY']}",
        "Content-Type": "application/json",
    },
    json={
        "userId": "u_42",
        "ip": "203.0.113.7",
        "deviceId": "d_xyz",
        "action": "login",
    },
    timeout=5,
)
print(r.json()["decision"])

PHP

php
<?php
$payload = json_encode([
  "userId" => "u_42",
  "ip" => "203.0.113.7",
  "deviceId" => "d_xyz",
  "action" => "login",
]);

$ch = curl_init("https://YOUR-APP.lovable.app/api/public/v1/evaluate");
curl_setopt_array($ch, [
  CURLOPT_POST => true,
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_POSTFIELDS => $payload,
  CURLOPT_HTTPHEADER => [
    "Authorization: Bearer " . getenv("VERILOOP_KEY"),
    "Content-Type: application/json",
  ],
]);
$response = json_decode(curl_exec($ch), true);
echo $response["decision"];
Latency is typically under 100 ms once your workspace has a few hundred events. The first calls take a bit longer while the per-workspace cache warms.