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.
Agent Resolve
Resolves the agent identity from the request, loads the agent's profile, active mandates, and behavioral history.
Status Check
Verifies the agent is in an active state and the associated session has not been terminated.
Capability Check
Confirms the agent has the required capabilities for the requested transaction type (e.g., purchase, refund, transfer).
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.
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.
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.
Velocity Check
Evaluates velocity patterns, amount outliers, rapid-fire detection, and known-bad merchant signals.
Risk Assessment
Produces a risk_score from 0.0 (safe) to 1.0 (high risk) based on all accumulated signals.
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.
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_…"