Skip to main content
Resold by Frayme. No client API key required. Credentials and billing are managed end-to-end.
Sumsub is the workhorse of Frayme’s identity stack. It bundles three logical surfaces — KYC, AML and FRAUD — inside one applicant lifecycle, and it’s the default identity orchestrator for natural-person KYC workflows.

How Frayme calls Sumsub

The standard pattern across natural-person KYC workflows:
1

Create applicant

A POST to Sumsub creates the applicant skeleton and returns applicant_id + sdk_token.
2

Hand off to the client app

Frayme notifies the client app with the applicant id and an SDK launch hint. The client app opens the Sumsub SDK; selfie and document binaries flow directly to Sumsub — they never touch Frayme.
3

Wait for the terminal review

A long-poll dataSource node (timeout 600s, retry 0) waits for Sumsub to return review_answer: GREEN | RED plus reject labels.
4

Triage in Frayme

A rule node partitions the outcome: GREEN → proceed; RED + soft labels → AI false-positive synthesis; RED + hard labels → manual review with deterministic-fail recommendation.

Real-time actions on a paused node

While a Sumsub dataSource node is paused awaiting review_answer, you can invoke named pending actions on it. Address each by the node’s pending_handle — from the node.notification webhook or GET /cases/{caseId}/pending — and POST /pending/{handle}/actions/{actionId} with the cases:callback scope. The handle and invoke mechanics are covered in Integration guide → Pending actions on a paused node. All six Sumsub actions are side effects: they return data and leave the node paused — the review still completes through the applicantReviewed webhook. The two prefill actions are a matched pair — use prefill_applicant_info on a natural-person applicant and prefill_company_info on a company (KYB) applicant; each writes the half of fixedInfo that matches how the applicant was created. The two reset actions are a fine/coarse pair — reset_level_step resets specific steps, reset_applicant resets the whole applicant.

Request bodies

token_ttl_secs is optional on the token and link actions (defaults: 600s for the SDK token, 1800s for the link). Every field on both prefill actions is optional — send only what you want written; empty values are skipped, and re-sending the same body is idempotent. reset_level_step takes a required id_doc_set_types array.

prefill_applicant_info fields

All fields are optional; send only what you want written. Every field is a string except addresses, which is an array of address objects (object[]). Each param maps to a Sumsub fixedInfo key (except email, which is a top-level applicant attribute set via change-profile-data). Country fields are ISO 3166-1 alpha-3. Each addresses entry is an object with these fields (all string):

prefill_company_info fields

All fields are optional; send only what you want written. Every field is a string except address, which is a structured object (object). Each param maps to a Sumsub fixedInfo.companyInfo key. Values are forwarded to Sumsub as-is and validated there. Sumsub’s companyInfo carries both free-text address strings (legal_address, postal_address) and a structured address object — they are independent fields, so you may send either, both, or neither. address is an object with these fields (all string): prefill_company_info targets an applicant created as a company (Sumsub type: company) — it writes fixedInfo.companyInfo, not the top-level person fixedInfo that prefill_applicant_info writes. Pick the prefill action that matches the node’s applicant type.

reset_level_step fields

Resets one or more verification steps of the applicant — the person then re-submits just those steps, and the review completes through the applicantReviewed webhook as usual. The rest of their verification is untouched (this is not a full applicant reset). Common values: IDENTITY, SELFIE, PROOF_OF_RESIDENCE, PROOF_OF_PAYMENT, APPLICANT_DATA, QUESTIONNAIRE, PHONE_VERIFICATION, EMAIL_VERIFICATION, E_SIGN, and the company steps COMPANY, COMPANY_DATA, COMPANY_DOCUMENTS, COMPANY_BENEFICIARIES. All-or-nothing: every requested step must be configured on the applicant’s level. Duplicates are collapsed, and up to 32 steps may be reset per call. Before resetting anything, the request is checked against the applicant’s steps — if any requested step is not on the level, the whole call is rejected with 400 and nothing is reset (so a mistaken step can’t leave the applicant half-reset). Each valid step is then reset in turn. This action is available only while the node is paused (it addresses the applicant by the paused node’s handle) — it cannot reset a step after the case has been decided.

reset_applicant

Resets the entire applicant — every step and all collected data — so the person redoes their whole verification. Use it when a step-level reset isn’t enough (e.g. the wrong person was verified). Takes no params; the request body is {}. Returns applicant_id. Like reset_level_step, it is a side effect (the node stays paused and the review completes through applicantReviewed), and is available only while the node is paused — not after the case is decided.

Resubmission retries

When Sumsub rejects an applicant with a fixable problem — a blurry selfie, a glare-covered document — it returns review_answer: RED with reviewRejectType: RETRY and reopens the applicant so they can try again. If the node is configured to allow retries (see Configuration), Frayme treats this as a retry round rather than a terminal decline: it keeps the node paused, re-mints the verification artifact, and notifies you so you can prompt the end user to resubmit. A hard rejection (reviewRejectType: FINAL) is always terminal and is never retried.

Detecting a retry

A retry round arrives as a node.notification webhook (see Integration guide → Webhooks) with payloadType set to sumsub-retry-requested — that payloadType is your signal that the applicant must resubmit. Detection is purely the payloadType; you do not poll or compute anything.

Output fields

A fresh artifact is re-minted on every retry round because the previous token or link may have expired by the time the applicant returns. Re-minting is best-effort: if the vendor call fails, the node still stays paused and you still receive the notification — just without a fresh sdk_token / verification_url that round.

What to do on a retry

  1. Show moderation_comment to the end user.
  2. Hand them the fresh sdk_token (or verification_url) and have them resubmit against the same applicant — no new case.
  3. Do nothing else: the node stays paused and re-emits a sumsub-retry-requested notification for each subsequent failed round, then resumes the workflow automatically on the first GREEN (or terminal RED).

When the budget runs out

If max_retries is greater than 0 and the applicant exhausts it, the next failed round is not sent as a retry notification. Instead the node resumes with that round’s terminal RED verdict and the workflow decides the case (typically declined) — you receive a normal case.decided webhook. The re-minted artifact is deliberately omitted from that terminal output, so a sumsub-retry-requested webhook is your only signal to re-prompt; once it stops, the case is moving to a decision.

Configuration

Retries are a per-node setting, off by default:

Regenerate a share token

A Sumsub share token lets a partner client (a forClientId in Sumsub) access this applicant. When the dataSource node is configured to generate one, Frayme mints it automatically on review completion and surfaces it as share_token on the node output. But a partner may need access long after the case is decided — so re-issuing a share token is a durable case action, not a paused-node pending action. Unlike the three actions above, it is addressed by caseId and works from the moment the node ran onward — including after the case is approved or declined: POST /cases/{caseId}/actions/sumsub/regenerate_share_token — requires scope cases:callback.
Returns share_token. The applicant is re-resolved from the case’s external_customer_id, so the case must carry one (required on every case type). Each call mints a fresh token — there is no idempotency.
There is no persisted default for for_client_id — supply it on every call. This lets you share the same applicant with a different partner later without reconfiguring the workflow.