Risk
Score the fraud risk of an IP, email, phone, or device — standalone, before or alongside a verification session.
The Risk API scores the fraud risk of a set of signals — IP, email, phone, device — and returns a level and a recommended action. Use it to pre-screen a user before starting verification, to gate a high-value action, or to enrich your own fraud model. It's a standalone endpoint: no verification session is required, though you can attach one.
PII is hashed
Identifiers you send (IP, email, phone) are hashed server-side before anything is persisted — the raw values are used only to compute the score for this request.
Score risk
/v1/risk/scoreAt least one identifier — ip, email, phone, or device_id — is required.
| Parameter | Type | Description |
|---|---|---|
ip | string | The user's IP address (IPv4 or IPv6). |
email | string | The user's email address. |
phone | string | The user's phone number. |
device_id | string | A device fingerprint or stable device identifier you collected. |
user_agent | string | The browser/user-agent string, used for additional signal. |
session_id | string | Optional verification session (vks_...) to associate. When set, the assessment rolls up into that session's risk view. |
claimed_country | string | The jurisdiction the user claims (ISO 3166, e.g. "US", "US-CA", "DE"). Compared against IP-derived geo. |
doc_country | string | ISO 3166 alpha-2 country of a document the user presented, when available. |
doc_region | string | 1–3 character region/state code of a presented document, when available. |
required_jurisdiction | string | The jurisdiction your use case requires (ISO 3166). Lets the engine flag a mismatch against the user's signals. |
curl https://api.stile.id/v1/risk/score \
-H "Authorization: Bearer stile_sk_..." \
-H "Content-Type: application/json" \
-d '{
"ip": "203.0.113.10",
"email": "user@example.com",
"claimed_country": "US-CA"
}'const res = await fetch("https://api.stile.id/v1/risk/score", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.STILE_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
ip: "203.0.113.10",
email: "user@example.com",
claimed_country: "US-CA",
}),
});
const assessment = await res.json();import requests, os
res = requests.post(
"https://api.stile.id/v1/risk/score",
headers={"Authorization": f"Bearer {os.environ['STILE_API_KEY']}"},
json={"ip": "203.0.113.10", "email": "user@example.com", "claimed_country": "US-CA"},
)
assessment = res.json()Response
{
"id": "risk_assessment_abc123",
"object": "risk_assessment",
"risk_score": 18,
"risk_level": "low",
"recommendation": "allow",
"triggered_signals": ["geo_mismatch"],
"reasons": ["Claimed jurisdiction differs from IP-derived location"],
"signal_details": {},
"created": 1741564800
}| Parameter | Type | Description |
|---|---|---|
risk_score | number | The numeric risk score. |
risk_level | "low" | "medium" | "high" | The bucketed risk level. |
recommendation | "allow" | "review" | "block" | The suggested action — `allow` for low, `review` for medium, `block` for high. Advisory; your application decides. |
triggered_signals | string[] | The signal keys that fired for this assessment. |
reasons | string[] | Human-readable explanations for the triggered signals. |
signal_details | object | Per-signal detail used to compute the score. |
Retrieve an assessment
/v1/risk/:idFetch a previously computed assessment by its id.
curl https://api.stile.id/v1/risk/risk_assessment_abc123 \
-H "Authorization: Bearer stile_sk_..."Risk runs inside verification too
You don't have to call this API to benefit from risk scoring — supplementary signals (IP analysis, device risk, geolocation) run automatically inside a verification session when your workflow includes them. This endpoint is for scoring outside of, or ahead of, a session.