Skip to main content

Guide

Whether your user simply needs to retake a blurry photo or has hit a compliance red line and cannot go any further, a single errorCode field tells you three things — whether to let the user try again, exactly what the user should do, and whether a resubmission is still possible — so that every KYC rejection becomes clear guidance rather than a vague “verification failed”. As a licensed card issuer, DCS normalises the dozens of rejection reasons coming from the underlying KYC vendors into one stable set of error codes that you can consume directly in your own product.

Where the reject code appears

When a KYC ticket’s status moves to REJECTED, the response carries a pair of fields describing the reason: The pair appears in the two places below with identical values, so you can read whichever channel suits you:
  • Querying the KYC status (you pull): see Query KYC status; the response carries errorCode / errorMessage when status=REJECTED.
  • The KYC_TICKET webhook (you receive): DCS pushes a notification whenever the ticket status changes, and the body carries the identically named errorCode / errorMessage fields (returned only for REJECTED). For the structure see Webhook data structures.
Who does what: the normalisation is done by DCS. You never have to deal with the raw reject codes of the underlying vendor (such as Sumsub) — you only integrate against the one set of errorCode values in the tables below. Mapping the raw codes onto this list is DCS’s job, and DCS notifies you in advance whenever a new value is added.

How to use these codes

Once you have an errorCode, work through the three steps below, which map onto the “Retryable / What the user should do / Resubmission possible” columns of the tables:
  1. Decide whether it is retryable. First establish whether the code is fixable (retry) or terminal (no retry). Never push a user to resubmit against a terminal code; they will just be rejected again.
  2. Tell the user what to do. For fixable codes, turn errorMessage or the “What the user should do” column into an in-product prompt (for example, “Please retake your document in better light”). For terminal codes, show one neutral message (for example, “Sorry, this application cannot proceed — please contact support”) and do not echo the specific compliance reason (a sanctions or PEP hit is sensitive information).
  3. Decide whether a resubmission is possible. Codes marked “Yes” go through the supplementary-document path (no need to fetch a new Sumsub token, call the resubmission endpoint directly); codes marked “No” mean starting over or stopping.

Full reject code list

The tables below regroup every reject code from the data dictionary into business buckets and add actionable columns. The errorCode values and their descriptions come faithfully from the data dictionary; the bucket, retryability, user guidance and resubmission columns are DCS documentation guidance, and the compliance position prevails in the end. Retryable: ✅ fixable, then retry / ❌ terminal, do not retry / ⚠️ depends (usually a system-side problem — retry later or escalate to a human).

Bucket 1 · Document image quality (fixable)

Something is wrong with the image itself (blurred, damaged, missing pages, wrong format); just have the user retake or re-upload it.

Bucket 2 · Document validity / type (partly fixable)

The document itself has expired, its type or template is not supported, or its language is not supported.

Bucket 3 · Supplementary material / incomplete information (fixable via resubmission)

Material is missing or details are incomplete; just prompt the user to supply the rest. A new Sumsub token is usually not needed.

Bucket 4 · Information mismatch (fixable by checking the details)

What the user entered does not match their document or the reference database; prompt them to check and correct it.

Bucket 5 · Face / liveness verification (partly fixable)

The face match or liveness check did not pass. Quality problems can be retaken; suspected third-party assistance, multiple people or spoofing is closer to terminal.

Bucket 6 · Compliance / risk terminal states (not retryable, show a neutral message)

The application hit a compliance red line such as sanctions, screening, EDD or suspicious behavior, and is terminal. Show one neutral message, do not echo the specific reason, and do not prompt a resubmission.

Bucket 7 · Eligibility / region restrictions (terminal, varies by partner configuration)

The user is outside the supported countries or regions, or fails a partner, age or similar eligibility requirement. Mostly terminal: for that user, retrying will not help.

Bucket 8 · Duplicates / suspected fraud (terminal)

A duplicate application, or suspected forgery or tampering.

Bucket 9 · Verification could not complete / data source problem (depends)

The application data could not be verified, or an upstream data source or database was unavailable. Separate “the user needs to check something” from “retry later, it is on the system side”.

Bucket 10 · Share token / reusable KYC (mostly retryable)

Reject reasons specific to the Sumsub share token or reusable KYC path. Most are token or session problems that a fresh attempt fixes; the channel-capability ones are terminal.

Bucket 11 · Submission not completed within the time window (TIMEOUT_*)

The TIMEOUT_ prefix always means the same thing: the user failed to complete the submission to Sumsub within the allotted time window, so the request was terminated on timeout. The suffix only tells you which step it was on when it timed out — it does not mean that check actually failed.
Troubleshooting tip: these codes account for a non-trivial share of rejections and are easily misread as “there is something wrong with the user’s documents”. When you see TIMEOUT_*, treat it as a timeout first — have the user start again and finish promptly, rather than asking them to re-supply whatever the suffix names.

Bucket 12 · Other

Integration advice

  • Branch on errorCode, never hard-code errorMessage text. errorMessage may change between versions or be localised; base your program logic on errorCode and use either errorMessage or your own copy from these tables for display.
  • Treat errorMessage as multilingual. Do not assume which language it comes back in. Program branches always follow errorCode; for display, use your own copy from these tables or localise errorMessage as a fallback.
  • Handle unknown codes. Values are added to and removed from these tables as compliance policy evolves. Keep a fallback branch for any errorCode outside the known list (handle it as OTHERS and raise an alert) so that a new code never breaks your front end.
  • Do not retry terminal codes in a loop. Buckets 6, 7 and 8 are terminal; resubmitting is pointless and may itself trigger risk controls. Show one neutral message and point the user to support.
  • Resubmissions do not need a new token. Where a resubmission is possible, such as proof of address (POA), supply the material through the resubmission path described in Apply for KYC; you usually do not need a fresh Sumsub share token.

Next steps

  • How to guide a user through a resubmission once you have the reject code: back to Apply for KYC.
  • Polling the ticket status yourself and parsing errorCode: see Query KYC status.
  • Letting users supply missing documents on a hosted page: see H5 KYC guide page.