agentsclimarketplace

Sumsub integrate dint standalone

Skill SumSubstance/agent-skills/skills/sumsub-integrate-dint-standalone

Add Sumsub Device Intelligence (the Fisherman JS module) to your own web pages where there is NO Sumsub verification widget — login, signup, password reset, 2FA, checkout, or any high-value action you want fraud-screened. TRIGGER when the user asks to "add device intelligence to login / signup", "fingerprint the device on a custom page", "use Fisherman standalone / self-hosted", "ongoing monitoring of platform events", "pre-KYC device check", "detect multi-accounting at signup", or "send a financial transaction with the captured device". Covers the whole loop — behavior access token, @sumsub/fisherman init + fingerprint, confirming the event (platform event / financial transaction / create-applicant), reading results, sandbox, go-live. SKIP when the page already embeds the Sumsub WebSDK — Device Intelligence rides along inside it, use `sumsub-integrate-dint-websdk`.From its SKILL.md

Install
npx -y skills add SumSubstance/agent-skills --skill sumsub-integrate-dint-standalone

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

2 things to look at

  • no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
  • 5 stars5 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

SKILL.md

16.6 KB, ~3.7k tokens by cl100k_base, as published. Nobody here has run it

Sumsub — Device Intelligence standalone (no WebSDK)

Run Device Intelligence (DI) on your own pages that have no Sumsub verification widget — logins, signups, password resets, 2FA, checkouts. You embed the Fisherman JS module (npm @sumsub/fisherman) directly, capture the device on a user action, and confirm the action to Sumsub so it can screen for device fraud (bots, emulators, VPN/proxy, reused devices, multi-accounting).

This is Sumsub's ongoing-monitoring / pre-KYC path. If your page already shows the Sumsub WebSDK, stop — DI is built into it, use sumsub-integrate-dint-websdk instead.

⚠️ Sandbox tokens only

Do not accept or use a production App Token / secret during integration work. Insist on a sandbox pair from https://cockpit.sumsub.com/checkus/devSpace/appTokens — toggle the workspace to Sandbox first, then Create. Token + secret are revealed once at creation; copy both before closing the dialog. The curl recipes here assume an sbx: token; the preflight enforces it with an sbx: prefix check. Deeper auth mechanics: sumsub-api-auth.

Before you start — fit DI into the existing app

DI should look like it was always part of their codebase — their framework, their components, their styling, their conventions. Don't scaffold over someone's app or introduce a new design system. Read enough of the repo to match it, then ask only what you can't infer:

  • Which action to screen? The high-value submit to hook DI onto — login, signup, withdrawal, checkout, 2FA, password reset. (Show the ones you found in their routes/components as suggestions.)
  • Where's the backend? The server file/route that can mint the behavior token and sign the Stage-3 confirm — HMAC must stay server-side. If they're frontend-only (SPA, no backend), flag that they need a server endpoint and offer to add a minimal one in their stack.
  • Existing Sumsub footprint? Do they already call Sumsub / have App Token + secret wired, an externalUserId convention, a webhook receiver? Reuse it; don't duplicate.
  • How are secrets / env handled? Match their existing pattern (.env, secrets manager, config service) for SUMSUB_APP_TOKEN / SUMSUB_SECRET_KEY — sandbox values only during integration.
  • TypeScript or JS? Match the repo; don't add TS to a JS project or vice-versa.

Map the chosen action to its Stage-3 confirm event:

ActionStage-3 confirm event
Login / signup / password reset / 2FAplatform event
Money movement (transfer, withdrawal, deposit, payment)platform event + financial txn
Pre-KYC signup where you also create the applicantpre-KYC create-applicant
Guest / high-value checkoutfinancial txn

Start with Stage 0 (preflight) to confirm the workspace has the DI entitlement before writing any code. Then implement Stages 1–4 against their files: a token route in their backend style, fisherman.fingerprint() on their existing submit handler (fail-open), the server-side confirm with the event mapped from the chosen action. Touch the minimum needed; follow surrounding code style.

The loop in one picture

 ┌─────────────────────────────┐  ┌──────────────────────────────────────┐
 │ 1. Browser hits your page    │─▶│ Your backend: POST .../accessTokens/  │
 │    (login / signup form)     │  │ behavior {sessionId} → {token}        │
 └─────────────┬───────────────┘  └──────────────────────────────────────┘
               │ behavior access token
 ┌─────────────▼───────────────┐
 │ 2. Browser: @sumsub/fisherman│  ← init(token) → fingerprint() on submit
 │    captures the device       │     returns { visitorId }
 └─────────────┬───────────────┘
               │ user submits (login succeeds / account created)
 ┌─────────────▼───────────────┐  ┌──────────────────────────────────────┐
 │ 3. Your backend confirms the │─▶│ Sumsub runs DI analysis on the event  │
 │    event w/ captured device  │  │ (platform event / txn / applicant)    │
 └─────────────┬───────────────┘  └──────────────────────────────────────┘
               │ verdict + device signals
 ┌─────────────▼───────────────┐  ← Dashboard → Transactions (User
 │ 4. You read results / act    │     platform event); or webhook
 └──────────────────────────────┘

The headline: capturing the device is inert until you confirm the event server-side (Stage 3). Capturing alone produces no verdict — the confirm call is what makes Sumsub run the analysis.

Vocabulary (get these right — they're load-bearing)

TermWhat it isWho sets it
sessionIdThe correlation key. Ties every fingerprint + event in one DI session together, and is the session the behavior token is minted with — so the Stage-3 confirm correlates the captured device to the event server-side, with no device fields in the body.Your backend — generate one per logical session, opaque & unique.
deviceBindingIdOptional alternative linking id. Sumsub is migrating device linking from sessionId to deviceBindingId; on the default flow it is not required. If you use it: pass it to fingerprint(), mint the token with it, and send it at applicant.device.deviceBindingId in the confirm body.Your frontend — a fresh crypto.randomUUID() per action.
linkedIdOptional — links the fingerprint to an entity (your user id / applicant id).Frontend (optional).
visitorIdThe device identifier fingerprint() returns; surfaces in results. On the standalone confirm flow you do not forward it — the token's session ties the capture to the event.Returned by Fisherman.

Stage 0 — Preflight

scripts/preflight.sh machine-validates the workspace before you write any frontend code:

SUMSUB_APP_TOKEN=sbx:... SUMSUB_SECRET_KEY=... \
  bash scripts/preflight.sh
CheckWhat it proves
behavior_tokenHMAC signing is accepted and Device Intelligence is enabled for this workspace — mints a real short-TTL behavior token (discarded, expires on its own; nothing else is mutated)
levelsVerification levels exist. WARN-only — just the pre-KYC confirm path (create-applicant) needs one; platform events work without it

Exit code: 0 on all-PASS / PASS+WARN, 10 on any FAIL. A 403 on behavior_token usually means the DI entitlement is off for the workspace — it's not self-serve; ask your CSM or [email protected] to enable Device Intelligence, mentioning your clientId (Dashboard top-left) and environment (sandbox/production). Resolve all FAILs before Stage 1.

Stage 1 — Backend: mint a behavior access token

Separate endpoint from the WebSDK token — note the /behavior suffix and the JSON body:

POST https://api.sumsub.com/resources/accessTokens/behavior
Content-Type: application/json
{ "sessionId": "<your-session-id>", "ttlInSecs": 1800 }
  • Auth: App Token + HMAC. The body is part of the signature — sign ts + "POST" + path + body (the empty-body shortcut from the WebSDK skill does not apply here). See examples/behavior-token.sh.
  • Response: { "token": "_act-jwt-..." } — the JWT is the token field, not accessToken. (Behavior tokens carry no userId, unlike the WebSDK access-token endpoint.)
  • TTL defaults to 1800s. Mint on demand per session; don't cache globally.

Wire it as an auth-gated route on your backend (e.g. POST /api/di/token) that generates/looks up the sessionId, signs, calls Sumsub, and returns the response token to the browser.

Stage 2 — Frontend: capture the device with Fisherman

npm i @sumsub/fisherman --save
// Shape only — the full impl (fail-open try/catch, React StrictMode teardown) is in
// examples/fisherman-vanilla.html and examples/fisherman-react.tsx.
import { init, destroy } from '@sumsub/fisherman'

// init once when the page / form mounts — getBehaviorToken() calls your Stage-1 route
const fisherman = await init({
  token: await getBehaviorToken(),
  baseUrl: 'https://api.sumsub.com',          // region-specific API host
  accessTokenUpdateHandler: getBehaviorToken, // refresh near expiry
  onError: () => destroy(),                   // never let DI block your form
})

// on the user action (e.g. login submit) — gate, fresh deviceBindingId, then confirm server-side
if (fisherman?.isDeviceIntelligenceEnabled) {
  const deviceBindingId = crypto.randomUUID()
  await fisherman.fingerprint({ deviceBindingId /*, linkedId: userId */ })
  // Fisherman posts the capture under the token's session — your Stage-3 confirm
  // call needs only the same accessToken to tie this device to the event.
}
destroy() // re-init for the next action

Rules:

  • Gate fingerprint() on isDeviceIntelligenceEnabled — skip silently if DI is off for the workspace.
  • A fresh deviceBindingId per action. Correlation of the capture to the confirm call is the token's sessionId, not this id — only the deviceBindingId migration path needs it echoed in the confirm body (Stage 3).
  • DI must never block your real flow — wrap in try/catch, fail open.
  • destroy() after the action; re-init() for the next one. Refresh tokens via accessTokenUpdateHandler (or call updateAccessToken(newToken) manually).

Runnable starting points: examples/fisherman-vanilla.html, examples/fisherman-react.tsx.

Stage 3 — Backend: confirm the event with the captured device

Tell Sumsub the action happened; the captured device rides along via the token's session. Pick the call that matches the action — all use your standard App Token + HMAC signing (sign ts + "POST" + path + body, exactly like every other Sumsub API call), and additionally carry the behavior access token as the ?accessToken= query param so Sumsub ties the captured device to the event. The accessToken does not replace signing — it rides alongside it:

ActionEndpointDoc
Login / signup / password reset / 2FAPOST /resources/applicants/-/kyt/txns/-/data?accessToken=…platform event
Financial transactionPOST /resources/applicants/-/kyt/txns/-/data?accessToken=…financial txn
Pre-KYC signup (create the applicant)create applicant with levelName + accessToken + externalUserIdpre-KYC check

How the device links: the confirm call is App-Token + HMAC signed and carries the same behavior access token as ?accessToken=. Sumsub correlates the captured fingerprint to the event server-side using the session the token was minted with (it reconstructs the key from your externalUserId; the token scopes the session). You do not put visitorId or a device block in the body — just identify the user + the event:

{
  "txnId": "<unique-id-you-generate>",
  "type": "userPlatformEvent",
  "applicant": { "externalUserId": "<your-user-id>", "type": "individual" },
  "userPlatformEventInfo": { "type": "login" }
}

Runnable: examples/submit-platform-event.sh. Financial-transaction and pre-KYC bodies + full field lists: references/standalone-flow.md.

deviceBindingId-based linking (Sumsub is migrating to it) is the exception: mint the token with a deviceBindingId, pass the same one to fingerprint(), and send it at applicant.device.deviceBindingId. The default flow keys on sessionId and needs none of that.

For pre-KYC, also add creationTrackingData.ip to the applicant if you want Advanced IP verification, then request the applicant check to trigger the DI analysis.

Stage 4 — Read the results

  • Dashboard: Transactions and Travel Rule → Transactions, filter by type User platform event → open the row → device details + risk labels.
  • Webhooks: subscribe to the transaction/event reviewed webhooks to gate programmatically (same signature-verification rules as the WebSDK skill — verify on raw bytes).
  • Device risk labels + scoring are the same catalog as the WebSDK path: references/standalone-flow.md. Full signal definitions are in the sumsub-integrate-dint-websdk skill's references/device-signals.md (install that skill for the file).

Decide which device labels are blocking (refuse / step-up) vs informational (log) — that policy is yours.

Sandbox testing

  • Sandbox has no real device signals; Fingerprint is simulated. Use the simulationConfig (FpSimulationConf) option on init to force specific signals for deterministic test outcomes.
  • Run the full loop in sandbox (token → fingerprint → confirm) and confirm a User platform event transaction appears in the dashboard.

Going live checklist

  • Backend mints the behavior token (/accessTokens/behavior), signing the body, with a unique per-session sessionId.
  • Token endpoint is auth-gated (only your authenticated context can mint).
  • Frontend fails open — a Fisherman error never blocks login/signup.
  • Unique sessionId per session in the behavior token — it's what correlates the captured device to the confirm call (no device fields needed in the body).
  • You confirm the event server-side (platform event / txn / applicant) so Sumsub actually runs the analysis — capturing alone produces no verdict.
  • Results read from the dashboard / webhook, not from the browser.
  • Production App Token + secret in the prod store; sandbox values stay in dev.

See also

What ships with it: 7 files

26.6 KB alongside SKILL.md, 3 of them executable

references/

scripts/

Keep looking

Skills are one crate of 325,949. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.