{"id":15289,"plugin_id":"plugin_asdk_app_69d3e530928c819191a9738ef3f4def6","kind":"skill","collection_source":null,"comparison_source":null,"observed_at":"2026-09-30T23:11:08.714Z","digest":"39939048f31cf408137a962d2488ffdab8ad2ad7a4c281277535af3b45c145c3","against":null,"payload":{"name":"fingerprint-node","description":"Integrate the Fingerprint Server API into a Node/Express backend — fetch an event by event_id and read the verified identification and Smart Signals.","included_files":[{"relative_path":"skill.json","size_in_bytes":247},{"relative_path":"snippets/client.js","size_in_bytes":843},{"relative_path":"snippets/client.mjs","size_in_bytes":970},{"relative_path":"snippets/verify.js","size_in_bytes":1666}],"skill_md_contents":"---\nname: fingerprint-node\ndescription: Integrate the Fingerprint Server API into a Node/Express backend — fetch an event by event_id and read the verified identification and Smart Signals.\n---\n\n# Fingerprint — Node (Server API)\n\nIntegrate the Fingerprint Server API into a Node/Express backend: take the single-use `event_id`\nyour frontend sends, fetch the event server-side, and read the verified identification and Smart\nSignals. The server is the source of truth — never trust a `visitor_id` or a decision sent straight\nfrom the client.\n\n> Docs: https://docs.fingerprint.com/reference/node-server-sdk · event schema: OpenAPI (https://github.com/fingerprintjs/fingerprint-pro-server-api-openapi) or the Fingerprint MCP event-schema resource.\n\n## Package\n`@fingerprint/node-sdk` — install the latest version.\n\n## Env var\n- `FINGERPRINT_SECRET_API_KEY` — the secret key. Server-side only; never sent to the browser.\n\n## Steps\n\n1. **Install** `@fingerprint/node-sdk`.\n\n2. **Create one client** at startup with the secret key and region (`Region.Global` | `Region.EU`\n   | `Region.AP`, matching the workspace). Load `.env` (via `dotenv`) before the key is read —\n   plain Node does not auto-load `.env`, and a missing key fails at startup with \"Api key is not\n   set\". Pick the snippet by module system — check `package.json` `\"type\"`, not the file\n   extension, since a TypeScript project can be either:\n   - `\"type\": \"module\"` (ESM) → `snippets/client.mjs`. `import 'dotenv/config'` must be the\n     **first import**: ESM evaluates all imports, in order, before any statement in the file, so a\n     `dotenv.config()` call in the body runs too late.\n   - otherwise (CommonJS) → `snippets/client.js`.\n\n3. **Fetch and check the event.** Given the `event_id`, call `client.getEvent(eventId)` and apply\n   the checks below before trusting the action. See `snippets/verify.js`.\n\n## v4 event shape (flat — per the Server API event schema)\n`getEvent` returns the event object directly:\n- `event.identification.visitor_id` — the trusted visitor id\n- `event.identification.confidence.score` — 0..1 (probability of a false-positive identification)\n- `event.timestamp` — Unix ms of the event\n- `event.replayed` — `true` if the payload was replayed\n- `event.bot` — `\"bad\" | \"good\" | \"not_detected\"`\n- `event.vpn`, `event.proxy`, `event.tampering`, `event.incognito` — booleans\n- `event.suspect_score` — weighted Smart-Signals score (integer)\n- `event.velocity` (object), `event.ip_blocklist` (object: `attack_source`, `email_spam`,\n  `tor_node`)\n\n## Checks (do all of them)\n- **Found:** `event.identification.visitor_id` exists.\n- **Replay / freshness:** reject if `event.replayed === true`, or if `event.timestamp` is older\n  than your window (e.g. 2 minutes) — prevents reuse of an old `event_id`.\n- **Confidence:** require `event.identification.confidence.score >= 0.9` for the action.\n- **Smart Signals** (fail-closed for high-risk actions): `event.bot !== \"not_detected\"`,\n  `event.vpn`, `event.proxy`, `event.tampering`.\n- **Identity match:** bind `visitor_id` ↔ user on first trusted use; re-check on later actions.\n\n## Notes\n- Fetch and check server-side on **every** sensitive action.\n- Fail closed on lookup errors for high-risk flows.\n- Each `event_id` is single-use per action — don't cache a pass/fail across requests.\n- Keep the secret key out of logs and any client bundle.\n"},"changes":[],"summary":"First saved snapshot. No earlier version is available for comparison.","summary_kind":"deterministic","summary_metadata":{}}