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", "fi
By sumsub · 646 installs
npx skills add sumsub/agent-skills --skill sumsub-integrate-dint-standalone
Source repository · Upstream listing
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 ](../sumsub integrate dint websdk/SKILL.md) 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/home?sbx=true — Connect Sumsub to
your AI agent Build & configure Generate token . 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 ](../sumsub api auth/SKILL.md).
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:
Action Stage 3 confirm event
Login / signup / password reset / 2FA platform event
Money movement (transfer, withdrawal, deposit, payment) platform event + financial txn
Pre KYC signup where you also create the applicant pre KYC create applicant
Guest / high value checkout financial 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
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)
Term What it is Who sets it
sessionId The 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.
deviceBindingId Optional 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.
linkedId Optional — links the fingerprint to an entity (your user id / applicant id). Frontend (optional).
visitorId The 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 ](scripts/preflight.sh) machine validates the workspace
before you write any frontend code:
Check What it proves
behavior token HMAC 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)
levels Verification 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 support@sumsub.com 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:
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 ](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
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 vanilla.html),
[ examples/fisherman react.tsx ](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:
Action Endpoint Doc
Login / signup / password reset / 2FA POST /resources/applicants/ /kyt/txns/ /data?accessToken=… [platform event](https://docs.sumsub.com/reference/send applicant platform event with captured device)
Financial transaction POST /resources/applicants/ /kyt/txns/ /data?accessToken=… [financial txn](https://docs.sumsub.com/reference/send financial transaction with captured device)
Pre KYC signup (create the applicant) create applicant with levelName + accessToken + externalUserId [pre KYC check](https://docs.sumsub.com/reference/use device intelligence for pre 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:
Runnable: [ examples/submit platform event.sh ](examples/submit platform event.sh).
Financial transaction and pre KYC bodies + full field lists:
[ references/standalone flow.md ](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 ](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
[ sumsub integrate dint websdk ](../sumsub integrate dint websdk/SKILL.md) — DI when
the page already embeds the Sumsub WebSDK widget.
[ sumsub integrate websdk ](../sumsub integrate websdk/SKILL.md) — the base
KYC WebSDK embed (token signing, webhook patterns reused here).
[ sumsub api auth ](../sumsub api auth/SKILL.md) — HMAC signing shared by every
Sumsub skill.
[ scripts/preflight.sh ](scripts/preflight.sh) — workspace validator (run
before Stage 1).
[ references/standalone flow.md ](references/standalone flow.md) — concepts,
event types, result reading, pre KYC and financial txn variants.
[Get started with Device Intelligence](https://docs.sumsub.com/reference/get started with device intelligence),
[Generate access token](https://docs.sumsub.com/reference/generate ac