Skip to main content
These two Node.js examples exercise the KYC sandbox. The shared-token script submits an applicant and token. The hosted script creates a session and receives a dummy verification link. Both explicitly move the applicant to a simulated result, then read it back. The status GET is read-only in both flows. The scripts check that polling does not advance the profile. Applicant email does not select the result.

1. Shared token

The shared-token script submits a Sumsub applicant and share token to Pods. With SCENARIO=rejected_retryable, it resubmits the same applicant with a fresh token and sets the second attempt to approved.

Requirements

  • Node.js 18 or newer, with built-in fetch.
  • Your staging Pods API URL and staging customer API key. Send the key from your backend as x-api-key.
  • Optional: Sumsub sandbox credentials, a level name, and the Pods recipient ID. If all four SUMSUB_* values are omitted, the script uses unique placeholder applicant IDs and tokens. Pods requires these fields but does not inspect their contents in the sandbox.
Download or copy kyc-sandbox.js, then run:
SCENARIO accepts approved, rejected, or rejected_retryable. The default is approved. Each run generates a new valid CPF, applicant ID, and wallet unless you provide WALLET_ADDRESS, so previous test results do not affect it. If you save the script outside a project configured for ES modules, save it as kyc-sandbox.mjs and run node kyc-sandbox.mjs.

How the example calls Pods

The script submits the normal production request shape. The sandbox returns a kycUserId in provider_pending:
The submission is already pending, but the script also calls the optional pending route. This returns the current status without starting another attempt:
It reads the status before setting an outcome and asserts that it is still provider_pending:
Next it calls the route for the chosen outcome. Every sandbox transition takes { "kycUserId": "…" } and returns the full KYC status response:
A subsequent GET reads the same status. For rejected_retryable, the script requests a new token for the same Sumsub applicant (or makes a new placeholder token), resubmits the same CPF, email, wallet, and applicant ID, then explicitly sets approved. It checks that the retry keeps the original kycUserId and returns to provider_pending first.
The full script signs Sumsub sandbox requests when credentials are supplied. It creates an applicant, simulates a GREEN review, and mints its first share token. On retry it mints a second token for that existing applicant, which is necessary to keep the Pods profile binding intact.
The transition routes exist only outside production. Sandbox outcomes simulate responses; no real Sumsub or Avenia verification occurs inside Pods. Keep both Pods and Sumsub credentials on your backend.

2. Hosted

The hosted script creates a Pods-hosted session. It checks that the returned link is clearly dummy, reads created twice, starts the simulated review, sets an outcome, and reads the result. With SCENARIO=rejected_retryable, it calls the hosted reset endpoint and then approves a second attempt.

Requirements

  • Node.js 18 or newer, with built-in fetch.
  • Your staging Pods API URL and staging customer API key. Pods Hosted KYC must be enabled for that customer.
  • A redirect URL configured on the customer. Set REDIRECT_URL only when you want to override the customer default with another allowlisted URL.
No Sumsub credentials, applicant ID, or share token are needed for this flow. The script creates a fresh valid CPF, email, and wallet for each run unless you provide WALLET_ADDRESS.
Save kyc-hosted-sandbox.js as kyc-hosted-sandbox.mjs outside an ES-module project, then run:
SCENARIO accepts approved, rejected, or rejected_retryable; its default is approved.

How the example calls Pods

First, the script creates a hosted session. The sandbox response has status: "created" and a verificationLink under .invalid. The link is a placeholder and cannot collect documents or change status:
After two GET calls confirm the profile is still created, the script starts the simulated review:
It reads provider_pending without changing it, then selects the outcome:
For a retryable result, the script calls the hosted reset route. It keeps the same kycUserId, returns to created, and then explicitly transitions to provider_pending and approved:
The hosted reset applies only to an eligible Sumsub-side rejected_retryable profile. It cannot restart a retryable rejection after an Avenia account link exists. See the hosted sandbox steps for the guard and state rules.