PlatformXeDocs
Get API Key

Fraud Detection Quickstart

Render your first fraud verdict in under five minutes.

This guide walks you from zero to a working fraud verdict. You'll end up with an API key scoped for the engine, a Detection Pack addon enabled on your organization, and a confirmed allow verdict in your audit trail.

Prerequisites

  • A PlatformXe organization on the Pro or Enterprise plan.
  • The Detection Pack addon enabled. Toggle it from the portal: Settings → Billing → Addons.
  • An API key with the scopes fraud:decide and fraud:audit (or wildcard *).

Until you accept the Fraud Detection Terms, some endpoints (case management, KYC) will return 402 FRAUD_TERMS_REQUIRED. Phase 6A endpoints (decide, shadow-decide, decisions) are available without the click-through.

1. Render your first verdict

curl -X POST https://api.platformxe.com/api/v1/fraud/decide \
  -H "Content-Type: application/json" \
  -H "x-api-key: pxk_live_your_api_key_here" \
  -d '{
    "subject": { "id": "usr_001", "kind": "user" },
    "action": "transfer",
    "resource": { "id": "txn_8a91", "kind": "transaction" },
    "context": {
      "amount": { "value": 50000, "currency": "NGN" },
      "deviceFingerprint": "df_3f9c..."
    }
  }'

Response:

{
  "success": true,
  "data": {
    "decisionId": "dec_2j7yhq8...",
    "verdict": "allow",
    "score": 0,
    "reasons": [
      {
        "kind": "default",
        "code": "phase_6a_default_allow",
        "weight": 0,
        "detail": "No rules evaluated — Phase 6B wires the rule engine. Default allow."
      }
    ],
    "ttlSeconds": 30,
    "notice": "This verdict is informational and is provided for risk assessment. The tenant remains the decision authority for any action taken. See https://docs.platformxe.com/legal/fraud-detection-terms for full terms.",
    "decidedAt": "2026-05-03T09:14:21.412Z",
    "shadow": false,
    "latencyMs": 4
  }
}

Phase 6A always returns allow with the phase_6a_default_allow reason. Phase 6B wires up velocity, threshold, and condition rules — those start producing real verdicts as soon as you publish your first rule.

2. Confirm it landed in the audit trail

curl https://api.platformxe.com/api/v1/fraud/decisions?limit=5 \
  -H "x-api-key: pxk_live_your_api_key_here"

You should see your new decision at the top of the list, with the same decisionId returned by decide.

{
  "success": true,
  "data": {
    "decisions": [
      {
        "id": "dec_2j7yhq8...",
        "verdict": "allow",
        "subjectId": "usr_001",
        "action": "transfer",
        "resourceKind": "transaction",
        "shadow": false,
        "decidedAt": "2026-05-03T09:14:21.412Z"
      }
    ],
    "count": 1,
    "limit": 5,
    "offset": 0
  }
}

3. Run a shadow verdict

Shadow calls produce a verdict with the same engine inputs but never trigger downstream cascades, meter the call, or enforce a block. They're how you validate rule changes before publishing them in Phase 6B.

curl -X POST https://api.platformxe.com/api/v1/fraud/shadow-decide \
  -H "Content-Type: application/json" \
  -H "x-api-key: pxk_live_your_api_key_here" \
  -d '{
    "subject": { "id": "usr_001", "kind": "user" },
    "action": "transfer",
    "resource": { "kind": "transaction" }
  }'

The response is identical in shape, but shadow: true flags it as informational only.

4. Wire the verdict into your app

The recommended pattern: call decide before you commit the action, branch on the verdict, and surface the decisionId to your support tooling for forensics.

import { PlatformXe } from '@caldera/platformxe-sdk';

const px = new PlatformXe({ apiKey: process.env.PLATFORMX_API_KEY! });

async function processTransfer(userId: string, txnId: string, amount: number) {
  const verdict = await px.fraud.decide({
    subject: { id: userId, kind: 'user' },
    action: 'transfer',
    resource: { id: txnId, kind: 'transaction' },
    context: { amount: { value: amount, currency: 'NGN' } },
  });

  switch (verdict.data.verdict) {
    case 'allow':
      return commitTransfer(txnId);
    case 'review':
      return queueForReview(txnId, verdict.data.decisionId);
    case 'step_up':
      return triggerStepUpAuth(userId, txnId, verdict.data.decisionId);
    case 'block':
      return rejectTransfer(txnId, verdict.data.decisionId);
  }
}

The tenant is always the decision authority. The verdict is informational — commitTransfer, rejectTransfer, and queueForReview are functions you write inside your application, not API calls into PlatformXe.

What's next