Identity verification is no longer a bolt-on for online gambling operators – it is the gate that decides whether a player can deposit, whether a regulator renews your licence, and whether your fraud team sleeps at night. Sumsub was ranked the #1 iGaming fraud-prevention provider in Gambling IQ’s 2026 “Defenders of Trust” industry report, and its API-and-iframe model has become the default way operators meet KYC and AML obligations across the FCA, CySEC and MAS jurisdictions. This tutorial walks you through a full server-to-server integration – from generating your first signed request to verifying webhook signatures and going live – in 12 concrete steps, with working Node.js and Python code you can paste into a real project.
By the end you will have a reproducible onboarding flow that creates applicants, embeds the verification UI, ingests review results over webhooks, and gracefully handles the failure modes that break most first integrations. Industry teams report a standard configuration can be completed in under 8 hours in 2026 – down from the 3–5 day industry average – but only if you avoid the signature, level-name and webhook-validation traps documented below.
Don't miss new tech stories on Google
Add Tech Insider once in the Google app and our stories appear in your news suggestions.
Why Sumsub KYC Matters for iGaming in 2026
Regulated gambling is the most KYC-intensive vertical on the internet. Operators must verify age, identity, source of funds and sanctions status before a player can transact, then re-screen continuously for the life of the account. Sumsub bundles document verification, biometric liveness, AML watchlist screening and transaction monitoring behind one API, which is why marketplaces like the Auth0 Marketplace now list it as a turnkey identity step. Operators in licensed markets answer to bodies such as the UK’s Financial Conduct Authority (FCA), and the integration exists to produce the evidence those regulators expect.
The fraud and compliance pressure
According to the 2026 Gambling IQ report, Sumsub’s platform detects onboarding and post-onboarding risk – money laundering, bonus abuse, account takeover and collusion – with a 97.5% success rate, a 15% improvement over its 2025 benchmarks. Fraud analyst Kris Galloway, quoted in the same report, credited the system with a 98.5% reduction in false positives for legitimate players versus 2025 legacy stacks, and a 99.2% accuracy rate on bonus-abuse and account-takeover detection. For an operator, fewer false positives means fewer abandoned deposits at the cashier.
Real-world adoption
EvenBet Gaming integrated Sumsub’s KYC API in Q1 2026 to automate AML screening across its global poker network, and by its quarterly report was processing over 500,000 monthly verifications at a 99.9% successful-verification rate. Payments infrastructure provider Monavate went further on 16 April 2026, embedding Sumsub KYC directly into its MonavateOne onboarding product across both the UK and EEA – as reported by FinTech Global – and cut onboarding times from 3 days to 45 minutes, a 90% reduction. These are the throughput numbers a serious gambling platform should design for from day one.
Prerequisites and Version Matrix
This tutorial targets a modern server runtime calling Sumsub’s REST API directly, plus the browser WebSDK for the player-facing flow. Pin the following versions to reproduce the examples exactly.
| Component | Version (2026) | Purpose |
|---|---|---|
| Node.js | 20.x LTS or 22.x LTS | Backend signing + webhook handler |
| Python (optional path) | 3.11+ | Alternative backend example |
| axios | 1.7.x | HTTP client for signed calls |
| express | 4.19.x | Webhook receiver |
| @sumsub/websdk | 2.x | Embedded verification UI |
| Sumsub API base | https://api.sumsub.com | Production REST endpoint |
Refer to the official Sumsub API reference for the authoritative endpoint contracts as you follow along – Sumsub’s own documentation changelog logged fresh KYC-related endpoint updates as recently as August 2026, so re-check it before you pin versions rather than trusting a bookmarked page. You will also need: a Sumsub dashboard account, an App Token and Secret Key from the dashboard (Dev Space → App Tokens), at least one configured verification level, and an HTTPS endpoint reachable from the public internet for webhooks (use a tunnel such as ngrok during development). Keep your Secret Key in an environment variable or a secrets manager – never in source control.
Sumsub pricing tiers you are integrating against
Your tier affects rate limits and which add-ons your level can call. As of July 2026, Sumsub’s standalone KYC API pricing sits alongside the iGaming-specific bundle below: Basic KYC checks run $1.35 each with a $149/month minimum, and Compliance-tier checks run $1.85 each with a $299/month minimum, per Sumsub’s own pricing page. New accounts can trial the API for 14 days with 50 free verifications before committing to either structure. The iGaming-specific bundle published for 2026 is:
| Plan | Price (2026) | Included | Overage |
|---|---|---|---|
| iGaming Starter | $499/month | Up to 5,000 verifications/month | $0.15 per extra verification |
| Fraud Detection Add-on | $150/month | Device intelligence + behavioral analysis | Bundled |
| Enterprise | From $2,500/month | Unlimited verifications, 24/7 live chat support | Custom |
How the Sumsub Integration Architecture Fits Together
Before writing code, understand the data flow. There are three actors: your backend (holds the Secret Key and signs every request), the player’s browser (runs the WebSDK with a short-lived access token), and Sumsub (performs the review and calls your webhook). The Secret Key never touches the browser.
The canonical flow
- A player registers; your backend creates a Sumsub applicant tied to your internal user ID.
- Your backend requests a short-lived access token for that applicant.
- The browser initialises the WebSDK with that token; the player uploads documents and completes liveness.
- Sumsub reviews the applicant and POSTs the result to your webhook.
- Your webhook verifies the signature, updates the player’s KYC status, and unlocks deposits.
Why server-to-server beats client-only
Some teams are tempted to drive everything from the browser. Don’t. The applicant lifecycle, AML re-screening and audit trail must live server-side so that a regulator can be shown a tamper-evident record. The browser only ever holds a token scoped to a single applicant and expiring in minutes. This same separation-of-concerns principle underpins robust age and identity gating elsewhere in gaming – see how platform operators approached it in our breakdown of facial age verification at scale.
Step 1: Provision API Keys and the Environment
In the Sumsub dashboard open Dev Space → App Tokens and generate a token pair. You receive an App Token (public-ish, identifies your app) and a Secret Key (must stay secret). Store them as environment variables.
# .env (never commit this file)
SUMSUB_APP_TOKEN=sbx:abc123YourAppToken
SUMSUB_SECRET_KEY=YourSuperSecretKeyValue
SUMSUB_BASE_URL=https://api.sumsub.com
SUMSUB_WEBHOOK_SECRET=YourWebhookValidationSecret
SUMSUB_LEVEL_NAME=igaming-basic-kyc
Expected result: running printenv | grep SUMSUB shows five variables. Start in the sandbox – sandbox App Tokens are prefixed sbx:. You will swap to a production token (prefixed prod:) only at Step 12.
Step 2: Build the Request Signing Function
Every Sumsub API call must be signed. The signature is an HMAC-SHA256 of the concatenation timestamp + HTTP_METHOD + path + body, keyed with your Secret Key, sent in three headers: X-App-Token, X-App-Access-Ts, and X-App-Access-Sig. Getting this wrong is the single most common reason a first integration returns 401.
// sumsub.js – signed request helper (Node.js 20+, axios 1.7)
import axios from 'axios';
import crypto from 'crypto';
const APP_TOKEN = process.env.SUMSUB_APP_TOKEN;
const SECRET = process.env.SUMSUB_SECRET_KEY;
const BASE = process.env.SUMSUB_BASE_URL;
function sign(method, path, body = '') {
const ts = Math.floor(Date.now() / 1000).toString();
const payload = ts + method.toUpperCase() + path + body;
const signature = crypto
.createHmac('sha256', SECRET)
.update(payload)
.digest('hex');
return { ts, signature };
}
export async function sumsubRequest(method, path, data = null) {
const body = data ? JSON.stringify(data) : '';
const { ts, signature } = sign(method, path, body);
const res = await axios({
method,
url: BASE + path,
data: data || undefined,
headers: {
'X-App-Token': APP_TOKEN,
'X-App-Access-Ts': ts,
'X-App-Access-Sig': signature,
'Content-Type': 'application/json',
'Accept': 'application/json',
},
validateStatus: () => true,
});
if (res.status >= 400) {
throw new Error(`Sumsub ${res.status}: ${JSON.stringify(res.data)}`);
}
return res.data;
}
Critical: the path you sign must include the query string exactly as sent, and the body string used in the signature must be byte-identical to the body you transmit. Stringify once, reuse the same string.
Step 3: Create an Applicant
An applicant is Sumsub’s record of one person. Tie it to your internal user via externalUserId – use your own immutable user ID, never an email, so the record survives email changes.
// createApplicant.js
import { sumsubRequest } from './sumsub.js';
export async function createApplicant(externalUserId) {
const level = process.env.SUMSUB_LEVEL_NAME;
const path = `/resources/applicants?levelName=${encodeURIComponent(level)}`;
const body = {
externalUserId,
type: 'individual',
// optional: prefill known data to speed review
fixedInfo: { country: 'GBR' },
};
const applicant = await sumsubRequest('POST', path, body);
return applicant.id; // store this against your user
}
Expected output: a JSON object whose id is a 24-character hex string (the applicant ID). Persist { userId, applicantId } in your database. If you POST the same externalUserId twice, Sumsub returns the existing applicant – idempotent by design.
Step 4: Choose and Wire the Verification Level
A level defines which checks run: ID document, proof of address, liveness, AML screening, and so on. You create levels in the dashboard, not the API, and reference them by their exact levelName. For gambling, most operators run a tiered model.
| Level | Checks | iGaming use case |
|---|---|---|
| igaming-basic-kyc | ID document + liveness | Registration / first deposit gate |
| igaming-enhanced | + Proof of address + AML screening | Withdrawal threshold / EDD |
| igaming-sof | + Source of funds questionnaire | High-roller / regulator-mandated |
Pitfall: the levelName is case- and character-sensitive. A trailing space or a capital letter that does not match the dashboard returns a 400 levelName not found even though the level exists. Copy it verbatim from the dashboard.
Step 5: Generate a Short-Lived Access Token
The browser cannot hold your Secret Key, so your backend mints a per-applicant access token that the WebSDK exchanges. Tokens default to a short TTL; set it explicitly.
// accessToken.js
import { sumsubRequest } from './sumsub.js';
export async function getAccessToken(externalUserId, ttlSeconds = 600) {
const level = process.env.SUMSUB_LEVEL_NAME;
const path =
`/resources/accessTokens?userId=${encodeURIComponent(externalUserId)}` +
`&levelName=${encodeURIComponent(level)}&ttlInSecs=${ttlSeconds}`;
const res = await sumsubRequest('POST', path);
return res.token; // pass to the browser
}
Expose this behind your own authenticated endpoint – e.g. GET /api/kyc/token – so only a logged-in player can mint a token for their own ID. Never let a client request a token for an arbitrary userId.
Step 6: Embed the WebSDK in the Browser
With a token in hand, the front end renders the verification UI. Use the official WebSDK so liveness, document capture and localisation are handled for you.
<!-- verification.html -->
<div id="sumsub-container"></div>
<script src="https://static.sumsub.com/idensic/static/sns-websdk-builder.js"></script>
<script>
async function launchKyc() {
// your authenticated endpoint returns a fresh token
const res = await fetch('/api/kyc/token', { credentials: 'include' });
const { token } = await res.json();
const sdk = window.snsWebSdk
.init(token, () => fetch('/api/kyc/token', { credentials: 'include' })
.then(r => r.json()).then(d => d.token)) // token refresh callback
.withConf({ lang: 'en', theme: 'dark' })
.on('idCheck.onApplicantStatusChanged', (p) => {
console.log('status changed', p.reviewStatus);
})
.build();
sdk.launch('#sumsub-container');
}
launchKyc();
</script>
Expected result: the player sees Sumsub’s document-upload and selfie flow inside your page. The token-refresh callback is mandatory – without it, a player who lingers past the TTL gets a frozen widget.
Step 7: Receive and Verify Webhooks
Sumsub notifies your backend of review results asynchronously. You must verify the signature on every webhook, or an attacker who learns your URL could forge an “approved” event and unlock deposits. Sumsub signs the raw request body with HMAC using your webhook secret; the digest algorithm is named in the X-Payload-Digest-Alg header (typically HMAC_SHA256_HEX).
// webhook.js – Express 4.19, raw body required for HMAC
import express from 'express';
import crypto from 'crypto';
const app = express();
const WEBHOOK_SECRET = process.env.SUMSUB_WEBHOOK_SECRET;
const ALG_MAP = {
HMAC_SHA1_HEX: 'sha1',
HMAC_SHA256_HEX: 'sha256',
HMAC_SHA512_HEX: 'sha512',
};
app.post('/webhooks/sumsub',
express.raw({ type: '*/*' }), // keep the body as a Buffer
(req, res) => {
const alg = ALG_MAP[req.header('X-Payload-Digest-Alg')] || 'sha256';
const expected = crypto
.createHmac(alg, WEBHOOK_SECRET)
.update(req.body) // raw Buffer, NOT parsed JSON
.digest('hex');
const received = req.header('X-Payload-Digest');
if (!received ||
!crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(received))) {
return res.status(401).send('bad signature');
}
const event = JSON.parse(req.body.toString('utf8'));
handleEvent(event); // see Step 8
res.sendStatus(200); // ack fast; process async if heavy
});
app.listen(3000);
Pitfall: if you put express.json() before this route, the raw body is consumed and your HMAC will never match. The signature must be computed over the exact bytes received.
Step 8: Handle Webhook Event Types
Sumsub emits several event types over the applicant lifecycle. Route on type and, for completed reviews, on the nested reviewResult.reviewAnswer.
| Event type | Meaning | Your action |
|---|---|---|
| applicantCreated | Applicant record exists | Mark status = pending |
| applicantPending | Documents submitted, under review | Show “in review” UI |
| applicantReviewed | Review complete (GREEN/RED) | Approve or reject deposits |
| applicantOnHold | Manual review needed | Notify compliance team |
| applicantReset | Applicant must re-verify | Lock account, prompt re-KYC |
// handleEvent.js
function handleEvent(event) {
const { type, externalUserId, reviewResult } = event;
switch (type) {
case 'applicantReviewed': {
if (reviewResult?.reviewAnswer === 'GREEN') {
markUserVerified(externalUserId); // unlock deposits
} else { // RED
const final = reviewResult.reviewRejectType === 'FINAL';
markUserRejected(externalUserId, final, reviewResult.rejectLabels);
}
break;
}
case 'applicantReset':
lockUserPendingReKyc(externalUserId);
break;
default:
updateUserKycStatus(externalUserId, type);
}
}
A RED result with reviewRejectType: 'RETRY' means the player can resubmit (e.g. blurry photo); FINAL means a hard block – treat it as a fraud signal and route to compliance.
Step 9: Poll Applicant Status as a Safety Net
Webhooks can be delayed or dropped. Implement a reconciliation job that fetches status directly for any applicant stuck in pending beyond a threshold.
// checkStatus.js
import { sumsubRequest } from './sumsub.js';
export async function getApplicantStatus(applicantId) {
const path = `/resources/applicants/${applicantId}/status`;
return sumsubRequest('GET', path); // { reviewStatus, reviewResult }
}
Run this on a cron every few minutes for un-reconciled applicants. Treat the webhook as the fast path and polling as the guarantee – never rely on webhooks alone for a money-gating decision. Operators building high-throughput fraud tooling around exactly this kind of reconciliation loop will find the engineering parallels in our deep dive on the AI fraud-detection and RNG stack behind real-money platforms.
Step 10: Add AML and Ongoing Monitoring
Onboarding KYC is necessary but not sufficient. Regulated operators must screen against sanctions and PEP lists continuously. Sumsub’s enhanced levels include AML screening, and ongoing monitoring re-checks players against updated watchlists automatically.
Enabling AML on a level
Configure AML on the level in the dashboard (it is a level setting, not an API field). When a watchlist hit occurs after onboarding, Sumsub emits an applicantReviewed or dedicated monitoring event with the hit details in reviewResult. Your handler should immediately freeze withdrawals and create a compliance case. For broader market context, see our coverage of best sweepstakes casino sites.
Source-of-funds for high rollers
For players crossing deposit thresholds, escalate them to your igaming-sof level via a fresh access token. The WebSDK will present the additional questionnaire and document requests without any code change beyond switching the level name.
Step 11: Test Thoroughly in the Sandbox
Sumsub’s sandbox lets you simulate every review outcome before touching real users. Create test applicants and use the dashboard’s “simulate” controls (or the documented test document images) to force GREEN, RED-RETRY and RED-FINAL paths.
- Happy path: upload a valid test document → expect
applicantReviewedwithGREEN. - Retry path: upload a blurry image → expect
RED/RETRYand confirm the player can resubmit. - Hard reject: trigger a sanctions hit → expect
RED/FINALand confirm deposits stay locked. - Signature failure: tamper with one byte of a webhook body → confirm your handler returns 401.
Log the correlationId from each webhook; you will need it when opening a Sumsub support ticket.
Step 12: Go Live – Production Checklist
Promotion to production is a deliberate switch, not an accident waiting to happen. Run this checklist:
- Swap
sbx:App Token for theprod:token and update the Secret Key. - Point the webhook URL in the dashboard to your production HTTPS endpoint (valid TLS, no self-signed certs).
- Confirm production levels exist with identical
levelNamevalues. - Set realistic
ttlInSecs(600s is a good default) and verify the token-refresh callback fires. - Load-test against your expected peak – EvenBet processes 10,000+ daily verifications; design headroom accordingly.
- Enable alerting on webhook 401s and on applicants stuck in
pending.
With sandbox parity in place, a standard go-live is the eight-hour exercise the 2026 Gambling IQ report describes – the time sinks are all in the sandbox debugging you have now already done.
A Complete Minimal Project Example
Putting Steps 2–8 together, here is the smallest end-to-end backend that creates an applicant, issues a token, and processes results. This is the skeleton EvenBet- and Monavate-style flows expand on.
// server.js – complete minimal Sumsub backend
import express from 'express';
import crypto from 'crypto';
import { createApplicant } from './createApplicant.js';
import { getAccessToken } from './accessToken.js';
const app = express();
// 1) Player registration → create applicant + token
app.post('/api/kyc/start', express.json(), async (req, res) => {
const userId = req.user.id; // from your auth middleware
await createApplicant(userId); // idempotent
const token = await getAccessToken(userId, 600);
res.json({ token });
});
// 2) Token refresh for the WebSDK callback
app.get('/api/kyc/token', async (req, res) => {
const token = await getAccessToken(req.user.id, 600);
res.json({ token });
});
// 3) Webhook (raw body for HMAC – see Step 7)
app.post('/webhooks/sumsub', express.raw({ type: '*/*' }), (req, res) => {
const expected = crypto.createHmac('sha256', process.env.SUMSUB_WEBHOOK_SECRET)
.update(req.body).digest('hex');
if (!crypto.timingSafeEqual(
Buffer.from(expected),
Buffer.from(req.header('X-Payload-Digest') || ''))) {
return res.status(401).send('bad signature');
}
const ev = JSON.parse(req.body.toString('utf8'));
if (ev.type === 'applicantReviewed' &&
ev.reviewResult?.reviewAnswer === 'GREEN') {
// unlock deposits for ev.externalUserId
}
res.sendStatus(200);
});
app.listen(3000, () => console.log('KYC backend on :3000'));
The same signing logic in Python
If your stack is Python 3.11+, the signing primitive is identical – HMAC-SHA256 over ts + method + path + body:
# sumsub.py
import time, hmac, hashlib, json, requests, os
BASE = os.environ["SUMSUB_BASE_URL"]
TOKEN = os.environ["SUMSUB_APP_TOKEN"]
SECRET = os.environ["SUMSUB_SECRET_KEY"].encode()
def sumsub_request(method, path, data=None):
body = json.dumps(data) if data else ""
ts = str(int(time.time()))
payload = (ts + method.upper() + path + body).encode()
sig = hmac.new(SECRET, payload, hashlib.sha256).hexdigest()
headers = {
"X-App-Token": TOKEN,
"X-App-Access-Ts": ts,
"X-App-Access-Sig": sig,
"Content-Type": "application/json",
}
r = requests.request(method, BASE + path,
data=body if data else None, headers=headers)
r.raise_for_status()
return r.json()
Five Pitfalls That Break First Integrations
These are the failure modes that consume the most debugging hours – addressing them up front is what turns a multi-day integration into an eight-hour one.
- Re-stringifying the body. Signing a freshly-stringified body while sending a differently-ordered one yields a valid-looking request that returns 401. Stringify once, sign and send the same string.
- Parsing the webhook body before HMAC. Any JSON middleware ahead of the webhook route destroys the raw bytes and breaks signature verification. Mount
express.raw()on that route only. - Wrong
levelName. A capitalisation or whitespace mismatch returns “level not found” even though the level exists. Copy verbatim from the dashboard. - Clock skew. The signing timestamp must be within Sumsub’s tolerance of real time. A server clock drifting by minutes produces intermittent 401s; run NTP.
- Trusting webhooks alone. Dropped or delayed webhooks leave players stuck. Always run the Step 9 polling reconciliation as a backstop before any money-gating decision.
Troubleshooting Reference
Keep this table next to your logs during integration.
| Symptom | Likely cause | Fix |
|---|---|---|
| 401 on every API call | Signature payload mismatch | Verify ts+method+path+body order; reuse one body string |
| 401 only sometimes | Server clock drift | Enable NTP; check ts is current epoch seconds |
| 400 levelName not found | Name typo / whitespace | Copy exact levelName from dashboard |
| Webhook 401 from your handler | Body parsed before HMAC | Use express.raw on the webhook route |
| WebSDK freezes after a minute | Token TTL expired | Implement the token-refresh callback |
| Duplicate applicants | externalUserId not stable | Use immutable internal user ID, not email |
| Player approved but deposits locked | Missed applicantReviewed event | Run Step 9 polling reconciliation |
| 403 on accessTokens | App token lacks scope/level | Check token’s permitted levels in dashboard |
Advanced Tips for Production iGaming Flows
Idempotent webhook processing
Sumsub may redeliver a webhook. Store each event’s identifier and make handleEvent idempotent so a redelivered “approved” event never double-credits a bonus or re-triggers a notification.
Tiered step-up verification
Start every player on igaming-basic-kyc for the fastest first deposit, then silently step up to igaming-enhanced when they cross a withdrawal or velocity threshold. Because the level is just a parameter on the access-token call, this requires no front-end change.
Localisation and conversion
Pass lang in withConf to render the WebSDK in the player’s language. Sumsub’s reduction of false positives (a 98.5% improvement cited by Kris Galloway) directly raises cashier conversion – every legitimate player you don’t wrongly block is a retained deposit.
Choosing Between API, iFrame, WebSDK and Mobile SDK
Sumsub exposes four integration surfaces, and picking the wrong one early forces a costly rewrite later. The 2026 product line – marketed as “API & iFrame-driven Solutions” – lets you embed verification directly into a login journey; on 29 May 2026 Sumsub shipped a dedicated Auth0 integration that runs KYC checks natively inside login flows, as covered by FinTech Global, needing, in Sumsub’s words, only “several hours” of work rather than weeks. Kris Galloway noted in May 2026 that the Auth0 listing alone cuts engineering load by 50% versus custom-coded identity flows, and on 18 June 2026 Sumsub pushed the same low-code philosophy further by launching an MCP integration with new AI-agent skills for compliance and KYC setup, as reported by PR Newswire/Morningstar. Here is how the surfaces compare for a gambling operator.
| Surface | Where it runs | Best for | Trade-off |
|---|---|---|---|
| REST API | Your backend | Applicant lifecycle, server logic, audit trail | You build the UI yourself |
| WebSDK | Browser (this tutorial) | Web casinos & sportsbooks | Needs token plumbing |
| iFrame / WebSDK link | Hosted by Sumsub | Fastest launch, low-code | Less styling control |
| Mobile SDK | iOS / Android app | Native gambling apps | Separate build per platform |
The hybrid most operators land on
In practice, serious operators use the REST API for the backend (applicant creation, tokens, status, AML) plus the WebSDK on web and the Mobile SDK in the app – all driven by the same server-side applicant records. If you’re targeting native gambling apps, pin the Mobile SDK to a current build: Sumsub’s Android SDK changelog shows a new mobile KYC SDK release on 17 August 2026, and shipping against an older pin is a common source of stale liveness and document-capture bugs. The iFrame link is a useful fallback for email-based re-verification campaigns where you simply send a player a hosted URL. For broader market context, see our coverage of leading online casino sites.
Why the API still anchors everything
Whichever front-end surface you pick, the applicant, its level, its tokens and its review results are all created and read through the REST API you built in Steps 2–9. That is deliberate: it keeps one tamper-evident source of truth regardless of how many client surfaces you add later.
Rate Limits, Retries and Resilience
A live gambling platform sends bursts of verification traffic during promotions and big sporting events. Sumsub’s API benchmarked 99.8% uptime across 2025–2026, but your client must still be resilient to transient errors and rate limiting.
Exponential backoff with jitter
Wrap sumsubRequest in a retry policy that backs off on 429 and 5xx while never retrying a 4xx caused by your own bad payload. Crucially, sign a fresh timestamp on each retry, because a stale timestamp will fail signature validation.
// retry.js – backoff wrapper around sumsubRequest
import { sumsubRequest } from './sumsub.js';
export async function withRetry(method, path, data, max = 4) {
let attempt = 0;
for (;;) {
try {
return await sumsubRequest(method, path, data); // re-signs each call
} catch (err) {
const status = Number((err.message.match(/Sumsub (\d+)/) || [])[1]);
const retryable = status === 429 || (status >= 500 && status < 600);
if (!retryable || attempt >= max) throw err;
const backoff = Math.min(2 ** attempt * 250, 4000);
const jitter = backoff * 0.3 * ((attempt % 3) / 3); // deterministic jitter
await new Promise(r => setTimeout(r, backoff + jitter));
attempt++;
}
}
}
Queue webhook side-effects
Acknowledge webhooks with a fast 200 and push any heavy work – emails, bonus crediting, compliance-case creation – onto a background queue. Sumsub treats a slow or failed response as undelivered and will redeliver, so a synchronous, slow handler causes duplicate processing. This pairs with the idempotency from the advanced-tips section.
Data Residency, GDPR and Audit Evidence
Identity documents are among the most sensitive personal data you will ever store, and gambling regulators audit how you handle them. A clean Sumsub integration minimises what you hold while maximising the evidence you can produce on demand.
Store references, not documents
Persist the applicantId, the review outcome, timestamps and the correlationId – but let Sumsub be the system of record for the raw document images and biometrics. This shrinks your own breach surface and is the pattern EvenBet and Monavate describe in their 2026 integrations, where onboarding data lives behind Sumsub’s API rather than in the operator’s primary database.
Producing an audit trail
When a regulator asks “prove this player was verified before their first deposit,” you answer with the stored applicantReviewed event (signature-verified), its timestamp, and the level used – a tamper-evident chain. Keep these events immutable; never overwrite a review record, append a new one. The same separation that protects players in mainstream platforms – where identity checks run before the user ever reaches the app – is what makes this defensible at audit time.
Right-to-erasure handling
Under GDPR a player can request deletion. Because Sumsub holds the documents, your erasure workflow calls Sumsub’s deletion endpoints and removes your local references, rather than scrubbing image blobs from a dozen of your own tables. Document this flow before launch – regulators such as the Cyprus Securities and Exchange Commission (CySEC) and the Monetary Authority of Singapore (MAS) increasingly ask to see it.
Performance Benchmarks You Can Design Against
Concrete 2026 numbers let you size infrastructure and set SLAs rather than guess. The figures below come from the named 2026 sources and the operators who published throughput data.
| Metric | 2026 figure | Source |
|---|---|---|
| Standard integration time | Under 8 hours | Gambling IQ “Defenders of Trust” 2026 |
| API uptime | 99.8% | Third-party reliability audit, 2025–26 |
| Fraud/risk detection rate | 97.5% | Gambling IQ 2026 (15% over 2025) |
| False-positive reduction | 98.5% vs 2025 legacy | Kris Galloway, Gambling IQ 2026 |
| EvenBet daily verifications | 10,000+ | EvenBet Gaming, April 2026 |
| EvenBet monthly verifications | 500,000+ @ 99.9% success | EvenBet quarterly report 2026 |
| Monavate onboarding time | 3 days → 45 min (90% cut) | Monavate, Q2 2026 |
Read these as design targets: if a single-server integration handles EvenBet’s 10,000 daily checks comfortably, your bottleneck at launch will be your own database writes and webhook queue, not Sumsub’s API. Provision the queue and the polling reconciler accordingly.
Beyond the Standard Coverage: What the Top-Ranked Pages Miss
The pages currently ranking for this query – Sumsub’s own iGaming landing page, its API reference, and the SDK.finance knowledge base – are excellent at what the product does but thin on how to ship a hardened integration. Across the top results, four topics are consistently absent.
1. Webhook signature verification with real code
The marketing and reference pages describe webhooks but rarely show the exact HMAC verification, the raw-body trap, or the X-Payload-Digest-Alg header handling. Step 7 above closes that gap – and it is the difference between a secure deposit gate and a forgeable one.
2. Reconciliation when webhooks fail
No top result treats webhooks as unreliable. In a money-gating system they must be. The Step 9 polling backstop and idempotent processing patterns are the operational reality the vendor docs omit.
3. Signature debugging and clock skew
The single biggest source of lost hours – payload ordering and NTP drift – gets a troubleshooting table here, not a one-line “use the SDK” hand-wave.
4. iGaming-specific tiering and step-up
Generic KYC guides ignore the gambling-specific pattern of basic-at-signup, enhanced-at-withdrawal, SOF-at-threshold. That tiering is what keeps first-deposit conversion high while satisfying FCA, CySEC and MAS expectations – and it is the part operators actually have to design themselves.
Controlling Verification Cost at Scale
At $0.15 per verification beyond the 5,000-included Starter cap, an operator running EvenBet-scale volume – 500,000 monthly checks – is firmly in Enterprise territory where unlimited verifications at $2,500/month become far cheaper than per-check overage. Knowing where the crossover sits lets you negotiate the right tier instead of bleeding overage fees.
Don’t re-verify needlessly
Each WebSDK launch against a fresh applicant is a billable verification. Reuse the existing applicant for the same player – recall that POSTing the same externalUserId is idempotent and returns the existing record rather than creating (and billing) a new one. Cache the applicant’s last GREEN result and skip a new check entirely unless your risk rules demand a step-up.
Step-up only when risk justifies it
Reserve the costlier enhanced and source-of-funds levels for players who cross withdrawal or velocity thresholds. Running every registrant through igaming-sof at signup burns budget and tanks first-deposit conversion. The basic-at-signup, enhanced-at-withdrawal pattern keeps the average cost per active player low while still satisfying enhanced-due-diligence obligations for the players who trigger them.
Model the crossover before you sign
Plot expected monthly verifications against the two pricing curves: Starter ($499 + $0.15/check over 5,000) versus Enterprise ($2,500 flat). The lines cross near 18,000 verifications per month – above that, Enterprise wins on price alone before you even count the 24/7 support and the fraud add-on. If you’re pricing against the standalone API instead of the iGaming bundle, third-party trackers KYCcost (August 2026) and APIbenchmarks (July 2026) independently confirm Sumsub’s reusable Basic checks at $1.35 with platform minimums from $149/month, and Compliance checks at $1.85 with minimums up to $299/month – useful reference points if your finance team wants a source outside Sumsub’s own pricing page. Build this model with your real funnel numbers so the tier decision is arithmetic, not a guess.
Observability: Knowing the Flow Works in Production
A KYC gate failing silently is worse than one failing loudly – players quietly can’t deposit and you find out from a revenue dip. Instrument three signals from day one.
- Webhook 401 rate. Any sustained nonzero rate means a signature or secret mismatch – alert immediately, because it implies either an attack or a broken deploy.
- Pending-beyond-threshold count. Applicants stuck in
pendingpast your SLA reveal dropped webhooks; this is exactly what the Step 9 reconciler exists to catch, so graph its catch rate. - GREEN-to-deposit latency. Time from
applicantReviewedGREEN to the player’s first successful deposit. A rising trend points to a bug between your verification flag and the cashier.
Log the correlationId on every event and request so a single ticket to Sumsub support carries the trace they need. With these three dashboards and the alerting from the Step 12 checklist, you will see problems before your players do.
Frequently Asked Questions
How long does a Sumsub KYC API integration take in 2026?
A standard configuration can be completed in under 8 hours according to the 2026 Gambling IQ “Defenders of Trust” report – down from the 3–5 day industry average – provided you avoid the signature, level-name and webhook-body pitfalls covered above.
How much does Sumsub cost for an iGaming platform?
The 2026 iGaming Starter tier is $499/month for up to 5,000 verifications, with $0.15 per additional verification. A Fraud Detection add-on is $150/month, and Enterprise plans with unlimited verifications start at $2,500/month.
Do I need to verify webhook signatures?
Yes – without HMAC verification an attacker who discovers your webhook URL could forge an “approved” event and unlock deposits. Verify the X-Payload-Digest over the raw request body using the algorithm named in X-Payload-Digest-Alg.
What is the difference between a level and an applicant?
A level is a reusable definition of which checks run (ID, address, liveness, AML). An applicant is one person being verified against a level. You configure levels in the dashboard and create applicants via the API.
Can I run everything from the browser?
No. Your Secret Key must stay server-side. The browser only ever holds a short-lived access token scoped to a single applicant. The applicant lifecycle, AML re-screening and audit trail belong on the backend for regulatory defensibility.
Which regulators does a Sumsub integration help satisfy?
Sumsub’s 2026 compliance audit reports alignment with FCA, CySEC and MAS requirements. The integration provides the identity, age and AML evidence those regulators expect, but you remain responsible for your own licensing obligations.
What accuracy can I expect from fraud detection?
The 2026 Gambling IQ report cites a 97.5% success rate on onboarding and post-onboarding risk and a 99.2% accuracy rate on bonus-abuse and account-takeover detection, with a 98.5% reduction in false positives versus 2025 legacy systems.
What should I do when a review comes back RED?
Check reviewRejectType. RETRY means the player can resubmit (e.g. a blurry photo); FINAL is a hard block – keep deposits locked and route the case to your compliance team as a fraud signal.







