POST /v2/verify
Billable verify. Use a secret API key (kv_sk_…). Never call this from the browser.
Request
Content-Type: application/json
POST https://api.keverd.com/v2/verify
X-Secret-API-Key: kv_sk_live_…
Content-Type: application/json
{
"event_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}
| Field | Type | Required | Description |
|---|---|---|---|
event_id | string (UUID) | Yes | Event id from browser/mobile collect (getVisitorData / React requestId) |
Response
Content-Type: application/json
{
"event_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"fingerprint": "kvd_…",
"visitor_id": "kvd_…",
"risk_score": 42,
"recommendation": "allow",
"action": "allow",
"reason": ["VPN_DETECTED", "INCOGNITO_DETECTED"],
"reasons": [
{
"code": "VPN_DETECTED",
"explanation": "The connection appears to route through a VPN.",
"evidence": {
"ip": "203.0.113.10",
"asn": "13335",
"asn_name": "Example ISP",
"webrtc": {
"request_ip": "203.0.113.10",
"webrtc_public_ips": ["198.51.100.20"],
"webrtc_matches_request": false
}
}
}
],
"score": 0.42,
"trust_score": 70,
"reputation_score": null,
"signals": {
"hardware": {},
"software": {},
"network": {},
"session": {}
},
"smart_signals": {
"vpn_detected": true,
"proxy_detected": false,
"tor_detected": false,
"incognito_detected": true,
"datacenter_detected": false,
"bot_detected": false,
"risk_score": 42,
"action": "allow",
"browser": "Chrome",
"operating_system": "macOS",
"location": {
"ip": "203.0.113.10",
"city": "Nairobi",
"country_code": "KE",
"country_name": "Kenya",
"ip_timezone": "Africa/Nairobi"
},
"ip_info": {
"asn": "13335",
"asn_name": "Example ISP",
"asn_network": "203.0.113.0/24",
"asn_type": "isp",
"datacenter": false,
"org": "Example ISP"
}
},
"created_at": "2026-07-25T12:00:00Z",
"country_code": "KE",
"country_name": "Kenya",
"page_url": "https://example.com/login",
"page_origin": "https://example.com",
"location": {
"ip": "203.0.113.10",
"city": "Nairobi",
"country_code": "KE",
"country_name": "Kenya",
"region": "Nairobi City",
"ip_timezone": "Africa/Nairobi",
"latitude": -1.286389,
"longitude": 36.817223
},
"ip_info": {
"asn": "13335",
"asn_name": "Example ISP",
"asn_network": "203.0.113.0/24",
"asn_type": "isp",
"datacenter": false,
"org": "Example ISP"
},
"times_seen": 3,
"first_seen": "2026-07-01T09:00:00Z",
"last_seen": "2026-07-25T12:00:00Z",
"is_new": false,
"device_history": {
"times_seen": 3,
"first_seen": "2026-07-01T09:00:00Z",
"last_seen": "2026-07-25T12:00:00Z",
"is_new": false,
"unique_ip_count": 2,
"unique_country_count": 1,
"last_seen_events": [
{
"event_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"timestamp": "2026-07-25T12:00:00Z",
"ip_address": "203.0.113.10",
"country_code": "KE",
"country_name": "Kenya",
"page_url": "https://example.com/login",
"page_origin": "https://example.com",
"risk_score": 42,
"action": "allow"
}
]
}
}
Response fields
| Field | Type | Description |
|---|---|---|
event_id | string | Verified event id |
fingerprint / visitor_id | string | null | Workspace-scoped visitor id |
risk_score | number | null | 0–100 |
action / recommendation | string | null | allow | soft_challenge | hard_challenge | block |
reason | string[] | Flat reason codes (back-compat) |
reasons | object[] | { code, explanation, evidence? } |
score | number | null | Normalized score (0–1 when present) |
trust_score | number | null | Device trust rollup when available |
reputation_score | number | null | Network reputation when available |
signals | object | null | Raw client signals for this event |
smart_signals | object | null | Derived flags + scores |
location | object | null | Geo from IP enrichment |
ip_info | object | null | ASN / ISP / datacenter |
times_seen | number | Sight visits in this workspace |
first_seen / last_seen | string | null | ISO-8601 timestamps |
is_new | boolean | true when times_seen <= 1 |
device_history | object | Full history bag (includes last 5 events) |
page_url / page_origin | string | null | Page context from collect |
country_code / country_name | string | null | From event geo |
created_at | string | null | Event timestamp (ISO-8601) |
device_history.last_seen_events is newest-first (up to 5), including the verified event when present.
Errors
| Status | Body / meaning |
|---|---|
| 400 | Missing / invalid event_id |
| 401 | Bad secret key |
| 402 | Protected-device quota exceeded |
| 404 | Event not found / wrong workspace |

