stile
HTTP API

Verified Person

Check if a user has been previously verified across any site in the stile network, enabling cross-site verification reuse.

The Verified Person API lets you check whether a user has already been verified — either on your site or across the stile network — so you can skip verification for returning users.

All examples on this page assume you've initialized the Node.js SDK. See Installation for setup.

Lookup

POST/v1/verified_person/lookup

Call this from your backend before loading the SDK. If the user is already verified at the required strength, you can skip the SDK entirely.

ParameterTypeDescription
emailstringUser email. At least one of email or phone is required.
phonestringUser phone number. At least one of email or phone is required.
methodsstring[]Only consider verifications that used one of these methods.
min_strengthstringMinimum credential strength to accept. E.g. "document_capture" to only accept doc capture or stronger (MDL, MID, EUDI PID).
max_agestringMaximum age of the verification in days. E.g. "30" for the last 30 days.
curl -X POST https://api.stile.dev/v1/verified_person/lookup \
  -H "Authorization: Bearer vk_test_..." \
  -H "Content-Type: application/json" \
  -d '{
    "email": "user@example.com",
    "min_strength": "document_capture"
  }'
import requests

res = requests.post(
    "https://api.stile.dev/v1/verified_person/lookup",
    headers={"Authorization": "Bearer vk_test_..."},
    json={
        "email": "user@example.com",
        "min_strength": "document_capture",
    },
)
result = res.json()

if result["verified"]:
    print(result["verified_person_id"])
body := strings.NewReader(`{"email":"user@example.com","min_strength":"document_capture"}`)
req, _ := http.NewRequest("POST", "https://api.stile.dev/v1/verified_person/lookup", body)
req.Header.Set("Authorization", "Bearer vk_test_...")
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
const result = await stile.verifiedPersons.lookup({
  email: "user@example.com",
  min_strength: "document_capture",
  max_age: "30",
});

if (result.verified) {
  console.log(result.verified_person_id);
  console.log(result.credentials);
  // [{ method: "MDL", strength: "MDL", verified_at: "...", expires_at: "..." }]
}

Response

{
  "object": "verified_person_lookup",
  "verified": true,
  "verified_person_id": "vp_abc123",
  "credentials": [
    {
      "method": "MDL",
      "strength": "MDL",
      "verified_at": "2025-03-01T12:00:00.000Z",
      "expires_at": "2026-03-01T12:00:00.000Z"
    }
  ]
}

Not found

When no matching credential exists, verified is false and credentials is empty:

{
  "object": "verified_person_lookup",
  "verified": false,
  "verified_person_id": null,
  "credentials": []
}

Credential strength

When using min_strength, credentials are ranked from weakest to strongest:

RankStrengthMethod
1self_attestationUser declaration
2facial_ageAI age estimation
3carrier_lookupMobile carrier verification
4open_bankingBank account verification
5document_capturePhysical ID scan + OCR
6mdlMobile Driver's License
7midMobile ID
8eudi_pidEU Digital Identity

A credential at a given strength satisfies any request at that level or below. For example, a document_capture credential (rank 5) satisfies a min_strength: "facial_age" request (rank 2).

On this page