
sumsub-create-level
Create or update a Sumsub applicant level. POST /resources/applicants/-/levels to create new, PATCH same path to update (id in body), GET /resources/applicants/-/levels/{id} to read one back. TRIGGER when the user asks to "create / add / build / update / edit a Sumsub level", supplies a list of required steps for an applicant flow (identity / selfie / proof-of-residence / questionnaire / payment methods / email or phone verification / KYB / e-sign), or wants a level wired to a specific questionnaireDefId. SKIP for other Sumsub entities (questionnaires, workflows, applicants) or for one-off subsetting tweaks not covered by the compact spec (use sumsub-api-generic for those).
- Installs
- 1.2K
- Last 24h
- +16
- Trending rank
- #6801
- Security
- Not audited
Install
Works with every agent the skills CLI supports.
npx skills add https://github.com/sumsub/agent-skills --skill sumsub-create-level- 01
Install
Run the command in your project. The CLI asks which agents to install for.
- 02
Describe the task
Ask your agent for something this skill covers. It loads sumsub-create-level automatically when relevant.
- 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 — Create Level
Builds an ApplicantLevel JSON payload from a compact spec, POSTs (or PATCHes) it to the Sumsub API, and reports the resulting name / id.
Endpoints
| Method | Path | When |
|---|---|---|
POST | /resources/applicants/-/levels | Create a new level. Body must NOT include id or key — server assigns them. |
PATCH | /resources/applicants/-/levels | Update an existing level (by id in body). |
GET | /resources/applicants/-/levels/{id} | Read one level. Use this to verify what landed (tenant gates may silently drop fields) or to resolve name from a known id. |
GET | /resources/applicants/-/levels | List all levels (use to reuse existing levels before creating duplicates). |
Body: ApplicantLevel. Returns the persisted level with id, createdAt, audit trails.
Auth — App Token + secret (sandbox only)
This skill talks to the public Sumsub API and signs each request per
the authentication reference.
The full how-it-works writeup lives in the sumsub-api-auth
skill — read it if you hit 401 Invalid signature.
⚠️ Sandbox tokens only. Do not accept or use a production App Token here — creating a level is a workspace-visible write. If the user offers a prod token, refuse and ask them to generate a sandbox pair at https://cockpit.sumsub.com/checkus/home?sbx=true (Connect Sumsub to your AI agent -> Build & configure -> Generate token). Token + secret are shown once — copy both before closing the dialog. The helper script enforces this — it rejects tokens that don't start with
sbx:.
| Var | Example |
|---|---|
SUMSUB_APP_TOKEN | sbx:... — sandbox App Token from the dashboard. |
SUMSUB_SECRET_KEY | The paired secret shown once at token creation. |
SUMSUB_BASE | Optional. Defaults to https://api.sumsub.com. |
If the user has already supplied credentials in conversation, reuse them; otherwise ask once before running. Never echo the secret back.
Procedure
-
Fetch tenant entitlements. Invoke the
sumsub-check-permissionsskill and parse the JSON result. Store theallowedChecksmap (its keys are the enabled entitlements); use it for all feature-gate checks in step 2 and the entitlements section below. Do this before anything else. -
Check existing entities. Before building anything, list existing levels, POA presets, and questionnaires (GET the respective list endpoints). If a matching entity already exists, offer to reuse its
idand skip the POST — the server creates a duplicate on every POST with no name deduplication. -
Translate the user's request to the compact spec below — name, applicant type, and a list of doc-set steps in the order they should appear in the WebSDK flow. If the request implies database / non-document verification, resolve sources via
sumsub-check-databasesfirst (see Database / non-document verification). -
Validate — confirm every
typeis a realIdDocSetType, everyQUESTIONNAIREstep has aquestionnaireDefIdthat points to an existing questionnaire, everyPROOF_OF_RESIDENCE*step has apoaPresetId/poaStepSettingsId(the server rejects the level if it's missing — runsumsub-create-poa-presetfirst if no preset exists), everyCOMPANYstep has at least one named sub-step. Use theallowedCheckskeys from step 0 to reject any entitlement-gated feature not present among them. -
Generate payload — run
${CLAUDE_SKILL_DIR}/scripts/build_level.pywith the spec on stdin → full payload on stdout. -
Show the resolved payload to the user and ask for explicit confirmation before the first POST.
-
Create vs. update:
- New level — POST via
${CLAUDE_SKILL_DIR}/scripts/post_level.sh. Returns response body + HTTP status. - Update existing — GET the current state via
${CLAUDE_SKILL_DIR}/scripts/get_level.shso the user sees the diff, then PATCH via${CLAUDE_SKILL_DIR}/scripts/patch_level.sh. The spec passed tobuild_level.pymust includeid: <level-id>— the builder preserves it into the payload, and PATCH refuses bodies without it. PATCH replacesrequiredIdDocs.docSetsas a single array — every docSet you send must carry the full intended state, since fields omitted from a docSet are wiped on the server. Copy preserved values from the GET response into your PATCH spec.
- New level — POST via
-
GET the level back via
${CLAUDE_SKILL_DIR}/scripts/get_level.shand compare to what was sent — several fields land differently from what was sent (see gotchas in references/level-schema.md). Report any discrepancy to the user. -
Build the dashboard link. Read
id,applicantType, andclientIdfrom the response body and format:https://cockpit.sumsub.com/checkus/sdkIntegrations/levels/<applicantType>Level/<id>?clientId=<clientId>&sbx=trueThe
<applicantType>Levelsegment is literallyindividualLevelforapplicantType: individual(confirmed) andcompanyLevelforapplicantType: company(assumed by analogy — surface as the best guess and flag if it 404s). Thesbx=truequery param targets the Sandbox workspace — it is the canonical sandbox link param shared across all skills. -
Report — lead with the human-readable name:
name,applicantType, ordered list of docSets created.- Dashboard link as a clickable markdown link.
- Final line:
Level ID (for SDK access tokens / future PATCH): <id>.
Surface 4xx errors verbatim — they usually point to a missing
questionnaireDefIdor an unknown enum value.
Tenant entitlements
Many level settings are gated behind tenant entitlements (allowedChecks). Before enabling a feature, check that the required BackgroundCheckTarget is present as a key in the allowedChecks map returned by sumsub-check-permissions (fetched in step 0).
DocSet type → required permission (OR — any one suffices):
| DocSet type | Required (any one of) |
|---|---|
QUESTIONNAIRE / QUESTIONNAIRE2-4 | QUESTIONNAIRE |
COMPANY / COMPANY_DATA | COMPANY | KYB_FULL | KYB_AUTO_AML_AND_REGISTRY | KYB_AUTO_AML_ONLY |
SOLANA_ATTESTATION / LINEA_ATTESTATION | PAYMENT_METHOD_CRYPTO |
PAYMENT_METHODS | PAYMENT_SOURCE | PAYMENT_METHOD | PAYMENT_METHOD_CRYPTO | KYT_UNHOSTED_WALLET_VERIFICATION |
INVESTABILITY | PROOF_OF_FUNDS |
PROOF_OF_RESIDENCE / PROOF_OF_RESIDENCE2 | POA | ADVANCED_POA_TYPE_DETECTION (often missing from allowedChecks even when the API actually allows it — proceed with a one-line warning; see below) |
E_KYC | E_KYC_TARGET |
E_SIGN | E_SIGN_TARGET |
TR_RECIPIENT_INFORMATION | TRAVEL_RULE |
DEVICE_CHECK | DEVICE_INTELLIGENCE |
Types not in this table (IDENTITY, SELFIE, APPLICANT_DATA, EMAIL_VERIFICATION, PHONE_VERIFICATION, etc.) are available to all tenants — no entitlement required.
AML / watchlist screening → WATCHLISTS. This isn't a docSet — it's level-wide behavior. When WATCHLISTS is in allowedChecks, AML/PEP/sanctions screening runs on by default on every level (turn it off per-level with disableWatchlists: true). When WATCHLISTS is absent, screening is off tenant-wide and no level setting enables it — treat a policy that needs AML screening as blocked on the missing entitlement (contact CSM), same as the docSet gates above.
If a requested feature requires an entitlement the tenant doesn't have — stop immediately. Do not build or POST the level. Tell the user which entitlement is missing, that the feature is unavailable on their account, and that they need to contact their CSM or Sumsub support to get it enabled. Resume only after the user confirms the entitlement has been added or explicitly decides to drop the feature.
Exception — POA. The POA / ADVANCED_POA_TYPE_DETECTION keys are often absent from allowedChecks even on tenants where the API actually accepts PROOF_OF_RESIDENCE levels (the entitlement seems to be baseline or covered by other keys; the documented mapping is stale on some tenants). When only POA is missing, proceed with a one-line warning to the user so they have context if support is later needed. Do NOT pause for explicit confirmation — Sumsub itself will reject the write if the tenant truly lacks the right, and that 4xx will be more informative than a pre-emptive halt. Surface any entitlement-related error verbatim if it comes back.
Safety
Creating a level is a write to a shared workspace. Always:
- Show the resolved payload to the user before the first POST (step 4 above).
- After each successful POST, GET the entity back and compare to what was sent — silent overrides are common.
- Do not re-POST a dependency (PoA preset, questionnaire) if it already succeeded mid-session — reuse the returned
id. - Do not delete or modify levels you didn't create in this session unless the user explicitly names them.
Names, not ids, in user-facing messages
This applies to every message you send the user about this level — not just the final report:
- Pre-POST summary: when you list which questionnaire and which POA preset will be attached, refer to each by
name/title(e.g. "POA preset «POA — 60 days»", "questionnaire «Applicant basics»"). Do not paste the rawid("6a16bfd4ded0fe13aa48165d") into prose — the user can't read it and it does not let them judge whether you picked the right entity. - Final report: still ends with
Level ID (for SDK access tokens / future PATCH): <id>on its own line — that line is the one place a raw id is correct, because the user needs to copy it for the next API call. - Diagnostic messages: when a 4xx response references a dependency id (POA preset not found, etc.), translate it to the name before showing the user.
If you don't yet know an entity's name (e.g. user supplied only an id from outside this session), GET the entity first and surface its name; do not fall back to the id.
Compact spec format
Accepts JSON or YAML on stdin. The builder fills in sensible defaults for each doc-set type (see references/level-schema.md).
{
"name": "Basic KYC",
"applicantType": "individual",
"type": "standalone",
"docSets": [
{"type": "IDENTITY", "docTypes": ["PASSPORT","ID_CARD","DRIVERS"]},
{"type": "SELFIE", "videoRequired": "passiveLiveness"},
{"type": "PROOF_OF_RESIDENCE", "docTypes": ["UTILITY_BILL"]},
{"type": "QUESTIONNAIRE", "questionnaireDefId": "source-of-funds"}
]
}
New levels must be WebSDK 2.0 (
websdkNext: true). On create, the builder setswebsdkNext: trueautomatically — you don't need it in the spec; just never setwebsdkNext: false(that ships a deprecated WebSDK 1.0 level). On update of an existing level (spec has anid), the builder leaveswebsdkNextuntouched and you should too: upgrading a live level's SDK is a heavy client-side migration, so never flip it as a side effect of an unrelated PATCH — change it only if the user explicitly asks.
Supported docSets[].type values
APPLICANT_DATA, EMAIL_VERIFICATION, PHONE_VERIFICATION, IDENTITY, IDENTITY2/3/4, SELFIE, SELFIE2, PROOF_OF_RESIDENCE, PROOF_OF_RESIDENCE2, PROOF_OF_PAYMENT, PAYMENT_METHODS, INVESTABILITY, COMPANY, COMPANY_DATA, COMPANY_DOCUMENTS, COMPANY_BENEFICIARIES, ACCREDITED_INVESTOR, E_SIGN, QUESTIONNAIRE/2/3/4, E_KYC, OTHER_DOCS, TR_RECIPIENT_INFORMATION, DEVICE_CHECK.
Per-type compact shortcuts
type | Shortcut keys | Builder expands to |
|---|---|---|
IDENTITY* | docTypes; videoRequired (disabled / docapture); captureMode & uploaderMode (sent only when docapture); nfcVerificationSettings: {mode} | flat fields on the docSet — only what you set. See Dashboard ↔ API mapping below. |
SELFIE* | videoRequired (default passiveLiveness; full set: disabled / enabled / photoRequired / passiveLiveness / staticLiveness), docTypes (default ["SELFIE"]); selfieProcessingSettings: {skipLivenessCheck, skipFaceMatchCheck} (used with payment-method verification — see below) | bare docSet with videoRequired [+ selfieProcessingSettings] |
PROOF_OF_RESIDENCE* | docTypes (default ["UTILITY_BILL"]); poaPresetId (or poaStepSettingsId) to attach a POA preset by id | docSet + poaStepSettingsId |
QUESTIONNAIRE* | questionnaireDefId (or questionnaireId alias) — required | bare docSet |
APPLICANT_DATA | fields — array of strings or {name, required, prefill, immutableIfPresent} | fields[] with defaults |
PAYMENT_METHODS | typeSettings (object — keys: bankCard, bankAccount, cryptoWallet, eWallet — see Payment method verification below); skipOwnershipCheck (bool, default false); skipRiskScoreCheck (bool); walletScreeningProvider (enum — see schema) | paymentSourceSettings with validated structure; always emits types: ["PAYMENT_SOURCE"] |
EMAIL_VERIFICATION / PHONE_VERIFICATION | — | bare docSet |
COMPANY | steps — array of {name, minDocsCnt?, idDocTypes?, idDocSubTypes?, fields?, applicantLevelName?} | full KYB step structure |
E_SIGN | esignSettings (pass-through) | as-is |
Unknown keys in a docSet are passed through to the API verbatim, so escape hatches are easy when you need an obscure field.
Dashboard ↔ API mapping for IDENTITY step
Verbatim labels from the Sumsub dashboard sidebar, paired with the API value to write. Match the user's description to a label, then use the value.
| Dashboard control | Label (user-visible) | API value | Spec key |
|---|---|---|---|
| Capture method | File upload | disabled | videoRequired |
| Capture method | Live capture | docapture | videoRequired |
| Capture mode¹ | Both manual and auto capture work at the same time | manualAndAuto | captureMode |
| Capture mode¹ | Only manual capture is active | manualOnly | captureMode |
| Capture mode¹ | Seamless live capture | seamless | captureMode |
| Fallback to file upload¹ | Always available | always | uploaderMode |
| Fallback to file upload¹ | Available only if camera capture failed | fallback | uploaderMode |
| Fallback to file upload¹ | Not available | never | uploaderMode |
| NFC verification² | Disabled | disabled | nfcVerificationSettings.mode |
| NFC verification² | Optional | optional | nfcVerificationSettings.mode |
| NFC verification² | Required | required | nfcVerificationSettings.mode |
¹ Only meaningful with videoRequired: docapture. Silently dropped from the payload otherwise (matches the dashboard's own behavior — it deletes both keys when the radio is toggled to File upload).
² required auto-rejects Web SDK applicants; Mobile SDK only.
Defaults emitted by the builder (necessary for the dashboard to render — the controls bind to actual stored values, not implicit UI defaults; empty fields render as "Select" placeholder, not as the default option):
videoRequired: docapture→captureMode: manualAndAuto,uploaderMode: always(unless caller overrides).- IDENTITY always gets
nfcVerificationSettings: {mode: disabled}unless caller overrides.
These match what the dashboard's own Vue watcher writes when the user first toggles Live capture. Caveat on PATCH: requiredIdDocs.docSets is replaced wholesale (only top-level Level fields merge) — every docSet in the PATCH spec must carry the full intended state, since omitted sub-fields are wiped. GET the level first and copy values you want to preserve.
AML / watchlist screening: two separate gates
- Tenant gate —
WATCHLISTSentitlement (checked in step 0). IfWATCHLISTSis inallowedChecks, AML screening is available and runs by default on every level. If it's not, screening is off for the whole tenant and no level setting turns it on — surface it as a missing entitlement (contact CSM), don't pretend the level enables it. - Level gate —
disableWatchlists(only matters when the tenant hasWATCHLISTS). To turn screening off for this level, send the top-level"disableWatchlists": true; omit it (orfalse) to keep it on.watchListCheckSettings.amlCaseTypeonly selects the provider (tenant-gated), anduseCustomWatchListCheckSettingsonly picks custom-vs-inherited config — neither is an on/off switch.
So for a policy that requires AML screening: confirm WATCHLISTS in step 0, then add nothing to the level and GET it back to confirm disableWatchlists isn't true. For a level that must skip AML, set disableWatchlists: true. Details: references/level-schema.md.
Payment method verification (step or action)
Payment method verification — the PAYMENT_METHODS docSet, for verifying a bank card, bank account, crypto wallet, or e-wallet — runs in two modes:
- As a step in a normal verification level: add a
PAYMENT_METHODSdocSet alongsideIDENTITY/SELFIE/PROOF_OF_RESIDENCE/ etc. The level stays a regularstandalonelevel with noactionType. Use this when payment verification is one part of a broader onboarding flow. - As an action on an actions-type level: set
type: "actions"andactionType: "paymentMethod". Use this for a standalone, re-runnable payment-method check decoupled from onboarding.
Pick the mode from how the user frames it — "add card/wallet verification to my KYC level" → step; "create a standalone payment-method check / action" → action.
Step mode — inside a standard level (identity and payment coexist):
{
"name": "KYC + payment method",
"type": "standalone",
"applicantType": "individual",
"docSets": [
{"type": "IDENTITY"},
{"type": "SELFIE", "videoRequired": "passiveLiveness"},
{"type": "PAYMENT_METHODS",
"typeSettings": {"bankCard": {"allowed": true, "countImages": "one"}}}
]
}
Action mode — inside an actions level:
{
"name": "Payment method check",
"type": "actions",
"actionType": "paymentMethod",
"websdkNext": true,
"docSets": [
{"type": "PAYMENT_METHODS", "skipOwnershipCheck": false,
"typeSettings": {"bankCard": {"allowed": true, "countImages": "one"}}}
]
}
Constraints the builder enforces:
actionType: "paymentMethod"requirestype: "actions", and the level must include aPAYMENT_METHODSdocSet.- Cannot set both
skipOwnershipCheck: trueandskipRiskScoreCheck: truesimultaneously. walletScreeningProvidergoes at thepaymentSourceSettingslevel, not insidetypeSettings.cryptoWallet(the builder places it correctly).bankAccountneeds a concrete verification method. UnlikebankCard, enabling a bank account withallowed: truealone is rejected by the API — it must enable at least one ofallowBankStatementUpload(statement upload, no extra entitlement) orallowExternalSourcesCheck(external data-source check, uses theE_KYCentitlement). Ask the user which method(s) they want; don't offer a bare "standard" bank-account option.
The PAYMENT_METHODS docSet (both modes): the builder always emits types: ["PAYMENT_SOURCE"] plus a paymentSourceSettings object assembled from your compact spec — the API rejects the docSet without paymentSourceSettings, so the builder never omits it.
typeSettings per payment source type:
| Key | Fields |
|---|---|
bankCard | allowed (bool); countImages ("one" / "two" / "some"); extractIban (bool); extractNationalBankAccountNumbers (bool); requireBankAccountNumber (bool) |
bankAccount | allowed (bool); allowBankStatementUpload (bool); allowExternalSourcesCheck (bool — requires E_KYC_TARGET entitlement). When allowed, at least one of these two methods must be true — see constraints above. |
cryptoWallet | allowed (bool); satoshiTestAllowed (bool); unhostedWalletFormType ("DEFAULT" / "SIMPLE" / "KAZ" / "TUR" / "SGP" / "POL" / "ITA") |
eWallet | allowed (bool) |
walletScreeningProvider enum: crystal / merkle / trmLabs / chainalysis / elliptic / cyvers
Entitlement: requires PAYMENT_SOURCE or KYT_UNHOSTED_WALLET_VERIFICATION (see Tenant entitlements).
Dashboard link: both modes live under sdkIntegrations/levels/individualLevel/<id> — the standard standalone-level URL pattern.
See examples/payment-methods.json for a complete action-mode spec.
Database / non-document verification (KYC)
Scope: KYC (individual) only. Company/KYB database checks are not covered via this path.
When the request implies checking applicant data against a database / registry rather than (or in addition to) a document — signals: "non-doc", "eKYC", "no document", "against a database/registry", "validate the ID / SSN / DNI number" — resolve and place sources via sumsub-check-databases before building the payload:
- Run
sumsub-check-databases <country>. A source is usable whenstatus == "ENABLED";SANDBOX_ONLYworks in sandbox but will not run in production (say so before building a level the user intends to go live with), andDISABLEDis not usable at all. If the source the user needs is unavailable, follow that skill's fallback + enablement guidance (don't silently drop it — point the user at Databases → Available products, self-serve for most sources). - Each source's
validationReady/stepsReadydecides the placement — the two signals are independent, check both:
| Signal | docSet | Notes |
|---|---|---|
validationReady: true | keep the document docSet (e.g. IDENTITY, types stays) | Source cross-checks the uploaded document's data against the database. Attach at the level's top-level checkSourceSettings (a sibling of requiredIdDocs, not nested inside it or inside the docSet). |
stepsReady contains a type on its own (e.g. E_KYC) | standalone docSet of that type, no types field | Database-only, no upload. E_KYC requires E_KYC_TARGET. Nest checkSourceSettings inside this docSet. |
stepsReady contains a type alongside an already-required doc step (e.g. IDENTITY) | keep that docSet's types | Applicant chooses document upload or the database check in the same step. Also requires E_KYC_TARGET. Nest checkSourceSettings inside that same docSet, not at the top level. |
If stepsReady lists more than one step type for a source, that's a menu of valid homes, not a mandate to use all of them — pick the one that matches the user's intent.
- Attach the chosen source(s) via
checkSourceSettings.countrySettings[]— either at the level's top level (acheckSourceSettingskey sibling torequiredIdDocs, forvalidationReadyplacements) or nested inside the relevant docSet (forstepsReadyplacements):
"checkSourceSettings": {
"countrySettings": [
{
"country": "ARG",
"checkType": "E_KYC_CHECK",
"groupType": "INPUT_COUNTRY",
"executionConfigurations": [
{"sourceId": "arg_gov_dni", "fallbackReasons": []}
]
}
]
}
country,checkType, andsourceIdcome straight from the check-databases response.groupType: useINPUT_COUNTRY(the applicant's country) — the default.TARGET_COUNTRYis only for the rare cross-border source (e.g. a visa check).executionConfigurationsis ordered — list multiplesourceIds to fall back in sequence.fallbackReasons(e.g.NAME_MISMATCH,DATA_NOT_FOUND) triggers the fallback to the next source;[]= no fallback.
See the three placements worked end-to-end in examples/identity-selfie-with-database-validation.json (top-level, validationReady), examples/identity-with-non-doc-selfie.json (nested in IDENTITY), and examples/non-doc.json (standalone E_KYC).
Field meanings, enum values, and the unavailable-source handling live in sumsub-check-databases + its schema reference.
Chaining with other Sumsub-* skills
This skill's QUESTIONNAIRE and PROOF_OF_RESIDENCE doc-sets accept ids produced by sibling skills, so a 3-step build-everything-from-scratch flow is natural:
| First run … | Pass the returned id as … |
|---|---|
sumsub-create-questionnaire | docSets[].questionnaireDefId on a QUESTIONNAIRE doc-set |
sumsub-create-poa-preset | docSets[].poaPresetId on a PROOF_OF_RESIDENCE doc-set |
See examples/with-presets.json for an end-to-end level that references both.
For database / non-document verification, run sumsub-check-databases to resolve sources and attach them via checkSourceSettings — see Database / non-document verification above.
Outputs
On success, lead with the human-readable info:
name,applicantType, ordered list ofdocSets[].idDocSetType.- Dashboard link:
https://cockpit.sumsub.com/checkus/sdkIntegrations/levels/<applicantType>Level/<id>?clientId=<clientId>&sbx=true. Render as a clickable markdown link. The<applicantType>Levelsegment isindividualLevelfor individuals (confirmed) orcompanyLevelfor companies (assumed pattern). All three fields (id,applicantType,clientId) come from the POST response body;sbx=truetargets the Sandbox workspace. - Finally, on its own line:
Level ID (for SDK access tokens / future PATCH): <id>.
On failure: HTTP status + the description/errorName from Sumsub's error envelope.
Worked examples
examples/identity-selfie.json— the most common pattern.examples/identity-live-capture.json— IDENTITY-only with Live capture + all docapture sub-options + NFC.examples/questionnaire-only.json— pure data-collection level (like the SOF level in this repo).examples/full-kyc.json—APPLICANT_DATA + IDENTITY + SELFIE + PROOF_OF_RESIDENCE + QUESTIONNAIRE.examples/kyb-company.json— KYB level with company + UBOs + representatives steps.examples/with-presets.json— references both a questionnaire (questionnaireDefId) and a POA preset (poaPresetId) returned by sibling skills.examples/payment-methods.json— payment method action level with bank card, bank account, crypto wallet, and e-wallet.examples/identity-selfie-with-database-validation.json— database validation (validationReady): document upload stays, source cross-checks it via top-levelcheckSourceSettings.examples/identity-with-non-doc-selfie.json— non-doc in an existing step (stepsReady):checkSourceSettingsnested insideIDENTITY, applicant can upload or use the database check.examples/non-doc.json— standalone non-doc (stepsReady): dedicatedE_KYCdocSet, no document upload.
See also
- references/level-schema.md — full
ApplicantLevelschema, all enum values, gotchas.
FAQ
What does the sumsub-create-level skill do?
Create or update a Sumsub applicant level. POST /resources/applicants/-/levels to create new, PATCH same path to update (id in body), GET /resources/applicants/-/levels/{id} to read one back. TRIGGER when the user asks to "create / add / build / update / edit a Sumsub level", supplies a list of required steps for an applicant flow (identity / selfie / proof-of-residence / questionnaire / payment methods / email or phone verification / KYB / e-sign), or wants a level wired to a specific questionnaireDefId. SKIP for other Sumsub entities (questionnaires, workflows, applicants) or for one-off subsetting tweaks not covered by the compact spec (use sumsub-api-generic for those).
How do I install sumsub-create-level?
Run npx skills add https://github.com/sumsub/agent-skills --skill sumsub-create-level 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-create-level/ (personal) or .claude/skills/sumsub-create-level/ (project).
Which AI agents can use sumsub-create-level?
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-create-level 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-create-level?
It is published by sumsub in sumsub/agent-skills. It has 1,188 recorded installs.
More from sumsub/agent-skills
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.
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.
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.
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.).
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
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).
Popular backend & apis skills
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.
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.
google-agents-cli-adk-code
google/agents-cli
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).
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.
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).
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.