Skip to main content
The sandbox supports two Sumsub KYC integrations. In the shared-token flow, your backend sends a share token and applicant ID to Pods. In the hosted flow, Pods creates the applicant and returns a verification link. Both flows let your backend choose a simulated outcome with an explicit sandbox request. Repeated status reads do not change the result.
Use your staging customer API key with the staging API URL, sent as x-api-key from your backend. Applicant email does not choose the result. Sandbox transition routes are absent in production.

1. Shared token

Use the same POST /api/v1/kyc/sumsub-share-token request as the production Sumsub reusable KYC flow. Pods does not call Sumsub for this sandbox submission, and Avenia operations are mocked. The share token and applicant ID must be non-empty, but Pods does not validate their contents.

Before you start

If you want real Sumsub sandbox values, follow Sumsub setup with your sandbox account: create an applicant, complete its sandbox review, and generate a share token for the Pods recipient. The Pods sandbox does not call Sumsub or inspect the token. The Node example supports both real Sumsub sandbox values and placeholders.

1. Submit a share token

Save kycUserId. The sandbox submission is now waiting for an explicit outcome. The email can be any valid address; strings such as approve or retry have no special meaning. The request also accepts taxId and optional taxIdCountry instead of cpf for the passport path. At least one of cpf or taxId is required. Use the same applicant identity for a later retry.

2. Read status without changing it

The response includes the stored status and other KYC fields. Calling this endpoint again leaves provider_pending unchanged until you set an outcome. Your application can poll exactly as it will in production, while your test controls when the result arrives.

3. Set an outcome explicitly

Call one of these staging sandbox endpoints with the kycUserId returned by submission: For example, choose a retryable rejection:
The transition returns the full KYC status response. Relevant fields are:
GET /api/v1/kyc/status now returns that result on every read. An approved transition returns providerResult: "APPROVED" and brlaEnabled: true in the mock. A rejected transition returns reason.code: "VERIFICATION_REJECTED" and reason.retryable: false.
The share-token submission already starts in provider_pending. You may still call POST /api/v1/kyc/status/sandbox/provider_pending with the same { "kycUserId": "…" } body. It returns the current status without starting another attempt or changing the profile. You can then call an outcome route when ready.

4. Retry a retryable rejection

Keep the same sumsubApplicantId, email, wallet address, and CPF. Generate a new share token for that applicant, then submit it to the same endpoint:
The profile keeps its kycUserId. Now call a sandbox outcome route again, for example /api/v1/kyc/status/sandbox/approved, and read the final status. Reusing the previous token leaves the result rejected_retryable. Changing the applicant identity returns 409 KYC_SUBMISSION_BINDING_MISMATCH.

State and access rules

Sandbox outcomes are simulated. They do not perform real identity verification or grant production access.

2. Hosted

Use the same POST /api/v1/kyc/hosted/sessions request as Pods Hosted KYC. The sandbox creates a mock Sumsub applicant and returns a URL on not-a-real-verification-link.invalid. This link is a placeholder: it does not collect documents or liveness evidence, and opening it does not advance KYC. Your backend controls each state change with the sandbox routes.

Before you start

You do not need Sumsub credentials or a share token for this flow. The hosted Node example exercises the steps below.

1. Create a hosted session

Save kycUserId. The sandbox link is deliberately unusable as a verification page. requiresWebView has the same shape as the production response, but your sandbox test should simulate completion through the transition endpoint instead of opening this link. Repeating session creation for the same CPF may return the existing profile and link.

2. Read status without changing it

Repeated reads remain created until your backend starts the simulated review. Later reads remain provider_pending until your backend selects an outcome.

3. Start the simulated review

The transition returns the full status response with status: "provider_pending". A later GET /api/v1/kyc/status still returns provider_pending. Starting the review twice is invalid; this route is only for created → provider_pending.

4. Set an outcome explicitly

From provider_pending, call one of /api/v1/kyc/status/sandbox/approved, /rejected, or /rejected_retryable with the same { "kycUserId": "…" } body. For example:
The response and subsequent status reads report rejected_retryable with reason.retryable: true. approved sets brlaEnabled: true in the mock. rejected ends the simulated attempt.

5. Reset a retryable hosted attempt

If the hosted profile reached rejected_retryable before Avenia import, call the normal hosted reset endpoint. This returns the same kycUserId to created and issues another dummy link:
Call /api/v1/kyc/status/sandbox/provider_pending again, then choose the next outcome. The sandbox’s placeholder link may have the same URL text after reset; its value does not drive state. Reset is limited to three attempts per profile and returns 409 KYC_RESET_NOT_ALLOWED when the profile is not eligible. An Avenia-side rejected_retryable result after import cannot use this reset route because the profile already has an Avenia account link.

State and access rules

The transition endpoint accepts only mock hosted profiles owned by the API-key customer. A real Sumsub applicant or another customer’s kycUserId returns 404 KYC_PROFILE_NOT_FOUND. Invalid state changes return 409 KYC_SANDBOX_INVALID_TRANSITION; concurrent updates return 409 KYC_PROFILE_CHANGED. In production the sandbox transition routes return 404 because they are not registered. The normal hosted session and reset endpoints remain available there, subject to the real provider and customer configuration.