Risk Assessment API
Risk assessment enables adaptive authentication by evaluating login attempts against configurable rules. Assessments are created automatically during authentication; rules define the conditions that trigger risk scores.
Admin endpoints require a Bearer token with the appropriate permission. All endpoints are scoped to the tenant identified by the X-Tenant-ID header.
Permission convention: resource:read grants list/get access. resource:write grants create/update/delete access.
Base path: https://api.ithbat.io/api/v1/
Assessments
Risk assessments are created automatically when a user authenticates. Each assessment records the factors that contributed to the risk score and the action the system took in response.
GET /api/v1/risk/assessments
Permission: audit:read
List risk assessments with pagination.
Query Parameters
| Parameter | Type | Description |
|---|---|---|
page | integer | Page number |
limit | integer | Results per page (max 100) |
userId | string | Filter by user ID |
riskLevel | string | Filter: low, medium, high, critical |
action | string | Filter: allow, challenge, block |
from | datetime | ISO 8601 start time |
to | datetime | ISO 8601 end time |
curl "https://api.ithbat.io/api/v1/risk/assessments?riskLevel=high&limit=25" \
-H "Authorization: Bearer <access_token>" \
-H "X-Tenant-ID: <tenant_id>"
Response 200
{
"success": true,
"data": {
"assessments": [
{
"id": "ra_7f3c1e2d4b8a9f0e",
"tenantId": "3e7a9f12-4b2c-4d8e-a1f0-9c2b3d4e5f6a",
"userId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"riskScore": 78,
"riskLevel": "high",
"factors": [
{
"name": "new_device",
"score": 30,
"description": "Login from an unrecognized device"
},
{
"name": "impossible_travel",
"score": 48,
"description": "Location change inconsistent with previous login 4 hours ago"
}
],
"ipAddress": "41.223.45.112",
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
"location": {
"country": "NG",
"city": "Lagos",
"latitude": 6.4541,
"longitude": 3.3947
},
"action": "challenge",
"createdAt": "2026-03-14T08:22:11Z"
}
],
"total": 1,
"page": 1,
"limit": 25,
"totalPages": 1
}
}
GET /api/v1/risk/assessments/{id}
Permission: audit:read
Get a single risk assessment by ID.
curl "https://api.ithbat.io/api/v1/risk/assessments/ra_7f3c1e2d4b8a9f0e" \
-H "Authorization: Bearer <access_token>" \
-H "X-Tenant-ID: <tenant_id>"
Response 200
{
"success": true,
"data": {
"id": "ra_7f3c1e2d4b8a9f0e",
"tenantId": "3e7a9f12-4b2c-4d8e-a1f0-9c2b3d4e5f6a",
"userId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"riskScore": 78,
"riskLevel": "high",
"factors": [
{
"name": "new_device",
"score": 30,
"description": "Login from an unrecognized device"
},
{
"name": "impossible_travel",
"score": 48,
"description": "Location change inconsistent with previous login 4 hours ago"
}
],
"ipAddress": "41.223.45.112",
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
"location": {
"country": "NG",
"city": "Lagos",
"latitude": 6.4541,
"longitude": 3.3947
},
"action": "challenge",
"createdAt": "2026-03-14T08:22:11Z"
}
}
Assessment Fields
| Field | Type | Description |
|---|---|---|
id | string | Unique assessment ID |
tenantId | string | Owning tenant UUID |
userId | string | UUID of the authenticating user |
riskScore | integer | Composite score from 0 (no risk) to 100 (maximum risk) |
riskLevel | string | Derived level: low (0–24), medium (25–49), high (50–74), critical (75–100) |
factors | array | Contributing factors — each has name, score, and description |
ipAddress | string | Client IP address at time of authentication |
userAgent | string | Client user agent string |
location | object | Resolved geolocation with country, city, latitude, longitude |
action | string | Decision taken: allow, challenge, or block |
createdAt | string | ISO 8601 timestamp |
Rules
Risk rules define the conditions under which risk scores are applied to authentication attempts. Rules are evaluated in priority order; all matching rules contribute their scores to the final composite score.
GET /api/v1/risk/rules
Permission: audit:read
List all risk rules for the tenant.
curl "https://api.ithbat.io/api/v1/risk/rules" \
-H "Authorization: Bearer <access_token>" \
-H "X-Tenant-ID: <tenant_id>"
Response 200
{
"success": true,
"data": {
"rules": [
{
"id": "rr_a3f8c2b1d9e047ac",
"tenantId": "3e7a9f12-4b2c-4d8e-a1f0-9c2b3d4e5f6a",
"name": "Login from blocked country",
"description": "Flag authentications originating from sanctioned or high-risk countries",
"condition": {
"type": "country",
"operator": "in",
"value": ["KP", "CU", "IR", "SY"]
},
"riskScore": 90,
"enabled": true,
"priority": 1,
"createdAt": "2026-01-10T00:00:00Z",
"updatedAt": "2026-02-05T14:30:00Z"
},
{
"id": "rr_b4e9d3c2e0f158bd",
"tenantId": "3e7a9f12-4b2c-4d8e-a1f0-9c2b3d4e5f6a",
"name": "Tor exit node",
"description": "Increase risk score for logins originating from known Tor exit nodes",
"condition": {
"type": "ip_reputation",
"operator": "equals",
"value": "tor"
},
"riskScore": 60,
"enabled": true,
"priority": 2,
"createdAt": "2026-01-10T00:00:00Z",
"updatedAt": "2026-01-10T00:00:00Z"
}
],
"total": 2
}
}
GET /api/v1/risk/rules/{id}
Permission: audit:read
Get a single risk rule by ID.
curl "https://api.ithbat.io/api/v1/risk/rules/rr_a3f8c2b1d9e047ac" \
-H "Authorization: Bearer <access_token>" \
-H "X-Tenant-ID: <tenant_id>"
Response 200
{
"success": true,
"data": {
"id": "rr_a3f8c2b1d9e047ac",
"tenantId": "3e7a9f12-4b2c-4d8e-a1f0-9c2b3d4e5f6a",
"name": "Login from blocked country",
"description": "Flag authentications originating from sanctioned or high-risk countries",
"condition": {
"type": "country",
"operator": "in",
"value": ["KP", "CU", "IR", "SY"]
},
"riskScore": 90,
"enabled": true,
"priority": 1,
"createdAt": "2026-01-10T00:00:00Z",
"updatedAt": "2026-02-05T14:30:00Z"
}
}
POST /api/v1/risk/rules
Permission: settings:write
Create a new risk rule.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Rule name (unique within tenant) |
description | string | No | Human-readable description |
condition | object | Yes | Condition that triggers the rule — see condition fields below |
riskScore | integer | Yes | Score to add (0–100) when the condition matches |
enabled | boolean | No | Whether the rule is active (default: true) |
priority | integer | No | Evaluation order; lower numbers run first (default: appended last) |
Condition Fields
| Field | Type | Description |
|---|---|---|
type | string | Factor type: country, ip_address, ip_reputation, device, time_of_day, failed_attempts |
operator | string | Comparison operator: equals, not_equals, in, not_in, greater_than, less_than |
value | any | The value to compare against — string, number, or array depending on type and operator |
curl -X POST "https://api.ithbat.io/api/v1/risk/rules" \
-H "Authorization: Bearer <access_token>" \
-H "X-Tenant-ID: <tenant_id>" \
-H "Content-Type: application/json" \
-d '{
"name": "Excessive failed attempts",
"description": "Raise risk score after repeated authentication failures in a short window",
"condition": {
"type": "failed_attempts",
"operator": "greater_than",
"value": 5
},
"riskScore": 55,
"enabled": true,
"priority": 3
}'
Response 201
{
"success": true,
"data": {
"id": "rr_c5f0e4d3f1g269ce",
"tenantId": "3e7a9f12-4b2c-4d8e-a1f0-9c2b3d4e5f6a",
"name": "Excessive failed attempts",
"description": "Raise risk score after repeated authentication failures in a short window",
"condition": {
"type": "failed_attempts",
"operator": "greater_than",
"value": 5
},
"riskScore": 55,
"enabled": true,
"priority": 3,
"createdAt": "2026-03-19T11:00:00Z",
"updatedAt": "2026-03-19T11:00:00Z"
}
}
PUT /api/v1/risk/rules/{id}
Permission: settings:write
Update a risk rule. All fields are optional; omitted fields retain their current values.
Request Body
| Field | Type | Description |
|---|---|---|
name | string | New rule name |
description | string | New description |
condition | object | Replacement condition |
riskScore | integer | New risk score (0–100) |
enabled | boolean | Enable or disable the rule |
priority | integer | New evaluation priority |
curl -X PUT "https://api.ithbat.io/api/v1/risk/rules/rr_c5f0e4d3f1g269ce" \
-H "Authorization: Bearer <access_token>" \
-H "X-Tenant-ID: <tenant_id>" \
-H "Content-Type: application/json" \
-d '{
"riskScore": 65,
"enabled": true
}'
Response 200 — Returns the updated RuleResponse.
DELETE /api/v1/risk/rules/{id}
Permission: settings:write
Delete a risk rule. Existing assessments that were scored by this rule are not affected.
curl -X DELETE "https://api.ithbat.io/api/v1/risk/rules/rr_c5f0e4d3f1g269ce" \
-H "Authorization: Bearer <access_token>" \
-H "X-Tenant-ID: <tenant_id>"
Response 200
{
"success": true,
"data": {}
}