Getting started

Quickstart

From zero to a server-verified visitor ID in 6 steps. You need a browser page, a backend that can make one HTTP call, and about ten minutes.

1. Get your API keys

Grab both keys from the dashboard under API keys. The public key (vp_pk_...) goes in the browser; the secret key (vp_sk_...) stays on your server. If you are running the stack locally with docker compose up, a demo pair is pre-seeded:

.env.local
# Seeded by the local docker compose stack (API on http://localhost:8080)
NEXT_PUBLIC_VERIPRINT_KEY=vp_pk_demo_public_key
VERIPRINT_SECRET_KEY=vp_sk_demo_secret_key

2. Install the SDK

terminal
npm i @veriprint/sdk

3. Identify in the browser

Create a client once and call identify(). The call collects device signals, posts them to the API, and resolves in one round trip.

app/identify.ts
import { Veriprint } from '@veriprint/sdk';

const vp = new Veriprint({ apiKey: 'vp_pk_demo_public_key' });

const visitor = await vp.identify();

console.log(visitor.visitorId);   // "vp_9f2c31e8a4d0"
console.log(visitor.confidence);  // 0.94: a 0..1 score, varies per request
console.log(visitor.bot.result);  // "notDetected"
console.log(visitor.latencyMs);   // round-trip time measured by the SDK

Prefer a one-shot call? import { identify } from '@veriprint/sdk' and await identify({ apiKey }) does the same thing without holding an instance.

Same-origin by default
The SDK POSTs to /api/veriprint/v1/identify on your own origin by default, so the request is not blocked as third-party traffic. Point it elsewhere with the endpoint option. For local dev, use endpoint: 'http://localhost:8080'. After each response the SDK writes the visitor ID into a cookie, localStorage, and the Cache API, so identity re-anchors after any one store is cleared.

4. The response shape

Every identify call (SDK or raw HTTP) resolves to the same JSON:

identify-response.json
{
  "visitorId": "vp_9f2c31e8a4d0",
  "requestId": "vpr_01j8x2m9k4",
  "confidence": 0.94,
  "confidenceLevel": "high",
  "ip": "203.0.113.42",
  "geo": {
    "country": "Germany",
    "countryCode": "DE",
    "region": "Berlin",
    "city": "Berlin",
    "latitude": 52.52,
    "longitude": 13.405,
    "asn": 3320,
    "asnOrg": "Deutsche Telekom AG",
    "isDatacenter": false,
    "isTor": false
  },
  "incognito": false,
  "bot": {
    "result": "notDetected",
    "type": null,
    "score": 0.02,
    "reasons": []
  },
  "vpnLikely": false,
  "firstSeenAt": "2026-05-03T09:12:44.000Z",
  "lastSeenAt": "2026-07-16T14:03:12.000Z",
  "visitCount": 23,
  "matchedVia": ["cookie", "fingerprint"]
}

confidence is computed per request. Treat it as a score to threshold on, not a constant. matchedVia tells you how the visitor was recognized this time: anchor stores (cookie, localStorage, cache), the fingerprint similarity match, or new for a first sighting.

5. Verify server-side

The browser response is convenient but spoofable. A hostile client can claim any visitorId or report bot.result: "notDetected". Before acting on it (blocking a signup, skipping a CAPTCHA), have your backend fetch the authoritative record by requestId using the secret key:

terminal
curl http://localhost:8080/v1/events/vpr_01j8x2m9k4 \
  -H "x-api-secret: vp_sk_demo_secret_key"

# or equivalently:
#   -H "Authorization: Bearer vp_sk_demo_secret_key"
events-response.json
{
  "requestId": "vpr_01j8x2m9k4",
  "identification": {
    "visitorId": "vp_9f2c31e8a4d0",
    "confidence": 0.94,
    "bot": { "result": "notDetected", "type": null, "score": 0.02, "reasons": [] },
    "...": "the full identify response, exactly as computed server-side"
  }
}

A public key here returns 401; an unknown requestId returns 404. Compare the verified identification.visitorId against whatever the client claimed. A mismatch is itself a strong fraud signal.

6. No JavaScript? Call the API directly

POST /v1/identify is plain JSON over HTTP, so non-JS backends and native apps can call it directly with whatever signals they can collect. Fewer signals means lower confidence, but the contract is identical:

terminal
curl -X POST http://localhost:8080/v1/identify \
  -H "x-api-key: vp_pk_demo_public_key" \
  -H "content-type: application/json" \
  -d '{
    "signals": {
      "timezone": "Europe/Berlin",
      "platform": "MacIntel",
      "hardwareConcurrency": 10,
      "deviceMemory": 16,
      "languages": ["de-DE", "en"]
    },
    "anchors": { "cookieId": "vp_9f2c31e8a4d0" },
    "url": "https://example.com/checkout",
    "sdkVersion": "raw-http"
  }'