Skip to main content

API Reference

Complete documentation for the Fraud Detection API endpoints.

Base URLโ€‹

http://localhost:8000

Authenticationโ€‹

Currently, the API does not require authentication for local development. Production deployments should implement API key or OAuth authentication.


Endpointsโ€‹

POST /decideโ€‹

Make a fraud decision for a transaction.

Request:

curl -X POST http://localhost:8000/decide \
-H "Content-Type: application/json" \
-d '{
"transaction_id": "txn_abc123",
"idempotency_key": "idem_abc123",
"amount_cents": 9999,
"currency": "USD",
"service_id": "mobile_prepaid_001",
"service_type": "mobile",
"event_subtype": "sim_activation",
"card_token": "card_xyz",
"user_id": "subscriber_789",
"phone_number": "15551234567",
"imei": "353456789012345",
"device_fingerprint": "device_abc",
"ip_address": "192.168.1.100",
"timestamp": "2026-01-04T15:30:00Z"
}'

Request Body:

FieldTypeRequiredDescription
transaction_idstringYesUnique transaction identifier
idempotency_keystringYesKey for duplicate detection
amount_centsintYesTransaction amount in cents
currencystringYesISO 4217 currency code
service_idstringYesTelco service identifier
service_typestringYesmobile or broadband
event_subtypestringNosim_activation, topup, device_upgrade, sim_swap, international_enable, equipment_purchase
card_tokenstringYesTokenized card reference
user_idstringYesSubscriber identifier
phone_numberstringNoSubscriber phone number (telco)
imeistringNoDevice IMEI (telco mobile)
sim_iccidstringNoSIM card ICCID (telco mobile)
device_fingerprintstringYesDevice identifier
ip_addressstringYesSubscriber IP address
timestampstringYesISO 8601 timestamp
device_emulatorboolNoTrue if device is emulated (SIM farm indicator)
device_rootedboolNoTrue if device is rooted/jailbroken
ip_datacenterboolNoTrue if IP is datacenter/cloud
ip_torboolNoTrue if IP is Tor exit node
ip_vpnboolNoTrue if IP is known VPN
card_countrystringNoCard issuing country (ISO 3166)
ip_countrystringNoIP geolocation country

Response:

{
"transaction_id": "txn_abc123",
"decision": "ALLOW",
"scores": {
"overall_risk": 0.15,
"criminal_score": 0.10,
"friendly_fraud_score": 0.08,
"bot_score": 0.02
},
"signals": [],
"latency_ms": 7.8,
"policy_version": "1.0",
"evidence_id": "evt_550e8400-e29b-41d4-a716-446655440000"
}

Response Fields:

FieldTypeDescription
transaction_idstringEcho of request transaction ID
decisionstringALLOW, FRICTION, REVIEW, or BLOCK
scores.overall_riskfloatCombined risk score (0-1)
scores.criminal_scorefloatCriminal fraud probability (0-1)
scores.friendly_fraud_scorefloatFriendly fraud probability (0-1)
scores.bot_scorefloatBot/automation probability (0-1)
signalsarrayList of triggered detection signals
latency_msfloatProcessing time in milliseconds
policy_versionstringPolicy version used for decision
evidence_idstringUUID of stored evidence record

Decision Values:

DecisionDescriptionRecommended Action
ALLOWLow risk, approve transactionProcess normally
FRICTIONMedium risk, needs verificationRequest 3DS/OTP
REVIEWHigh risk, needs manual reviewQueue for analyst
BLOCKVery high risk, declineReject transaction

GET /healthโ€‹

Check system health and component status.

Request:

curl http://localhost:8000/health

Response:

{
"status": "healthy",
"redis": "connected",
"postgres": "connected",
"policy_loaded": true,
"policy_version": "1.0",
"uptime_seconds": 3600
}
FieldDescription
statusOverall health: healthy, degraded, unhealthy
redisRedis connection status
postgresPostgreSQL connection status
policy_loadedWhether policy is loaded
policy_versionCurrent policy version
uptime_secondsSeconds since API started

GET /policy/versionโ€‹

Get current policy version and metadata.

Request:

curl http://localhost:8000/policy/version

Response:

{
"version": "1.0",
"loaded_at": "2026-01-04T10:00:00Z",
"rules_count": 5,
"thresholds": {
"block": 80,
"review": 60,
"friction": 40
}
}

POST /policy/reloadโ€‹

Hot-reload policy configuration without restart.

Request:

curl -X POST http://localhost:8000/policy/reload

Response:

{
"success": true,
"previous_version": "1.0",
"new_version": "1.1",
"loaded_at": "2026-01-04T15:45:00Z"
}

GET /metricsโ€‹

Prometheus metrics endpoint.

Request:

curl http://localhost:8000/metrics

Response (text/plain):

# HELP fraud_decisions_total Total fraud decisions by type
# TYPE fraud_decisions_total counter
fraud_decisions_total{decision="ALLOW"} 1234
fraud_decisions_total{decision="FRICTION"} 56
fraud_decisions_total{decision="REVIEW"} 23
fraud_decisions_total{decision="BLOCK"} 12

# HELP fraud_decision_latency_seconds Decision latency in seconds
# TYPE fraud_decision_latency_seconds histogram
fraud_decision_latency_seconds_bucket{le="0.005"} 800
fraud_decision_latency_seconds_bucket{le="0.01"} 1200
fraud_decision_latency_seconds_bucket{le="0.05"} 1320

# HELP fraud_detector_triggered_total Detector trigger counts
# TYPE fraud_detector_triggered_total counter
fraud_detector_triggered_total{detector="card_testing"} 45
fraud_detector_triggered_total{detector="velocity"} 78
fraud_detector_triggered_total{detector="geo_anomaly"} 23
fraud_detector_triggered_total{detector="bot"} 12
fraud_detector_triggered_total{detector="friendly_fraud"} 34

Error Responsesโ€‹

400 Bad Requestโ€‹

Invalid request payload.

{
"error": "validation_error",
"message": "transaction_id is required",
"details": {
"field": "transaction_id",
"issue": "missing"
}
}

500 Internal Server Errorโ€‹

Server-side error.

{
"error": "internal_error",
"message": "Redis connection failed",
"request_id": "req_abc123"
}

Rate Limitsโ€‹

EnvironmentLimit
DevelopmentUnlimited
Production10,000 req/min (configurable)

Idempotencyโ€‹

The /decide endpoint is idempotent. Sending the same transaction_id multiple times returns the cached result without re-processing:

# First call - processes transaction
curl -X POST http://localhost:8000/decide -d '{"transaction_id": "txn_001", ...}'
# Response: {"decision": "ALLOW", "latency_ms": 8.2, ...}

# Second call - returns cached result
curl -X POST http://localhost:8000/decide -d '{"transaction_id": "txn_001", ...}'
# Response: {"decision": "ALLOW", "latency_ms": 0.3, "cached": true, ...}

This prevents duplicate charges or inconsistent decisions on network retries.