Authorization Engine

Real-time transaction authorization combining mandate enforcement, risk scoring, decision trust evaluation, and behavioral anomaly detection.

Overview

The authorization engine processes every transaction request through a multi-stage pipeline that evaluates compliance, risk, and behavioral trust in real time. Decisions are returned in 23ms P50, under 100ms P95, and under 200ms P99 at sustained 150K auth/hour.

The engine produces one of three decisions: APPROVE, DECLINE, or STEP_UP (requires additional verification). Each decision includes detailed metadata about which checks passed or failed, enabling full auditability.

The authorization pipeline

Every authorization request flows through these stages sequentially. If any stage produces a terminal decision, the pipeline short-circuits and returns immediately.

1

Agent Resolve

Resolves the agent identity from the request, loads the agent's profile, active mandates, and behavioral history.

2

Status Check

Verifies the agent is in an active state and the associated session has not been terminated.

2b

Capability Check

Confirms the agent has the required capabilities for the requested transaction type (e.g., purchase, refund, transfer).

2c

Intent Anomaly Gate

Compares the agent's stated intent_context against its session-level behavioral patterns. Detects prompt injection attempts, context drift, and goal misalignment.

3

Mandate Enforcement

Verifies the transaction is within the agent's active mandate: amount limits, daily/monthly caps, merchant category codes, country restrictions, and expiry date.

3b

Behavioral Overlay

Computes the agent's current KYA Score across 6 anomaly dimensions. Applies the decision limit multiplier based on the agent's trust zone, potentially reducing effective spending limits.

4

Velocity Check

Evaluates velocity patterns, amount outliers, rapid-fire detection, and known-bad merchant signals.

5

Risk Assessment

Produces a risk_score from 0.0 (safe) to 1.0 (high risk) based on all accumulated signals.

6-7

KYA Trust Scoring + Decision

Combines all signals into a final KYA trust score and decision. Updates agent metrics, fires relevant webhooks, logs the authorization for audit, and returns the response.

Request format

The POST /api/v1/authorize endpoint accepts the following fields:

Field Type Required Description
agent_id string Yes ID of the agent making the transaction
amount string Yes Transaction amount as a decimal string (e.g., "49.99")
currency string Yes ISO 4217 currency code (e.g., "USD", "EUR")
merchant string Yes Merchant name or identifier
mcc string No Merchant Category Code (4-digit)
country string No ISO 3166-1 alpha-2 country code of merchant
intent_context object Yes Agent's reasoning for the transaction. Must include intent_type (one of PURCHASE, REPEAT_PURCHASE, RECURRING, COF, REFUND, TRANSFER), plus task description, reasoning chain, and confidence level
session_id string No Group transactions into a session for behavioral correlation
idempotency_key string No Prevents duplicate processing if retried

Response format

The authorization response provides the decision along with all signals that contributed to it:

{
  "decision": "APPROVE",
  "authorization_id": "auth_7f3k9x2m",
  "agent_id": "agent_abc123",
  "amount": "42.99",
  "currency": "USD",
  "trust_score": 0.87,
  "risk_score": 0.12,
  "gates_fired": [],
  "cognitive_limit_multiplier": 1.0,
  "effective_limit": "500.00",
  "mandate_id": "mnd_xyz789",
  "recommendations": [],
  "timestamp": "2026-05-25T14:32:01.234Z"
}
Field Description
decision APPROVE, DECLINE, or STEP_UP
authorization_id Unique ID for this authorization event (for audit trail)
trust_score Agent's current KYA Score at time of evaluation (0.0 - 1.0)
risk_score Transaction-specific risk assessment (0.0 - 1.0)
gates_fired Array of gate names that triggered during evaluation
cognitive_limit_multiplier Current multiplier applied based on trust zone
effective_limit Actual spending limit after decision multiplier applied
recommendations Suggested actions when declined (e.g., "reduce amount", "verify intent")

Decisions

APPROVE

The transaction passed all checks. The agent is within mandate limits, risk is acceptable, and decision trust is sufficient. Process the payment.

DECLINE

The transaction was rejected. Check gates_fired for specific reasons and recommendations for suggested remediation. Common decline reasons: mandate exceeded, high risk score, CRITICAL trust zone, or intent anomaly detected.

STEP_UP

The transaction requires additional verification before it can proceed. This occurs when the system detects moderate risk or ambiguity. Implement a step-up challenge (e.g., re-confirm with the human principal) and re-submit if confirmed.

Step-up flow

When you receive STEP_UP, present the transaction details to the human principal for confirmation. If confirmed, re-submit the same authorization request with an additional "step_up_confirmed": true field.

Gates

Gates are named safety checks that can fire during authorization. When a gate fires, it appears in the gates_fired array and may influence the decision.

Gate Trigger Typical Decision
mandate_exceeded Amount exceeds per-transaction, daily, or monthly mandate limits DECLINE
mandate_expired The agent's mandate has passed its valid_until date DECLINE
mcc_blocked Transaction's MCC is in the mandate's blocked list or not in allowed list DECLINE
country_blocked Merchant country is restricted by the mandate DECLINE
risk_velocity Spending velocity exceeds normal patterns (z-score spike) STEP_UP
risk_amount_outlier Transaction amount is a statistical outlier for this agent STEP_UP
risk_rapid_fire Too many requests in a short window (rate limiting) DECLINE
cognitive_decline Agent's KYA Score is in RED or CRITICAL zone, reducing effective limits DECLINE or STEP_UP
intent_anomaly Agent's stated intent doesn't match behavioral patterns (possible prompt injection) DECLINE
session_terminated Agent's session was terminated due to repeated failures DECLINE

Code examples

Complete authorization flow with decision handling. Submit the request to POST /api/v1/authorize with your Client API key in the X-API-Key header, then branch on the returned decision:

curl -X POST https://api.mandatelabs.ai/api/v1/authorize \
  -H "X-API-Key: mdt_live_…" -H "Content-Type: application/json" \
  -d '{
    "agent_id": "agt_…",
    "amount": "149.99",
    "currency": "USD",
    "merchant": "Amazon Web Services",
    "mcc": "5734",
    "country": "US",
    "intent_context": {
      "intent_type": "PURCHASE",
      "task_reference": "cloud_infrastructure_scaling",
      "reasoning_summary": "Auto-scaling triggered by traffic spike"
    },
    "session_id": "sess_daily_ops_20260525"
  }'

# Response includes "decision": "APPROVE" | "DECLINE" | "STEP_UP",
# plus authorization_id, trust_score, risk_score, gates_fired, recommendations.
import httpx

resp = httpx.post(
    "https://api.mandatelabs.ai/api/v1/authorize",
    headers={"X-API-Key": "mdt_live_…"},
    json={
        "agent_id": "agt_…",
        "amount": "149.99",
        "currency": "USD",
        "merchant": "Amazon Web Services",
        "mcc": "5734",
        "country": "US",
        "intent_context": {
            "intent_type": "PURCHASE",
            "task_reference": "cloud_infrastructure_scaling",
            "reasoning_summary": "Auto-scaling triggered by traffic spike",
        },
        "session_id": "sess_daily_ops_20260525",
    },
)
result = resp.json()

# Handle the decision
if result["decision"] == "APPROVE":
    print("Transaction approved")
    process_payment(result["authorization_id"])
elif result["decision"] == "STEP_UP":
    print(f"Step-up required. Gates: {result['gates_fired']}")
    # Request human confirmation, then re-submit
elif result["decision"] == "DECLINE":
    print(f"Declined. Reasons: {result['gates_fired']}")
    print(f"Recommendations: {result['recommendations']}")
const resp = await fetch("https://api.mandatelabs.ai/api/v1/authorize", {
  method: "POST",
  headers: { "X-API-Key": "mdt_live_…", "Content-Type": "application/json" },
  body: JSON.stringify({
    agent_id: "agt_…",
    amount: "149.99",
    currency: "USD",
    merchant: "Amazon Web Services",
    mcc: "5734",
    country: "US",
    intent_context: {
      intent_type: "PURCHASE",
      task_reference: "cloud_infrastructure_scaling",
      reasoning_summary: "Auto-scaling triggered by traffic spike",
    },
    session_id: "sess_daily_ops_20260525",
  }),
});
const result = await resp.json();

// Handle the decision
if (result.decision === "APPROVE") {
  console.log("Transaction approved");
  processPayment(result.authorization_id);
} else if (result.decision === "STEP_UP") {
  console.log(`Step-up required. Gates: ${result.gates_fired}`);
  // Request human confirmation, then re-submit
} else if (result.decision === "DECLINE") {
  console.log(`Declined. Reasons: ${result.gates_fired}`);
  console.log(`Recommendations: ${result.recommendations}`);
}

To review past authorization decisions for an agent, query the authorization history endpoint (newest first, paginated):

curl "https://api.mandatelabs.ai/api/v1/authorize/log/agent/agt_…?limit=10" \
  -H "X-API-Key: mdt_live_…"

Next steps