Skip to main content
Risk assessment is the core of Clausum. Call POST /api/v1/assess from your backend at the moment of decision — before capturing a card, releasing a transfer, or completing a sensitive action.
Use $CLAUSUM_API_BASE from Clausum support — not a guessed hostname. See Access & environments.

Where to call it

1

Collect context

Gather transaction, identity, payment method, device, and (optionally) behavioral data. Use the browser SDK to capture device and behavior automatically.
2

Assess server-side

From your backend, call /assess with your secret key. Do not call it with a secret key from the browser.
3

Enforce the decision

Act on approve, review, challenge, or decline.

Minimum request

Only amount and currency are required:
{ "amount": 1500, "currency": "MXN" }
Send as much as you have — every field unlocks more signals:
{
  "amount": 1500,
  "currency": "MXN",
  "transaction_type": "payment",
  "email": "customer@example.com",
  "phone": "+5215512345678",
  "customer_id": "cus_abc123",
  "payment_method": {
    "type": "card",
    "card_bin": "411111",
    "card_last4": "4242",
    "card_country": "MX",
    "card_brand": "visa"
  },
  "device": {
    "ip": "201.150.10.22",
    "fingerprint": "fp_9a8b7c6d",
    "user_agent": "Mozilla/5.0",
    "timezone": "America/Mexico_City"
  },
  "behavior": {
    "session_duration_ms": 18230,
    "mouse_movements": 142,
    "copy_paste_events": 0
  },
  "billing": { "country": "MX", "city": "CDMX", "postal_code": "06600" },
  "metadata": { "order_id": "ORD-123", "channel": "web" }
}

Full example

import "server-only"

const CLAUSUM_URL = `${process.env.CLAUSUM_API_BASE}/api/v1/assess`

export async function assessAndCapture(order: Order, signals: ClientSignals) {
  let assessment
  try {
    const res = await fetch(CLAUSUM_URL, {
      method: "POST",
      headers: {
        Authorization: `Bearer ${process.env.CLAUSUM_SECRET_KEY}`,
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        amount: order.amountInCents,
        currency: order.currency,
        email: order.email,
        customer_id: order.customerId,
        payment_method: order.paymentMethod,
        device: signals.device,
        behavior: signals.behavior,
        session_id: signals.sessionId, // from the browser SDK
        metadata: { order_id: order.id },
      }),
      signal: AbortSignal.timeout(2000),
    })

    if (!res.ok) throw new Error(`assess failed: ${res.status}`)
    assessment = await res.json()
  } catch (err) {
    // Fail open: log and continue rather than blocking a real customer
    console.error("[clausum] assessment unavailable", err)
    return capturePayment(order)
  }

  switch (assessment.decision) {
    case "decline":
      throw new PaymentBlockedError(assessment.blocked_by ?? "high risk")
    case "challenge":
      return requireStepUp(order, assessment)
    case "review":
      await flagForReview(order, assessment)
      return capturePayment(order)
    default:
      return capturePayment(order)
  }
}

Best practices

The browser SDK is great for collecting signals and pre-checks, but the authoritative decision that gates money movement should be made from your backend with a secret key.
Use a short timeout (1–2s). If Clausum is unreachable, default to your normal flow and log it. Blocking legitimate customers is usually worse than missing one assessment.
Store session_id, risk_score, and signals with the order. You’ll need them for disputes and fraud reports.
Decide on a unit (smallest currency unit / cents is recommended) and use it everywhere so amount-based signals and limits behave predictably.
After changing rules, run scenarios in the dashboard Simulación view and confirm Panel metrics before routing production traffic.