Documentation / WHMCS Addons

KYC Identity Verification for WHMCS

Everything you need to install, configure, and run the addon — from your Sumsub credentials through to the client-side verification flow. If you are setting up a fresh install, start at Requirements and work down.

Version 1.9 WHMCS 9.x PHP 8.2+ ionCube loader required

1. Requirements

What your WHMCS install needs before you start.

ComponentRequirement
WHMCS9.x (8.x is likely compatible but is not tested or supported)
PHP8.2 or newer
PHP extensionscurl and iconv
ionCubeLoader installed and matching your PHP version — the addon ships encoded
CronAbility to add a cron entry (every 15–30 minutes)
SumsubYour own Sumsub account, with an App Token and Secret Key
LicenseOne license key per WHMCS installation

The addon is the WHMCS integration layer — nothing more. All document scanning, liveness, and face matching happen inside Sumsub, using the verification level you configure in your own Sumsub account. The addon never stores your clients' ID documents, never runs a liveness check, and never makes a verification decision. Sumsub is billed separately by Sumsub.

2. Install the addon

  1. Unzip the download and upload the tpckycsumsub/ folder into /modules/addons/ on your WHMCS install.
  2. Go to WHMCS Admin → System Settings → Addon Modules, find TPC KYC - Sumsub, and click Activate.
  3. Set Access Control to the admin roles that should be able to see KYC data, then save.
  4. Open Addons → TPC KYC - Sumsub. The addon provisions its own mod_sumsub_settings table on first load.
  5. Go to the Settings tab and paste your License Key. The addon validates it against the TPC license server and caches a local key, so short network outages will not lock you out.
  6. Work through the Setup Guide tab — it shows a live readiness checklist of which settings are still missing, plus your install's copy-ready webhook and cron URLs.

Upgrading from an older version? Deploy the new files and open the addon once. It migrates existing settings automatically — no deactivate/reactivate needed, and your credentials survive because they live in the addon's own settings table rather than in the WHMCS module config.

3. Sumsub-side setup

Get your credentials and verification level in order before configuring the WHMCS side.

3.1 Create a verification level

  1. Log in to the Sumsub dashboard.
  2. Go to Applicants → Levels and click Create level, or reuse the default basic-kyc-level.
  3. Configure the document types, liveness check, and review policy to match your compliance requirements.
  4. Copy the level name exactly — this is what goes into the addon's LEVELS setting.

3.2 Generate API credentials

  1. In the Sumsub dashboard, go to Dev Space → App tokens.
  2. Click Create new token and give it a descriptive name, e.g. whmcs-production.
  3. Copy the App Token — it starts with sbx: for sandbox or prd: for production. This is the APIKEY setting.
  4. Copy the Secret Key — this is SECRETKEY. Sumsub will not show it again, so store it somewhere safe.

3.3 The API URL

Sandbox and production both use:

https://api.sumsub.com/

Sumsub uses the same base URL for both environments — there is no separate sandbox hostname. Which environment you reach is decided entirely by the App Token: a token created in Sandbox mode (sbx:) hits the sandbox tenant, a Production token (prd:) hits production. A token created in one mode cannot be used against the other.

The URL must end with a trailing slash. Paste it into the APIURL field on the Settings tab.

Working in sandbox. Each environment has its own App Token, Secret Key, levels, and webhooks — switching means re-entering every credential on the Settings tab. In sandbox, real checks are disabled and results are simulated: complete a check with Sumsub's test documents, then approve or reject the applicant yourself in the dashboard. While testing you will often reset or delete applicants, which makes Sumsub issue a new applicant ID for the same person — the addon re-resolves each applicant by its stable externalUserId, so the dashboard still shows the latest result.

4. Cron and webhook

The webhook gives you real-time updates; the cron is the safety net that actually activates orders. Set up both.

4.1 Register the webhook in Sumsub

  1. Go to Dev Space → Webhooks → Webhook manager and click Create webhook. Make sure the Sandbox / Production toggle (top-right) matches the environment of your App Token.
  2. Name the webhook, e.g. TPC KYC, and set Webhook receiver to HTTP address.
  3. In Target, enter your webhook URL:
    https://yourdomain.com/modules/addons/tpckycsumsub/webhook.php
  4. Under Webhook types, select applicantReviewed. You may also add applicantWorkflowCompleted. Set Applicant types to All types or Individual.
  5. Leave Signature algorithm on SHA256 — the default. The handler also accepts SHA512 and the deprecated SHA1.
  6. Sumsub auto-generates a Secret key for this webhook. Copy it.
  7. In Addons → TPC KYC - Sumsub → Settings, paste that value into the Webhook Secret field and save.
  8. Save the webhook in Sumsub, then click Test webhook and watch the WHMCS Activity Log for a Sumsub webhook entry to confirm delivery.

The webhook secret is not your App Secret Key. It is a separate value generated per webhook in Sumsub's Webhook manager. It must match the WHMCS WEBHOOK_SECRET setting exactly, or every delivery is rejected with HTTP 403. If you leave WEBHOOK_SECRET empty, the handler falls back to SECRETKEY — make sure whichever one is in use matches Sumsub.

4.2 Add the cron entry

The cron polls Sumsub for results, runs the age and name checks, activates approved orders via the native WHMCS AcceptOrder API, and sends your email templates. Run it every 15–30 minutes:

*/15 * * * * php -q /path/to/whmcs/modules/addons/tpckycsumsub/tpckycsumsubCron.php

The cron is protected by the CronSecret value on the Settings tab. The Setup Guide tab prints the exact command and URL for your install, with the secret already filled in.

5. The addon tabs

All configuration lives inside the addon, not on the WHMCS module-config screen. Open Addons → TPC KYC - Sumsub and use the tab bar at the top.

TabWhat it does
DashboardEvery client and domain registrant with a KYC record, their status, the orders they hold and why, and the manual-approve action.
Audit logEvery manual decision and automatic action, newest first, filterable by client and action.
Mandatory KYCThe rules that decide which orders are held: product groups, domains (all or per TLD), payment methods, order size, client country — each as a trigger or a condition.
CustomersRequire KYC for specific clients, regardless of what they order.
SettingsCredentials and secrets (API Token, Secret Key, Webhook Secret, API URL, Levels, Registrant level, License Key, Cron Secret) plus the lifecycle settings: reminder ages, automatic cancellation, alert webhook, stale and throttle hours, document-country check, registrant resend interval, retention years.
Setup GuideEnd-to-end walkthrough with a live readiness checklist, your copy-ready webhook and cron URLs, and direct links to the relevant Sumsub pages. Start here on a fresh install.
Status GuideReference for every status pill and fail reason the dashboard can show.

Secrets are never echoed back. Leave a secret field blank to keep the stored value. Settings live in the addon's own mod_sumsub_settings table, so they survive deactivate and reactivate. Every save is written to the audit log (secrets only as changed).

6. Choosing which orders require KYC

On Addons → TPC KYC - Sumsub → Mandatory KYC. Five rule types, each with a role: trigger or condition.

RuleWhat it looks at
Product groupsTick WHMCS product groups. Matches when the order contains a product from a ticked group.
DomainsRequire KYC for ALL domain orders, or tick individual TLDs (e.g. .cn, .ru). Per-TLD picks are kept while the master toggle is on. This rule also defines which domains get registrant verification.
Payment methodsTick payment gateways (only active ones are offered). Matches when the order is paid with one of them.
Order sizeMinimum order total (default currency, tax included), minimum number of new items, or the client's total over the last N days. Leave a field empty to disable that limit.
CountriesA country list in include or exclude mode, checked against the client's billing country; optionally also against the checkout IP country (Cloudflare header).

How roles combine. An order is held when at least one trigger matches (or no trigger is configured) and every configured condition matches. Rule types you have not filled in are ignored whatever their role.

  • Product groups = trigger alone: VPS orders are held, everything else goes through.
  • Product groups = trigger, Payment methods = condition: VPS orders paid by card are held; VPS orders paid by bank transfer go through.
  • Countries (exclude EU) = condition alone: every order from outside the EU is held.
  • No rule configured at all → every new order is held. Configure at least one rule before go-live.

Always true, whatever the rules:

  • Renewal-only orders are never held (renewals with no new service, add-on or domain), not even for flagged clients.
  • Verified clients are not held again — unless the order contains an in-scope domain with a third-party registrant.
  • Switching an unpaid order's invoice to a ticked payment method re-runs the rules and can hold the order; switching away never releases one.
  • Every hold records why: the dashboard shows it under the client's status (Held: #1234 · trigger groups (gid 3) + condition gateways (paypal)) and the Activity Log repeats it.

7. Domain registrant verification

From 1.9 the addon verifies the registrant named on a domain, not only the WHMCS account holder — what EU registries and NIS2 Article 28 ask of registrars and resellers: accurate, verified registration data for the person or company that actually holds the domain.

Turning it on

Registrant verification uses the Domains rule of the Mandatory KYC tab and nothing else: a domain is in scope when Require KYC for ALL domain orders is on or its TLD is ticked. If the Domains rule is not configured, no registrant is ever asked — even when the addon holds every order because no rules are set.

Registrants are verified against Settings → Registrant level (REGISTRANT_LEVELS; empty = same as LEVELS). That Sumsub level must include the Applicant data step.

What happens on a domain order

  1. The client places an order with an in-scope domain. The addon looks at the registrant: the account holder's own details, or a third party (a saved Contact, or details typed at checkout).
  2. Own details: nothing extra. The client's own verification covers the domain. If the client is unverified, the order is held for the client as usual.
  3. Third party: the order is held at Pending KYC for the registrant. The registrant receives registrant-verification with their own Sumsub link at the contact's email address; the account holder receives registrant-pending-owner. If the account holder is unverified too, the order waits for both.
  4. The registrant verifies in Sumsub like a client would. The same checks apply: age, Sumsub answer, name match against the registrant data, document country, duplicate document.
  5. When every subject the order waits for is verified, the cron activates the order and the domain is sent to the registrar. The registrant gets registrant-verification-success, the account holder registrant-verified-owner.

A verified registrant is remembered for that client's later orders. They verify again only when their phone or country changes or the verification has expired; address and company changes are just stored. An edited saved Contact is re-checked at the next domain order.

The guard in front of the registrar

Even if an order is accepted by hand (Accept Order, Register in the admin area) or placed through the API, the addon checks the registrant just before the registrar module is called. If the registrant is not verified, or the contact data about to be sent differs from what was verified, the registrar call is stopped with a message, the action is parked, and the registrant gets a fresh link (at most every Registrant link resend interval hours). The cron sends the registration or transfer automatically once the registrant has verified — nothing to redo by hand. Domains of orders placed before the 1.9 upgrade are let through (audited as pre_feature_order).

On the dashboard

Registrants appear as their own rows with Subject = Registrant, the same status pills and reasons as clients, and the held orders they block. Approve Manually works on a registrant row too and activates the orders that no longer wait for anyone else. KYC history lists every registrant action: links sent, corrections, switches, guard blocks.

When the name on the document does not match

If Sumsub approves the registrant but the document name does not match the registrant data, the order stays held and you are alerted. You do not have to act: the account holder sees the mismatch in their client area and can fix it themselves — correct the details, adopt the name from the ID document, or switch the order to a different registrant (see What clients see). Or you approve manually after checking.

Nothing is backfilled. Existing domains and their contacts are never contacted; orders placed before the upgrade register without registrant verification. If you want verification for an old pending order, cancel it and have it placed again.

8. Requiring KYC for a specific customer

Sometimes you need to require KYC for one client regardless of what they order — a flagged or high-risk account, for example.

Two ways to flag a customer

  • From their profile — open the client in WHMCS admin and click the Require KYC action button. It becomes Remove KYC requirement once set.
  • From the Customers tab — type a client ID or email and click add. The table lists every flagged client with their current KYC status and a Remove button.

What flagging does

  • The client's new orders are held at Pending KYC until they complete verification — regardless of the Mandatory KYC rules (renewal-only orders excepted).
  • Their existing active services are not touched. Held orders activate automatically once the client verifies. Removing the flag does not release orders that are already held.
  • A flagged-but-unverified client also sees the client-area verification banner, so they can complete KYC proactively before ordering.
  • Flagging and un-flagging are written to the audit log.

9. Admin dashboard

Open Addons → TPC KYC - Sumsub. The table shows every client and registrant with a KYC record, newest review first.

ColumnShows
SubjectClient or Registrant.
WHMCS nameName, the WHMCS client ID, and a shortened Sumsub applicant ID (hover for the full value).
CountryCountry detected by Sumsub.
Required documentsThe level name as it appears in Sumsub.
Review startedWhen Sumsub first received data for the applicant.
StatusA coloured pill. Underneath: the reason when something needs attention, and each held order as Held: #orderId · reason (the order id links to the WHMCS order).
TagAny reject labels Sumsub attached, e.g. ID_INVALID, DUPLICATE.
ActionsView Client, KYC history (audit log for this client), Approve Manually.

Status pills

PillMeaning
ApprovedVerified, orders activated.
Review Complete (Pending Approval)Sumsub finished; your decision is needed. The reason is underneath: Name needs review, Document country differs from billing country, Document already used by another client, Account changed since verification. See section 10.
Awaiting User / Awaiting Service / Requires ActionSumsub needs something from the applicant or is still working.
Initialized / PendingNot started / submitted and under review.
Action needed — please try againSumsub asked for another attempt (bad photo etc.); the client has been told what to fix.
FailedUnder 18 or final Sumsub rejection.
Activation FailedVerified, but WHMCS could not activate an order; the cron retries — check the Activity Log.

Search across name, country and status; page size 10 / 25 / 50 / 100 / All.

Checking one applicant's status live

To force a fresh status pull without waiting for the cron, open this URL, replacing {userid}:

addonmodules.php?module=tpckycsumsub&checkstatus={userid}

Manual approval

Use Approve Manually when a row waits for your decision (Review Complete (Pending Approval)) and you have satisfied yourself about the identity, or when KYC was completed out of band.

  1. Find the row. The green check-mark button appears on any row whose status is not Approved.
  2. Click it, confirm the browser prompt, then type an optional note (why you approved). Cancelling either prompt aborts.

What happens: a CSRF token is validated, the approval and your note are written to the audit log, every held order that no longer waits for another subject is activated via AcceptOrder, and the subject receives the success email. If an order fails to activate the row becomes Activation Failed and a warning tells you which order.

Manual approval skips the age, name, country and duplicate checks. Do not use it to bypass a Sumsub rejection unless you have independently verified the identity.

10. Holds that need your decision

These never fail the client and never email them. They show as Review Complete (Pending Approval), write review_hold to the audit log and send you the alert client #N needs a manual KYC review.

Reason shownWhat happenedWhat to check
Name needs reviewThe name on the ID document does not match the WHMCS account name (accent- and case-insensitive; swapped order, a missing middle name or a first-name-only document already count as a match).Compare the names side by side (the client's KYC page shows both). Typo → approve manually. Different person → contact the client.
Document country differs from billing countryThe ID document was issued in a different country than the client's billing country (Check document country against billing country, on by default).Expats and companies are common legitimate cases. Approve manually or ask the client. Turn the check off in Settings if it does not fit your customer base.
Document already used by another clientThe same identity document (country + type + number, stored only as a hash) already verified another client or registrant; the alert names which one.Duplicate account, reseller registering for customers, or fraud. Decide, then approve or leave held.
Account changed since verificationA verified client changed their name or country in a way that no longer matches the document.Read the audit entry (account changed: ...). Until approved again, their new orders go through the normal rules.

11. Handling a rejected client

Rejections are automatic and come from Sumsub's review or the age gate. Each outcome is applied once per Sumsub attempt, so a rejection does not re-send the failure email every cron run.

OutcomeTriggerEmail sent
under_18Sumsub returned a date of birth that makes the applicant under 18.user-verification-failed
a Sumsub reject label or sumsub_rejectedSumsub's review result is RED and final — fraud, forged document, and so on.user-verification-failed
Action needed — please try againSumsub's review result is RED but retryable — blurry photo, screenshot, cut-off document. Sumsub's own explanation is stored and shown to the client.user-verification-retry with a fresh link and the what to fix text

Re-verification flow

  1. The client opens Client Area → Verify KYC.
  2. The page shows Try again (retry) or Re-Submit KYC / Continue Verification.
  3. Clicking it fetches a fresh WebSDK link bound to the client's existing applicant and redirects them back into the Sumsub flow. A new submission is a new attempt and is evaluated afresh.

If the Sumsub applicant is locked — common after a final RED result — reset it from the Sumsub dashboard (Applicant → Reset applicant) before the client re-submits.

12. Reminders, automatic cancellation and alerts

All of this runs inside the status-sync cron. Configure it under Settings → Held orders, alerts and retention.

  • Reminders (Reminder emails after (hours), default 24,72): at each age a held order reaches, the subject it waits for — client or registrant — gets one reminder with a fresh 7-day link. One reminder per client per run, none while their documents are under review, none to rejected registrants. Empty = no reminders.
  • Automatic cancellation (Cancel held orders after (days), off by default): unpaid orders whose subject never started a review are cancelled after N days and the client gets user-verification-cancelled listing the orders. Paid orders are never cancelled — you get an alert instead. Orders you accept or cancel yourself in WHMCS stop being tracked on the next run.
  • Alerts go to every admin who receives WHMCS system emails (subject TPC KYC: ...) and, if set, to a Slack / Teams alert webhook URL. The same alert is repeated at most every Repeat the same alert at most every (hours) (default 24). Alerts carry ids only, no personal data.
AlertAct on it by
license invalid — KYC is NOT being enforcedfixing the license key / outbound HTTPS. No order is held while the license is invalid.
client #N needs a manual KYC reviewopening the dashboard row (section 10).
orders of client #N failed to activatechecking the Activity Log for the AcceptOrder error and accepting the order by hand if needed.
paid order #N still waiting for KYCcontacting the client; the order is paid but still unverified.
N order(s) waiting for KYC longer than Xhreviewing the dashboard (Alert when an order waits longer than (hours), default 48).
registrar action blockednothing — the registrant has a link and the cron re-sends the registration after they verify.

13. Audit log and retention

Addons → TPC KYC - Sumsub → Audit log shows the newest 500 entries with when / client / by (admin or system) / action / detail. Filter by client ID or action; from the dashboard, KYC history opens it for one client.

You will see manual_approve (with your note), flag_on / flag_off, settings_change (which keys changed; secrets only as changed), review_hold, account_change, auto_cancel, relationship_ended / relationship_resumed, retention_purge, and the registrant entries (registrant_*, registrar_action_blocked, pre_feature_order, test_mail_sent).

Retention

When a client account is closed or deleted, the retention clock starts on their KYC row. After Keep KYC records after the account ends (years) (default 5 — the Romanian Law 129/2019 term) the cron deletes the local KYC record and its held-order rows, once a day, and writes retention_purge.

The addon does not delete anything in Sumsub. Once a month, filter the audit log by retention_purge (Sumsub deletion to do) and delete the applicants it names in the Sumsub dashboard. Audit entries themselves are kept.

14. Diagnosing a stuck order

A client says they finished KYC but their order is still Pending KYC. Work through this in order.

  1. Confirm the cron ran. Look for a recent cron entry from the addon in the WHMCS Activity Log (it ends with a done (...) summary). If nothing appears for hours, the cron is not executing — check your server cron, the URL and path, and the CronSecret value. previous run still active — skipping. means a run is stuck or still going.
  2. Look at the dashboard row. Review Complete (Pending Approval) with a reason underneath means the order waits for you (section 10). Action needed or Failed means it waits for the client.
  3. Is it a domain order with a registrant? Look for a row with Subject = Registrant for that client. The order waits for the registrant, not the client. The client can resend the link or change registrant from their client area.
  4. Check the KYC row status live. Run Check Status. Whatever Sumsub returns is the source of truth. pending / onHold → the client has not finished; send them to Verify KYC.
  5. Row is Approved but the order is still held? AcceptOrder failed — look for failed to activate order {id} in the Activity Log (usually the order or its items changed in WHMCS). Fix the order and let the cron retry, or accept it by hand.
  6. Order accepted but a domain was not registered? The registrar guard stopped it (registrar action blocked in the Activity Log). It is sent automatically once the registrant verifies, or approve the registrant manually.

The WHMCS Activity Log is the addon's detailed log. Filter by KYC or Sumsub to see holds with their reasons, cron summaries, webhook deliveries, signature failures, alerts and guard actions. The Audit log tab is the record of decisions.

15. What clients see

First-time verification from checkout

  1. The client completes checkout and receives the standard WHMCS order confirmation.
  2. Seconds later they receive a second email — Identity Verification Required (user-verification). It contains the direct verification link, valid for 7 days.
  3. In the client area, a yellow banner appears at the top of every page: "Identity verification required. Complete KYC verification to activate your orders." The close button dismisses it for the current browser session.
  4. Clicking the verification link takes them into Sumsub's hosted WebSDK flow: ID upload, liveness selfie, submit.
  5. Sumsub reviews. The webhook updates the stored status as the review progresses.
  6. On the next cron run, if the review is approved and the checks pass, their orders are activated and they receive Identity Verification Approved (user-verification-success). If a check holds them for admin review, the KYC page says their documents were received and are being reviewed; nothing is emailed until an admin decides.
  7. If they do not finish, they receive a reminder with a fresh link at the configured ages (default after 1 and 3 days) and — if enabled — a cancellation notice when an unpaid order is cancelled.

Verifying from the client area

Clients can also start or resume KYC without an email. They log in, click Verify KYC in the top navigation, and:

  • No record yet — the page shows a form with a Submit KYC button, plus a Personal / Company toggle if applicable. Clicking it creates the Sumsub applicant and redirects to the WebSDK.
  • Incomplete record — the page shows Continue Verification or Re-Submit KYC, opening a fresh WebSDK session bound to their existing applicant.
  • Retry requested — the page shows Sumsub's What to fix text and a Try again button; the email user-verification-retry carries the same text.

The page also displays the current status and, once completed, the Sumsub and WHMCS names side by side for transparency.

The persistent banner

The yellow banner is the addon's nudge. As long as the client has an unactivated order, an incomplete KYC record, or is flagged on the Customers tab, it appears on every page (and again on the invoice page of a held order). Its wording follows the situation: verification required, your identity verification needs another attempt, or an order is waiting for a domain registrant. Dismissing it hides it for the current browser session only. It is suppressed on the KYC page itself and on the checkout cart.

Domain registrants

When an account holder orders an in-scope domain for someone else, that person has to verify, not the account holder.

The account holder receives registrant-pending-owner, sees a banner saying an order is waiting for a domain registrant, and finds a Domain registrants card on Verify KYC listing each registrant of a held order with their status and these actions:

  • Resend verification link — a fresh link to the registrant's email (at most once every Registrant link resend interval hours, default 6).
  • Correct details — fix a typo in the registrant's name, email, phone, address or company; the saved Contact is updated too. A changed email or phone always starts a new verification.
  • Use the name from the ID document — shown after a name mismatch: adopts the verified name onto the registrant and the Contact, and releases the order.
  • Change registrant — move the held order to another Contact or to the account holder's own details. The WHMCS order contact changes too, so the registrar receives the new registrant's data.

When the registrant has verified, the account holder receives registrant-verified-owner and the order activates; on a rejection, registrant-failed-owner. Verified registrants are shown but can no longer be corrected or switched.

The registrant receives registrant-verification at the contact email address, sent from your WHMCS system address: a domain is being registered in their name on behalf of the account holder, please verify your identity. It contains their own Sumsub link (7 days). Then the Sumsub flow, and registrant-verification-success, -retry or -failed depending on the outcome, with reminders at the same ages as client reminders. The registrant never needs a WHMCS login and never sees the account holder's data.

Client-facing pages inherit your theme (Lagom2 and Twenty-One are both supported).

16. Email templates

All templates are created automatically with a default text the first time any addon page or the cron runs; existing templates are never overwritten. Edit them under Setup → Email Templates (type General).

TemplateWhoTriggered byExtra merge fields
user-verificationclientan order is held{$verification_url} — a 7-day WebSDK link
user-verification-reminderclientreminder ages{$verification_url}
user-verification-retryclientSumsub asks for another attempt{$verification_url}, {$kyc_message}
user-verification-successclientverified (cron or manual approval)—
user-verification-failedclientunder 18 or final rejection—
user-verification-cancelledclientunpaid held orders auto-cancelled{$order_ids}, {$kyc_days}
registrant-verification / -reminder / -retry / -success / -failedregistrantsame events, for the registrant of a held domain{$verification_url}, {$kyc_message}
registrant-pending-owner / -verified-owner / -failed-owneraccount holdera registrant was asked / verified / rejected—

Customisation tips

  • Match the brand voice of your other WHMCS emails — first-person plural, direct, short.
  • Always keep {$verification_url} on its own line as a clickable link in the verification, reminder, retry and registrant templates. If omitted, the email falls back to a generic link to the KYC page.
  • Keep {$kyc_message} in the retry templates — it is Sumsub's own explanation of what went wrong, which is what gets the client through on the second attempt.
  • In user-verification-failed, direct the client to open a support ticket rather than replying to the email.
  • In registrant-verification, explain in one sentence who is registering the domain and why the registrant is asked (registry rules / NIS2). The registrant may have never heard of you.
  • Test registrant delivery with Settings → Send test registrant email before go-live (mail path, From address, SPF).

17. Production checklist

A healthy production setup has all of the following.

  • Cron running every 15–30 minutes with the correct CronSecret (it is incremental, so frequent runs are cheap).
  • Webhook registered in Sumsub, pointing at https://yourdomain.com/modules/addons/tpckycsumsub/webhook.php.
  • WEBHOOK_SECRET identical to the Secret key shown for that webhook in Sumsub's Webhook manager.
  • A production App Token (prd:) in Settings, not a sandbox one.
  • At least one rule configured on the Mandatory KYC tab (otherwise every order is held), roles reviewed so low-risk products still activate instantly.
  • If you sell domains: the Domains rule set to the TLDs that need registrant verification, the registrant level including the Applicant data step, and one test registrant email sent and received.
  • Reminder ages, automatic cancellation and the alert webhook set the way you want them; at least one admin receiving WHMCS system emails.
  • All email templates present (they are created automatically) and their copy reviewed.
  • Access control on the addon restricted to the admin roles that should see KYC data.
  • A public KYC policy or FAQ page for the user-verification email to link to.

Monitoring: the admin alerts tell you when something needs you. Review the Activity Log weekly during rollout, monthly once stable; review retention_purge entries monthly and delete the named applicants in Sumsub.

18. Support

Email support is included for the whole license year, direct from the engineers who wrote the addon. Send us your WHMCS version, PHP version, addon version, and the relevant Activity Log lines (filtered by Sumsub) and we can usually pinpoint the issue on the first reply.

Need a hand, or not running the addon yet?

Email office@projektcom.com for support, or take a look at what the addon does.

19. Changelog

Every release, newest first. Version numbers follow the value reported on the addon's own module config.

1.9 — 31 October 2026 current

Registrant verification. Domain registrations and transfers now verify the registrant named on the domain, not only the account holder. The verification link goes directly to the registrant's email. Account holders registering under their own details are not asked twice. Orders wait until every registrant has passed.

Added

  • Registrant subjects on the dashboard (new Subject column) with manual approval, registrant and owner email templates, a Send test registrant email action, and two settings: Sumsub level for registrants and the registrant link resend interval.
  • Client area Domain registrants card: resend the link, correct the registrant's details, adopt the verified name after a mismatch, or switch a held order to a different registrant (which also changes the WHMCS order contact).
  • A guard before the registrar call stops unverified or altered registrant data even on manual acceptance or API orders, and sends the registration automatically after verification.
  • Reminders and automatic cancellation follow the subject an order waits for; registrants get their own reminders.
  • Dark-mode styles for all admin pages on admin templates that opt in.

Behaviour changes on upgrade

  • In-scope domain orders whose registrant is a third party are now held until that registrant has verified (in scope = the Domains rule on the Mandatory KYC tab).
  • Registrant verification is a separate, unconditional gate on in-scope TLDs: a client registering an in-scope domain under their own details must be verified even if the Domains rule is set as a condition.
  • Registrant mails are sent through the WHMCS mailer and do not appear in the client's Email History.
  • A verified registrant's phone or country change re-verifies before the next domain order is released. Rejected or admin-held registrants are never mailed automatically.
  • Existing domains and registrants are not contacted; orders placed before the upgrade register without registrant verification.

1.8 — October 2026

Added

  • Checks after verification: ID document country vs billing country, duplicate identity document (stored only as a hash), and a re-check of verified clients who change their name or country. All of these hold for admin review; none fails a client.

Behaviour changes on upgrade

  • The document-country check is on by default (Settings → Check document country against billing country).
  • Reminders are on by default (24 h, 72 h); orders already held before the upgrade count as already reminded.
  • Missing email templates are created automatically; existing templates are never changed.
  • Renewal-only orders are never held, even with no rules configured. Automatic cancellation stays off until you set Cancel held orders after (days).

1.7 — October 2026

  • Sumsub retry rejections let the client try again with Sumsub's explanation (user-verification-retry, Try again on the KYC page, specific banner). No more false "name mismatch" failure on the client page.

1.6 — October 2026

  • Reminders with a fresh link, optional automatic cancellation of unpaid held orders, admin alerts (license invalid, review needed, activation failed, stale orders) by email and optional Slack / Teams webhook, cheaper incremental cron with a daily full sweep.

1.5 — October 2026

  • Audit log tab: manual approvals with a note, flags, settings changes, purges. Retention: local records are deleted N years (default 5) after the client account is closed or deleted; the audit log names the Sumsub applicant to delete.

1.4 — October 2026

  • New hold rules: payment method, order size (total / item count / client total over N days), country (billing, optionally Cloudflare IP). Each rule type is a trigger or a condition. Renewal-only orders always go through. Switching an unpaid order's invoice to a KYC gateway holds the order. Each held order records why.

1.3 — October 2026

  • Every Sumsub call goes through one signed client. A rejection is applied once per Sumsub attempt (no more failure email every 30 minutes). The Activity Log no longer receives webhook bodies, WebSDK links, names or dates of birth.

1.2 — 23 June 2026

The release that made the addon configurable from inside itself, and hardened it for production use on someone else's WHMCS.

Added

  • Settings tab — all credentials moved into the addon's own mod_sumsub_settings table, so they survive deactivate/reactivate. Secrets are never echoed back.
  • Mandatory KYC tab — pick which orders require verification by product group, by individual domain TLD, or with a master toggle for all domain orders.
  • Customers tab — flag individual clients as KYC-required regardless of what they order, from the tab or from a button on the client profile.
  • Setup Guide tab — end-to-end walkthrough with a live readiness checklist and copy-ready webhook and cron URLs for your install.
  • Status Guide tab — reference for every status and fail reason the dashboard can show.
  • Latin-name matching as a mandatory check, plus an admin nav restyle.

Changed

  • Addon folder renamed sumsub → tpckycsumsub, module label is now TPC KYC - Sumsub. Existing settings migrate automatically on first load after the upgrade.
  • A failed name match now holds the record for manual review instead of auto-failing the customer.
  • Applicants resolve by their stable externalUserId, so a verified result still displays after an applicant is reset or recreated at Sumsub.
  • Dashboard: newest-first ordering, and a full client-side table with per-page sizing, sort on any column, and search across all columns.
  • Webhook secret split out of the App Secret Key into its own WEBHOOK_SECRET setting.

Fixed

  • Webhook signature verification now reads Sumsub's X-Payload-Digest headers — previously every delivery was rejected with 403.
  • Cron matches the KYC name against tblclients order-insensitively.
  • The user-verification email now receives the verification_url merge field.
  • Duplicate KYC rows prevented via a unique index on userId.
  • Cron output is timestamped; the cron secret can be passed via CLI argument as well as a GET parameter.
  • 30-second cURL timeouts throughout, to stop requests hanging indefinitely.

Security

  • HMAC signature verification on the webhook — blocks spoofed status updates.
  • CSRF protection on the client-area KYC form and on manual-approve, which moved from a GET link to a protected POST form.
  • IDOR and XSS fixes in the status-check endpoint via strict userId validation and output escaping.
  • API payloads built with json_encode to prevent JSON injection; applicant IDs URL-encoded.
  • License enforcement hardened — every entry point now fails closed.

1.1 — 5 March 2026

Added

  • Age gate — applicants under 18 are rejected automatically, with under_18 recorded as the fail reason.
  • Name matching against the WHMCS client record, with ASCII normalisation and a name_mismatch fail reason.
  • Sumsub RED review answers now fail the record and store the reject label as the fail reason.
  • Fail reasons surfaced in the admin dashboard.

Fixed

  • Full name stored correctly on the KYC record.
  • placeOfBirth removed from the Sumsub applicant payload.
  • Missing failed status language key added; the init status now displays as Initialized.

1.0 — 1 March 2026

First release. Sumsub applicant creation at checkout, orders held as Pending KYC, client-area verification page hosting the Sumsub WebSDK, status-sync cron with automatic order activation via AcceptOrder, admin dashboard, and license validation.