Server-side verification
The browser SDK provides signals, but browser payloads can be spoofed — use server-side verification for enforcement decisions. Secret API keys never belong in client-side code.
Endpoint
Secret-key authenticated
// Request
{
"session_id": "sess_xxx",
"event": "signup_attempt"
}
// Response
{
"verified": true,
"risk_status": "available",
"risk_score": 87,
"recommendation": "challenge",
"challenge_passed": false,
"challenge_passed_at": null,
"session": {
"visitor_id": "vis_xxx",
"first_seen_at": "2026-09-08T10:00:00.000Z",
"last_seen_at": "2026-09-08T10:05:00.000Z",
"event_count": 4,
"pageview_count": 2,
"risk_reasons": ["vpn_detected", "payment_attempt"],
"ip_rotating": true,
"asn_rotating": false,
"country_rotating": false,
"distinct_ips": 2,
"distinct_asns": 1,
"distinct_countries": 1,
"ips": ["203.0.113.7", "203.0.113.9"],
"countries": ["IL"],
"last_ip": "203.0.113.9",
"last_country": "IL",
"last_country_name": "Israel",
"last_asn": 1680,
"last_asn_name": "Partner",
"last_organization": "Partner Communications",
"network": {
"vpn": true, "proxy": false, "tor": false, "relay": false,
"hosting": false, "datacenter": false, "malicious": false
}
}
}session is the picture Shield has of the whole session, for your own records — an order notification, a fraud queue, a CRM note. risk_reasons are the distinct reasons across every event; ip_rotating, asn_rotating and country_rotating are true when the session was seen from more than one IP, network or country; network flags are true if any event of the session came from that kind of address; last_* describe the most recent event. ips holds at most 10 addresses. Identity is not included — your backend already knows who its customer is.
challenge_passed is true once the visitor completed a Cloudflare Turnstile challenge that Shield verified for this session (see In-page enforcement). Accept challenge only when it is true and reject block to turn in-page friction into a decision no client can bypass. risk_status is unknown when no event of the session had IP intelligence; treat it as monitor, never as safe.
Recommended flow
signup_attempt and receives the initial risk signal.session_id./v1/shield/sessions/verify with your secret API key.Integration example
// Frontend: include session ID in the signup request
const { sessionId } = FindIP.getSession();
await fetch('/api/signup', {
method: 'POST',
body: JSON.stringify({ email, password, findip_session_id: sessionId }),
});
// Backend: verify before creating the account
const verify = await fetch('https://shield.findip.net/v1/shield/sessions/verify', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.FINDIP_SHIELD_SECRET_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
session_id: req.body.findip_session_id,
event: 'signup_attempt',
}),
});