MCPInstall

sumsub-integrate-id-connect

End-to-end recipe for integrating Sumsub ID Connect — the OIDC-based "Verify with Sumsub ID" flow that lets a user share previously-verified identity claims with your app. TRIGGER when the user asks to "integrate Sumsub ID Connect", "add Verify-with-Sumsub-ID button", "reuse Sumsub KYC via OIDC", "exchange the Sumsub authorization code", "mint a Sumsub ID share token", or asks how to wire up @sumsub/id-connect, the OIDC code → accesstoken exchange (/api/snsId/oauth/token), the share-token / partner-consent flow, or the share-link redirect. Covers preconditions checklist, automated preflight, frontend button (library button + raw redirect alternative), backend code-for-token exchange, share-token minting, partner-consent shareLink flow, and applicant materialisation through /resources/api/reusableIdentity/reuse. SKIP for the standalone WebSDK / KYC widget (use sumsub-integrate-websdk), or for plain Reusable-KYC-via-API where the donor and recipient are both your own tenants w

Installs
981
Last 24h
+16
Trending rank
#6692
Security
Not audited

Install

Works with every agent the skills CLI supports.

npx skills add https://github.com/sumsub/agent-skills --skill sumsub-integrate-id-connect
  1. 01

    Install

    Run the command in your project. The CLI asks which agents to install for.

  2. 02

    Describe the task

    Ask your agent for something this skill covers. It loads sumsub-integrate-id-connect automatically when relevant.

  3. 03

    Review the result

    The agent follows the SKILL.md steps, scripts and references bundled with the skill.

SKILL.md

The instructions your agent reads when the skill is triggered.

Sumsub — ID Connect integration

Embed the "Verify with Sumsub ID" OIDC flow end-to-end — preconditions → preflight → button → backend exchange → consent → applicant in your workspace.

⚠️ Sandbox tokens only

Do not use a production App Token / secret while wiring this up. 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 preflight enforces this with an sbx: prefix check.

Deeper auth mechanics: sumsub-api-auth.

⛔ Order of operations — do NOT scaffold an app first

This is the single most important rule of this skill. Write no frontend or backend code, create no demo project, scaffold nothing until BOTH gates below are green. The client-side Sumsub setup (Stage 0a) is manual and cannot be done by you — jumping to code before it exists produces an app that can't authenticate, can't redirect, and can't reuse. Always follow this sequence:

  1. Confirm Stage 0a preconditions with the user — one by one. Do not assume any item is done. For each, ask the user whether it exists; if it doesn't, stop and hand them the exact manual step and where to do it (the support email template, the Dev Space → OIDC Settings registration, the App Token minting page, the level creation hand-off). These are Sumsub-dashboard / support actions only — there is no public API for them, so you cannot do them for the user. Wait until every item is confirmed before moving on.
  2. Run Stage 0b preflight and require exit 0. Only after the preconditions are confirmed, run scripts/preflight.sh. Resolve every FAIL (loop back to Stage 0a as needed). Do not proceed on any FAIL.
  3. Only now build. With both gates green, proceed to Stage 1 and scaffold the frontend/backend.

If the user says "just build the demo" before the gates are green, briefly explain why it won't work yet and walk them through the missing precondition first. The code is the last step, not the first.

What ID Connect is (and isn't)

Sumsub ID Connect lets a business request specific verified identity claims — age, name, nationality, email, country of residence, humanness — from a Sumsub ID account belonging to the end-user. Sumsub hosts the entire user-facing flow: sign-in, account creation (if needed), email OTP, any missing verification steps, and a per-recipient consent screen. Your app receives the result as a signed OIDC token plus, optionally, an applicant materialised in your workspace through Reusable KYC.

This is not the WebSDK. The WebSDK runs a full KYC capture inside your page; ID Connect delegates the whole UX to Sumsub.

The lifecycle in one picture

 ┌──────────────────────────────┐
 │ Stage 0a Preconditions check │  manual setup on Sumsub side
 │ Stage 0b scripts/preflight.sh │  automated validation
 └──────────────┬───────────────┘
                │ clientId, levelName, allowlist
 ┌──────────────▼───────────────┐
 │ Stage 1: Frontend "Verify…"  │  authorize redirect with PKCE
 │   button                      │
 └──────────────┬───────────────┘
                │ onSuccess({ code, state })
 ┌──────────────▼───────────────┐
 │ Stage 2: code → access_token  │  POST id.sumsub.com/api/snsId/oauth/token
 │   (client_secret_basic)       │
 └──────────────┬───────────────┘
                │ access_token
 ┌──────────────▼───────────────┐
 │ Stage 3a: → share token       │  POST /resources/accessTokens/sumsubIdShareToken
 └──────────────┬───────────────┘
                │ sharingAllowed?
        ┌───────┴────────┐
        │ false           │
        ▼                ▼ true
 ┌──────────────────┐ ┌──────────────────────────────┐
 │ Stage 3b:        │ │ Stage 4: reuse/preview +     │
 │ shareLink        │ │   reuse/commit               │
 │ redirect + retry │ │ → applicant in your workspace │
 └────────┬─────────┘ └──────────────────────────────┘
          │
          └──────► back to Stage 3a (retry — now sharingAllowed: true)

Endpoints

METHODURLAuthStage
(browser redirect)https://id.sumsub.com/api/snsId/oauth/authorizenone1
GEThttps://id.sumsub.com/.well-known/openid-configurationnone0b
GEThttps://id.sumsub.com/.well-known/jwks.jsonnone(id_token validation)
POSThttps://id.sumsub.com/api/snsId/oauth/tokenclient_secret_basic2
POSThttps://api.sumsub.com/resources/accessTokens/sumsubIdShareTokenApp Token + HMAC3a
POSThttps://api.sumsub.com/resources/snsId/oauth/shareLinkApp Token + HMAC + Bearer3b
GEThttps://api.sumsub.com/resources/api/reusableIdentity/reuse/previewApp Token + HMAC4
POSThttps://api.sumsub.com/resources/api/reusableIdentity/reuseApp Token + HMAC4

The "Enable Sumsub ID Connect" toggle, OIDC client registration (client_secret + redirect_uri allowlist), and sharing-partner registration are Sumsub dashboard UI only — no public-API equivalent.

Stage 0a — Preconditions checklist

Before any code or preflight, the following must already exist on the Sumsub side. Each item maps to a check below or to a runtime failure if missed.

  • Sumsub support has enabled ID Connect for your workspace. This is not a self-serve toggle — until support flips it, no OIDC client can be created and the preflight will report connect_token: ID Connect not enabled for this workspace. Email your CSM or support@sumsub.com first and wait for confirmation. Template:

    ```
    Subject: Enable Sumsub ID Connect for clientId <YOUR_CLIENT_ID> (sandbox)
    
    Hi Sumsub team,
    
    Please enable Sumsub ID Connect for our workspace.
    
      Environment:         sandbox
      clientId:            <YOUR_CLIENT_ID>          (Dashboard top-left)
      Intended scopes:     openid, share, name        (adjust as needed)
      Intended recipients: self                       (or list partner clientIds)
      Use case:            <one-line description of where the button will live>
    
    Once enabled we'll register the OIDC client + redirect URIs in
    Dev Space → OIDC Settings.
    
    Thanks
    ```
    
  • App Token + secret (sandbox). Minted at https://cockpit.sumsub.com/checkus/home?sbx=true via Connect Sumsub to your AI agent -> Build & configure -> Generate token. Both values shown once at creation. → exported as SUMSUB_APP_TOKEN / SUMSUB_SECRET_KEY.

  • OIDC client registered at Dashboard → Dev Space → OIDC Settings. Capture all three: - client_id (public — goes in the browser, used as forClientId for the share token in the common self-recipient case) - client_secret (shown ONCE at creation; if you lose it you must regenerate, which invalidates existing integrations). Required for the Stage 2 code→token exchange — keep it server-side only. - redirect_uri allowlist populated for BOTH callbacks (Sumsub matches byte-for-byte — trailing slash, casing, port, query all matter): - your authorize callback (e.g. https://yourapp.com/auth/callback) - your shareLink callback (e.g. https://yourapp.com/share-complete) Sumsub redirects the browser back to these URLs and requires public HTTPS — a bare http://localhost:3000 won't work for local testing. To develop on your machine, expose your local server with a public HTTPS tunnel (ngrok) and allowlist that origin — see Local development with ngrok below.

  • At least one verification level exists in this workspace. Capture levelName. If none, hand off to sumsub-create-level first — Stage 4 can't materialise an applicant without one.

  • At least one Sumsub ID account with verified data for end-to-end testing. An email-only account (no completed KYC) makes Stage 4 fail with errorCode 10521 reusable-kyc-inactive-sumsub-id-account — see the error table at the end of Stage 4.

Stage 0b — Preflight

scripts/preflight.sh machine-validates the preconditions that can be probed without minting OIDC codes or creating applicants. It does not mutate anything.

SUMSUB_APP_TOKEN=sbx:... SUMSUB_SECRET_KEY=... \
  bash scripts/preflight.sh

Checks (each independent — one failing doesn't abort the others):

CheckWhat it proves
connect_tokenApp-Token HMAC signing is accepted and ID Connect is enabled for the workspace — probes the endpoint with a known-bad code and expects 401 Invalid code (a 404 invalid clientId means ID Connect isn't enabled). This is a connectivity/entitlement probe, not the Stage 2 exchange route.
oidc_discoveryhttps://id.sumsub.com/.well-known/openid-configuration returns a valid OIDC discovery doc
levelsAt least one verification level exists in this workspace

Exit code: 0 on all-PASS / PASS+WARN, 10 on any FAIL. Resolve all FAILs before Stage 1.

Local development with ngrok

ID Connect can't be tested against http://localhost. Sumsub redirects the browser back to your redirect_uri after the authorize flow (Stage 1) and after the shareLink consent flow (Stage 3b), and it requires the URL to be public HTTPS and present in the OIDC client's redirect_uri allowlist byte-for-byte. A bare localhost URL is neither public nor HTTPS, so the redirect fails. For local development, put a public HTTPS tunnel in front of your local server with ngrok and allowlist that origin.

  1. Start your backend locally (the example listens on PORT=3000):

    PORT=3000 node examples/express-callback.js
    
  2. Open a tunnel to that port. Prefer a reserved (static) domain so the URL survives restarts — a free random ngrok URL changes on every launch and forces you to re-edit the allowlist each time:

    ngrok http 3000 --domain=your-reserved-name.ngrok-free.app
    # or, ephemeral URL (changes each restart): ngrok http 3000
    

    ngrok prints a forwarding URL, e.g. https://your-reserved-name.ngrok-free.app.

  3. Allowlist BOTH callbacks at the ngrok origin in Dashboard → Dev Space → OIDC Settings (sandbox workspace) — byte-for-byte, including trailing slash:

    https://your-reserved-name.ngrok-free.app/
    https://your-reserved-name.ngrok-free.app/share-complete
    
  4. Point the app at the public URL, not localhost. The browser's redirect_uri and the server-side shareLink redirectUri must derive from the same public origin, so set PUBLIC_BASE_URL and restart:

    PUBLIC_BASE_URL=https://your-reserved-name.ngrok-free.app \
      PORT=3000 node examples/express-callback.js
    

    Then open the ngrok URL (not localhost:3000) in the browser so the redirect_uri it sends matches the allowlist.

⚠️ Re-register on every URL change. If you use an ephemeral ngrok URL, the allowlist entry (and PUBLIC_BASE_URL) must be updated each time ngrok restarts. A reserved domain avoids this churn.

ngrok's free interstitial ("You are about to visit…") only affects API/XHR calls, not top-level browser navigation, so it doesn't block the OIDC redirects. A reserved domain or paid plan removes it entirely.

Stage 1 — Frontend: the button

⛔ Gate. Do not start this stage until Stage 0a preconditions are all confirmed with the user AND Stage 0b preflight exits 0. If you haven't done both, go back — see "Order of operations" above. This is the first stage where you write code; everything before it is setup you must verify first.

Architecture — what's yours vs Sumsub's

Sumsub provides: the OIDC service (id.sumsub.com), the HMAC API (api.sumsub.com), and the optional @sumsub/id-connect JS library that mounts the button.

You write both halves of the integration:

  • Frontend (this stage) — page with the button. Generates PKCE, kicks off the OIDC redirect to id.sumsub.com, receives ?code= in the callback, POSTs { code, codeVerifier } to your own backend.
  • Backend (Stages 2-4) — HTTP endpoint that your frontend POSTs to. Signs Sumsub API calls with your App Token + secret (which must NEVER reach the browser), orchestrates the chain code → access_token → share token → reuse, and returns the materialised applicant.

The two halves are coupled by one route name — POST /api/sumsub/id-connect/exchange in the examples; rename to fit your routing. Reference pair (matched): examples/oidc-button.html (frontend) + examples/express-callback.js (backend). The backend is a thin orchestrator (~180 lines of Node/Express); port it to your stack of choice — the wire format is identical regardless of language.

⚠️ onSuccess is not a verification signal. It only confirms the user finished the OIDC consent step and Sumsub issued an authorization code. The actual verification verdict comes from Stage 4 — applicant.review.reviewStatus in the /reuse response (immediate, if your recipient level runs no additional checks) or the applicantReviewed webhook (authoritative, for any level that runs post-reuse checks). Never grant access or unlock features based on onSuccess firing.

Three variants — use Method 1 (createButton) by default; the others exist for design-system or no-bundler scenarios.

Method 1 — pre-built button via @sumsub/id-connect (recommended)

import { createButton } from '@sumsub/id-connect';

// PKCE helpers (S256 — full versions in examples/oidc-button.html).
const b64url = (buf) => btoa(String.fromCharCode(...new Uint8Array(buf)))
  .replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
const sha256 = (s) => crypto.subtle.digest('SHA-256', new TextEncoder().encode(s));

// Generate the PKCE pair yourself, store the verifier under YOUR key — Stage 2
// on the backend needs that verifier to exchange the code for an access token.
const verifier  = b64url(crypto.getRandomValues(new Uint8Array(32)));
const challenge = b64url(await sha256(verifier));
sessionStorage.setItem('myapp.pkce.verifier', verifier);

createButton({
  clientId:      '<your-client-id>',
  permissions:   ['openid', 'share', 'name'],
  container:     document.getElementById('button-container'),
  codeChallenge: challenge,                            // library uses YOUR challenge — skips its own PKCE gen
  loginHint:     'user@example.com',                   // optional, prefills the email field
  onSuccess: async ({ code, state }) => {
    const v = sessionStorage.getItem('myapp.pkce.verifier');
    await fetch('/api/sumsub/id-connect/exchange', {
      method:  'POST',
      headers: { 'Content-Type': 'application/json' },
      body:    JSON.stringify({ code, codeVerifier: v, redirectUri: location.href }),
    });
  },
  onError: (err) => console.error('sumsub-id-connect error', err),
});

Why generate PKCE yourself: the Stage 2 token exchange needs the verifier. If you let the library generate it, you depend on the library's internal sessionStorage key (undocumented per minor version) to read it back in onSuccess. Passing your own codeChallenge keeps the verifier under a key you own. Same pattern works for Methods 2 and 3.

Runnable example: examples/oidc-button.html.

Method 2 — your trigger + library modal

Same library, you own the trigger element; library opens the flow in an overlay via openModal({...}). Use when your design system has its own buttons.

Runnable example: examples/oidc-modal.html.

Method 3 — raw OIDC redirect (no library)

Direct navigation to the OIDC authorize endpoint, no Sumsub script on the page. Reach for this when CSP forbids third-party scripts, you're in an SSR-only environment, or you maintain a generic OIDC client across multiple providers.

GET https://id.sumsub.com/api/snsId/oauth/authorize
  ?client_id=<your-client-id>
  &response_type=code
  &redirect_uri=<allowlisted URI>
  &scope=openid+share+name
  &state=<random CSRF nonce>
  &code_challenge=<base64url(SHA256(code_verifier))>
  &code_challenge_method=S256
  &login_hint=<optional email>

You generate the code_verifier (43–128 chars, URL-safe), derive code_challenge = base64url(SHA256(verifier)), store the verifier (sessionStorage), and forward it to your backend after the callback. Sumsub only accepts code_challenge_method=S256 (plain is rejected) and the redirect_uri must match the allowlist byte-for-byte.

Runnable example: examples/oidc-redirect.html.

Choosing scopes

Default ['openid', 'share', 'name']. Add email, profile, or offline_access (refresh token) only when downstream logic actually reads them — extra scopes trigger extra checks in the user-facing flow. Full table: references/scopes-and-claims.md.

Stage 2 — Backend: code → access_token

Exchange the authorization code on the OIDC token endpoint. The code came from the browser authorize flow, so its counterpart is the standard OIDC token endpoint — authenticated with the OIDC client_secret (client_secret_basic), not HMAC.

POST https://id.sumsub.com/api/snsId/oauth/token
Content-Type: application/x-www-form-urlencoded
Authorization: Basic base64(<client_id>:<client_secret>)

grant_type=authorization_code
&code=<the code your frontend got>
&redirect_uri=<exact-match URI from Stage 1 — byte-for-byte>
&code_verifier=<PKCE verifier matched to the code_challenge from Stage 1>

Response (24-hour access_token):

{
  "access_token":  "snd-id-con-a-...",
  "refresh_token": "snd-id-con-r-...",   // only with `offline_access`
  "token_type":    "Bearer",
  "expires_in":    86400,
  "id_token":      "eyJhbGc..."           // only with `openid` — RS256-signed
}

Refresh later via grant_type: "refresh_token"; you cannot request more scopes on refresh than were granted at consent time.

The client_secret stays server-side — never in the browser bundle. The exchange is client_secret_basic / client_secret_post; do not HMAC-sign it. (The App-Token + HMAC auth is still used in Stage 3a/4 for the share token and reuse calls.)

Gotchas

  • Invalid code 401 has three common causes: PKCE mismatch (verifier doesn't hash to the challenge sent at authorize), code already used (single-use; refreshing the callback page double-fires), or code expired (short TTL — exchange immediately).
  • redirect_uri must match Stage 1 byte-for-byte — trailing slash, casing, port and query all count, or the exchange fails.
  • id_token validation — use a mature library (jose, pyjwt, jjwt) against the jwks_uri from .well-known/openid-configuration. Never trust unverified JWT contents.

Stage 3 — Backend: access_token → share token + consent

Mint a share token scoped to a recipient (forClientId). Always implement the consent fallback (Stage 3b) — sharingAllowed: false is returned whenever the user hasn't yet authorised sharing with this specific forClientId. In the common self-recipient case both consents are usually granted in one click on the Stage 1 consent screen, but production code that only handles sharingAllowed: true breaks the first time a user re-enters the flow or a recipient configuration differs.

Stage 3a — mint share token

POST https://api.sumsub.com/resources/accessTokens/sumsubIdShareToken
{
  "sumsubIdConnectToken": "<access_token from Stage 2>",
  "forClientId":          "<recipient clientId>",
  "ttlInSecs":            1800
}

forClientId:

  • Self-recipient (common case): your own workspace clientId, visible in the Dashboard top-left.
  • Third-party recipient: the partner's clientId (they must be pre-registered as a partner in the Dashboard).

Response:

{
  "token":          "_act-snsId-...",
  "forClientId":    "<echoed>",
  "sharingAllowed": true    // or false → continue to Stage 3b
}

Stage 3b — partner-consent shareLink

If sharingAllowed: false, mint a consent link and redirect the user:

POST https://api.sumsub.com/resources/snsId/oauth/shareLink
Authorization: Bearer <access_token from Stage 2>
X-App-Token + X-App-Access-Ts + X-App-Access-Sig

{
  "redirectUri": "<your shareLink callback URL — must be in the allowlist>",
  "forClientId": "<same recipient clientId>",
  "displayMode": "page",
  "state":       "<csrf-or-correlation-id>"
}

Response: { "link": "https://id.sumsub.com/share/<id>" } — expires in 5 minutes.

Persist the access_token server-side keyed by state (in-memory Map is OK for demos; use Redis / encrypted cookie / session table for prod). Redirect the user to the link. After consent, Sumsub redirects back to redirectUri as ?token=<JWT> — a signed RS256 JWT whose payload carries state (alongside sharingAllowed: true and forClientId).

⚠️ state is inside the JWT payload, not a top-level ?state= query param. Decode the token JWT to read state back (verify its signature against the jwks_uri first), then look up the saved access_token by that state. Re-call Stage 3a — the share token now returns sharingAllowed: true. Decoded payload shape: { iss, sub, aud, iat, exp, sharingAllowed, state, forClientId }.

Full reference implementation: examples/express-callback.js (in-memory pendingShare Map keyed by state, /share-complete handler).

Stage 4 — Materialise the applicant

With a usable share token, create the applicant in your workspace. Always preview first.

Preview (no side effects)

GET https://api.sumsub.com/resources/api/reusableIdentity/reuse/preview
  ?shareToken=<token>
  &levelName=<your-level>
  &userId=<externalUserId>

Returns the same ApplicantPublicDto shape that /reuse would create — use it to surface compatibility errors before committing.

Commit (creates the applicant)

POST https://api.sumsub.com/resources/api/reusableIdentity/reuse
  ?shareToken=<token>
  &levelName=<your-level>
  &userId=<externalUserId>

userId is the externalUserId Sumsub stores on the applicant — stable per real user, opaque to the user, tied to your auth system. Same rules as WebSDK.

Reuse error codes

All 400 responses include errorCode (integer) and errorName (kebab-case) suitable for code branching. 401 is generic token validity — no errorCode, just description.

HTTP / errorCodenameCauseAction
401 / —Token is invalidShare token expired (TTL exceeded), already consumed, or malformedRe-mint via Stage 3a — call /sumsubIdShareToken again with the still-valid access_token
400 / 10501not-in-partners-listforClientId is not registered as a sharing partner of your workspaceAdd the recipient as a partner in the Dashboard (Sumsub UI only — no public API)
400 / 10502invalid-partner-idThe partner ID extracted from the share token is invalidRe-check forClientId; re-mint share token against a real partner
400 / 10503invalid-share-tokenShare token is malformed or expiredRe-mint via Stage 3a
400 / 10504non-suitable-share-tokenShare token is not suitable for reuse at the given levelName (scope mismatch)Re-mint share token with matching scope, retry against the same level
400 / 10505reusable-kyc-disabledReusable KYC is disabled for this workspaceContact Sumsub support to enable Reusable KYC for your workspace
400 / 10506reusable-kyc-not-reusableGeneric fallback — donor doesn't meet reuse eligibility and no more specific reason matchedInspect the donor in the Dashboard; pick a different donor or fall back to the WebSDK
400 / 10507reusable-kyc-not-approved-applicantDonor applicant is not in an approved state (pending / rejected / on-hold)Wait for donor's KYC to be approved; use a donor with approved status
400 / 10508reusable-kyc-not-active-applicantDonor applicant is inactive (deactivated / blocked)Use a different donor — reactivation is Sumsub-side
400 / 10509reusable-kyc-not-kyc-moderation-typeDonor's source moderation type is not suitable for reuseDonor needs standard KYC moderation; specialised flows aren't reusable
400 / 10510reusable-kyc-not-selfie-or-identity-docRequired selfie or identity document is missing on donorPick a level without that doc-set, or have donor re-verify
400 / 10511reusable-kyc-not-selfie-livenessRecipient level requires liveness; donor's selfie wasn't captured with livenessUse a level without videoRequired: passiveLiveness on SELFIE, or have donor re-verify with liveness
400 / 10512reusable-kyc-not-req-doc-overlapRequired document types don't overlap between donor and recipient levelsPick a recipient level whose required docs are a subset of donor's
400 / 10513reusable-kyc-not-compatible-doc-typeRecipient level requires document types the donor doesn't carryUse a less strict level, or fall back to the WebSDK for full capture
400 / 10514reusable-kyc-not-actual-poi-dateDonor's Proof of Identity is outdated and not valid for reuseDonor must re-submit fresh POI, or relax recipient level's POI freshness window
400 / 10515reusable-kyc-not-actual-poa-dateDonor's Proof of Address is outdated and not valid for reuseDonor must re-submit fresh POA, or relax recipient level's POA freshness window
400 / 10516reusable-kyc-not-acceptable-ageDonor doesn't meet the age criteria of the recipient levelNo recovery — different user required
400 / 10517reusable-kyc-incompatible-capture-settingsCapture settings (file upload vs live camera, etc.) mismatch between donor and recipientAlign recipient level's captureParams with what donor used, or have donor re-capture
400 / 10518reusable-kyc-email-mismatchDonor's email doesn't match the email already on the recipient applicantResolve duplicate-applicant collision — different externalUserId, or align emails
400 / 10519reusable-kyc-phone-mismatchDonor's phone doesn't match the phone already on the recipient applicantSame as 10518 — resolve collision
400 / 10521reusable-kyc-inactive-sumsub-id-accountDonor Sumsub ID account has no stored documents (email-only, KYC never completed)Donor must complete full KYC on id.sumsub.com first; for testing, use a Sumsub-provided verified test account

After the applicant is materialised, your applicantReviewed webhook is the authoritative signal for verification outcome — wire it up the same way as for the WebSDK. See sumsub-integrate-websdk for the webhook material and sumsub-manage-webhooks for the sandbox webhook subscription setup.

Going-live checklist

When the user says "we're ready for prod":

  • Sumsub support has enabled Sumsub ID Connect for the production clientId (separate from sandbox).
  • Production redirectUris (both authorize and shareLink callbacks) are in the Dashboard allowlist on the prod workspace.
  • Backend token-exchange endpoint is auth-gated (only the authenticated user can exchange a code minted for them).
  • id_token signature is verified against the prod JWKS.
  • externalUserId is stable per real user (not email, not display name).
  • /reuse/preview is called before /reuse so compatibility errors surface as UX, not 4xx noise.
  • Stage 3b shareLink flow is implemented and tested — don't ship code that only handles sharingAllowed: true.
  • In-memory state used for the shareLink callback is replaced with a real session store (Redis / encrypted cookie / DB).
  • App Token + secret + OIDC client_secret are in the prod secret store, not committed and not in browser bundles.
  • Refresh-token storage (if used) is server-side only, encrypted at rest, single-tenant.

See also

  • references/scopes-and-claims.md — full scope table, token-endpoint response shape, error codes.
  • scripts/preflight.sh — preconditions validator.
  • examples/oidc-button.html — Method 1 (createButton) — recommended.
  • examples/oidc-modal.html — Method 2 (openModal).
  • examples/oidc-redirect.html — Method 3 (raw OIDC redirect with PKCE).
  • examples/express-callback.js — full backend (Stages 2-4 incl. Stage 3b consent flow).
  • sumsub-api-auth — auth signing reference.
  • sumsub-create-level — when the workspace has no recipient level yet.
  • sumsub-integrate-websdk — sibling skill; reuse its webhook material once the applicant is materialised.

FAQ

What does the sumsub-integrate-id-connect skill do?

End-to-end recipe for integrating Sumsub ID Connect — the OIDC-based "Verify with Sumsub ID" flow that lets a user share previously-verified identity claims with your app. TRIGGER when the user asks to "integrate Sumsub ID Connect", "add Verify-with-Sumsub-ID button", "reuse Sumsub KYC via OIDC", "exchange the Sumsub authorization code", "mint a Sumsub ID share token", or asks how to wire up @sumsub/id-connect, the OIDC code → accesstoken exchange (/api/snsId/oauth/token), the share-token / partner-consent flow, or the share-link redirect. Covers preconditions checklist, automated preflight, frontend button (library button + raw redirect alternative), backend code-for-token exchange, share-token minting, partner-consent shareLink flow, and applicant materialisation through /resources/api/reusableIdentity/reuse. SKIP for the standalone WebSDK / KYC widget (use sumsub-integrate-websdk), or for plain Reusable-KYC-via-API where the donor and recipient are both your own tenants w

How do I install sumsub-integrate-id-connect?

Run npx skills add https://github.com/sumsub/agent-skills --skill sumsub-integrate-id-connect in your project. The skills CLI detects the agents you use and copies the skill into the right folder. For Claude Code you can also place the skill folder at ~/.claude/skills/sumsub-integrate-id-connect/ (personal) or .claude/skills/sumsub-integrate-id-connect/ (project).

Which AI agents can use sumsub-integrate-id-connect?

Any agent that supports the open Agent Skills format (a folder with a SKILL.md file), including Claude Code, Codex, Cursor, GitHub Copilot, Gemini CLI, Windsurf, Cline, OpenCode and more.

Is sumsub-integrate-id-connect safe to install?

No partner security audit is available yet. Skills can run commands and scripts, so read the SKILL.md and any bundled files before installing.

Who maintains sumsub-integrate-id-connect?

It is published by sumsub in sumsub/agent-skills. It has 981 recorded installs.

More from sumsub/agent-skills

View all →

sumsub-api-auth

sumsub/agent-skills

Authenticate to the Sumsub API with an App Token + secret key (HMAC-SHA256 request signing). TRIGGER when the user asks to "call / sign / authenticate Sumsub API requests", debugs 401 Unauthorized / signature errors against api.sumsub.com, or needs a working request example with X-App-Token / X-App-Access-Sig / X-App-Access-Ts headers. SKIP only when a more specific skill in this repo (questionnaire/level/workflow/POA-preset/generic) already covers the user's actual task — those skills sign requests the same way and only need this one for auth deep dives.

Backend & APIs1.2K installs

sumsub-api-generic

sumsub/agent-skills

Catch-all fallback for any Sumsub API task that does NOT match a more specific skill (e.g. create-sumsub-level, sumsub-create-questionnaire, sumsub-api-auth). TRIGGER when the user wants to call, inspect, or debug a Sumsub API endpoint not otherwise covered — fetching applicants, listing levels, reviewing AML hits, exporting data, generating SDK tokens, anything against api.sumsub.com. The procedure — locate the right endpoint in the OpenAPI schema, read its request/response shape, build the payload, sign with App Token, and validate. SKIP whenever a narrower Sumsub skill already covers the request.

Backend & APIs1.2K installs

sumsub-check-skills-version

sumsub/agent-skills

Verify that the locally installed Sumsub agent-skills package is compatible with the published version before doing any Sumsub work. TRIGGER at the start of any task that touches Sumsub — Sumsub Dev MCP tools (mcpSumsubDev), KYC/AML workflows, applicants, checks, transactions, verification levels, verification links, questionnaires, fraud network, VASP lists, or anything Sumsub-related — so the user is warned before a stale skills package produces wrong results. Also use this skill when the user explicitly asks "are my Sumsub skills up to date / current", "is there a newer version of the Sumsub skills", or similar. Skip the actual update (the user runs npx skills add sumsub/agent-skills --all themselves) and skip any other Sumsub API or entity task — those have their own skills.

AI & Agents1.2K installs

sumsub-create-poa-preset

sumsub/agent-skills

Create or update a Sumsub Proof-of-Address (POA) preset. POST /resources/api/agent/poaStepSettings to create new, PATCH same path to update (id in body), GET /resources/api/agent/poaStepSettings/{id} to read one back. TRIGGER when the user asks to "create / add / build / configure / update / edit a POA preset" or "PoA step settings", configure which proof-of-address document types are accepted (utility bills, bank statements, tax bills, etc.), set validity periods per provider type, enable POI-as-POA (accept identity doc as proof of address), tune the cross-validator (name/address fuzzy match between POI and POA), or add per-country POA overrides. SKIP for attaching a preset to a level (set poaStepSettingsId on the level instead, via sumsub-create-level), or for non-POA presets (cross-check presets, permission presets, etc.).

Backend & APIs1.2K installs

sumsub-manage-webhooks

sumsub/agent-skills

Manage Sumsub clientWebhooks (event subscriptions for applicantReviewed / applicantPending / kytTxn / etc.) — reads via /resources/api/clientWebhooks, writes via /resources/api/agent/clientWebhooks. Sandbox only — production webhooks must be created by a human directly in the Sumsub dashboard. TRIGGER when the user asks to "list / retrieve / show webhooks", "create / add / register a webhook", or "update / edit / change a webhook target / event list / secret / signature algorithm" against their sandbox tenant. SKIP for production webhook setup (refer the user to the dashboard), for unrelated webhook surfaces (Stripe / videoIdent / Fireblocks / NFC / partner-specific receive paths under /resources/webhooks/...), for testing one-off delivery (use the inspectionCallbacks/testWebhook endpoint directly), and for KYT-only webhook routing (that's managed in the Sumsub dashboard's KYT section). The public API does not expose delete or per-webhook delivery stats — for those, refer

Backend & APIs1.2K installs

sumsub-integrate-websdk

sumsub/agent-skills

End-to-end recipe for adding Sumsub KYC to a website or web app via the Sumsub WebSDK. TRIGGER when the user asks to "integrate / embed / add Sumsub", "show the KYC widget", "add WebSDK", "verify users with Sumsub on the frontend", supplies an existing levelName they want to plug into a page, or asks how to wire up access tokens / lifecycle events / webhooks for Sumsub verification in an arbitrary project. Covers the whole loop — level setup, server-side access-token signing, snsWebSdk init (vanilla canonical, React recipe), client lifecycle events, token refresh, source-of-truth via webhooks + applicant GET, sandbox testing, go-live checklist. SKIP for building the level/questionnaire/POA-preset payload itself (use the sibling skills), or for backend-only API calls with no frontend (use sumsub-api-generic).

Backend & APIs1.2K installs

Popular backend & apis skills

View category →

find-skills

vercel-labs/skills

Helps users discover and install agent skills when they ask questions like "how do I do X", "find a skill for X", "is there a skill that can...", or express interest in extending capabilities. This skill should be used when the user is looking for functionality that might exist as an installable skill.

OfficialBackend & APIs4.1M installs

entra-app-registration

microsoft/azure-skills

Guides Microsoft Entra ID app registration, OAuth 2.0 authentication, and MSAL integration. USE FOR: create app registration, register Azure AD app, configure OAuth, set up authentication, add API permissions, generate service principal, MSAL example, console app auth, Entra ID setup, Azure AD authentication. DO NOT USE FOR: Key Vault secrets (use azure-keyvault-expiration-audit), general Azure resource security guidance.

OfficialBackend & APIs566.7K installs

This skill should be used when the user wants to "write agent code", "build an agent with ADK", "add a tool", "create a callback", "define an agent", "use state management" — in a project that needs ADK (Agent Development Kit) API patterns and code examples. It provides a quick reference for agent types, tool definitions, orchestration patterns, callbacks, state management, the graph Workflow API, and reference recipes to study. Do NOT use for scaffolding (use google-agents-cli-scaffold) or deployment (use google-agents-cli-deploy).

Backend & APIs514.8K installs

embedded-captions

heygen-com/hyperframes

Add captions or subtitles to an existing single-subject talking-head video without editing the footage. Use for plain verbatim captions, cinematic captions embedded behind the subject, VFX captions, “炸/特效/酷炫字幕,” or a named identity from the 35-style catalog. Route by visual identity, not by backend engine. The quiet anchor rail is the default; embed every word only when the user explicitly wants a fully cinematic treatment. The workflow runs locally end to end, including transcription and subject matting; split multi-shot footage before applying it.

Backend & APIs453.3K installs

entra-agent-id

microsoft/azure-skills

Provision Microsoft Entra Agent Identity Blueprints, BlueprintPrincipals, and per-instance Agent Identities via Microsoft Graph, and configure OAuth 2.0 token exchange (fmipath, OBO, cross-tenant) including the Microsoft Entra SDK for AgentID sidecar. USE FOR: Agent Identity Blueprint, BlueprintPrincipal, agent OAuth, fmipath token exchange, agent OBO, Workload Identity Federation for agents, polyglot agent auth, Microsoft.Identity.Web.AgentIdentities. DO NOT USE FOR: standard Entra app registration (use entra-app-registration), Microsoft Foundry agent authoring (use microsoft-foundry).

OfficialBackend & APIs336.6K installs

neon

neondatabase/agent-skills

Overview of Neon, a complete set of cloud backend primitives around Lakebase Postgres: Auth, Object Storage, Functions, the AI Gateway, and Realtime. Start here to choose Neon for undecided login, files, APIs, and LLM calls, set up the CLI or MCP server, and follow the branch-first workflow. Use when building an app or backend on Neon, or when "Neon" or "Lakebase Postgres" is mentioned. Child skill neon-postgres wins for an existing DATABASEURL, SQL, schema, inspect, or search. Child skill neon-auth wins for login, users, sessions, identity routing, and Managed Better Auth setup. Child skill neon-realtime wins for live queries in reactive apps and agents. Also use for object storage, S3, buckets, serverless functions, function triggers, cron, AI gateway, LLM calls, realtime, logs, Loki, Grafana, observability, postgres, database, backend, Claimable Neon, neon.new, or a no-signup database.

Backend & APIs237.1K installs