Skip to main content

Overview

In the sandbox environment, customer KYC is mocked: no upstream KYC provider is called, and no end-user KYC data is collected. Customer onboarding still flows through the full review pipeline (sourcing, document validation, extraction, verification, compliance checks) — but the compliance-checks stage is satisfied by a mock that defers the verdict for one hour by default. Org-level KYB is not mocked. Your organization completes real KYB against real providers in sandbox; sandbox KYB approval is the prerequisite for graduating to production.

Customer-onboarding lifecycle

When you submit a customer onboarding application in sandbox:
  1. The application enters "processing".
  2. The mock records pending field verifications for the same paths a real KYC transaction would (business website, classification report, adverse-media report, associated persons, TIN — depending on the submitted data and country).
  3. A 1-hour timer starts.
  4. Either you call one of the simulate endpoints below to drive a specific outcome, or the timer fires and auto-approves the application.
First call wins: subsequent simulate calls return 409 Conflict.

Simulate endpoints

POST /v2/sandbox/applications/:id/simulate/decision forces a sandbox application to a terminal status on demand, regardless of the application’s current review stage. The body’s outcome field selects approved or rejected.

Works for any application type

This endpoint is not limited to customer onboarding. It accepts every application type your sandbox API key can create: outcome: "rejected" publishes the matching *.rejected event for the application’s type. Rejected applications never reach a provisioning branch.

Request shape

The endpoint requires your sandbox API key and a JSON body with an outcome field. The simplest approval call:
Returns 200 OK with the application at its current state. Replays against an already-terminal application return 200 with the current resource (idempotent).

Rejection options

The same endpoint with outcome: "rejected" accepts optional fields to shape the rejection: Structured category is only meaningful for KYB-pipeline application types (customer_onboarding, organization_onboarding, customer_update, sanctions_review). Sending category on a non-KYB type (e.g. a virtual_account application) returns 422 REJECTION_CATEGORY_NOT_APPLICABLE. Sending category with outcome: "approved" returns 400 VALIDATION_ERROR. Within category: generic an optional reason is accepted (this is how integrators simulate a manual operator rejection); for all other categories reason cannot be combined with category. Categories: document_mismatch (optional field: tax_id, date_of_incorporation, business_name, business_entity_id), data_sourcing_mismatch (optional field: business_entity_id, ubo_first_name, ubo_last_name, ubo_phone, ubo_email, ownership_list), compliance (no field), generic (no field; accepts an optional reason).

Errors

Non-custodial wallet provisioning

The customer’s wallets are provisioned via POST /v2/customers/:id/wallets/claim-non-custodial, which mints a non-custodial wallet account, sets up the signer roster, and creates the wallets in one shot. Submitting the crypto_wallet feature application alone enables the feature row but does not provision an account. See the Custodial vs non-custodial guide for the full copy-paste curl flow.

Notes

  • Customer KYC data submitted to sandbox is not transferred to production. Sandbox and production are isolated environments — end-user customers re-onboard in production.
  • The mock matches the real KYC adapter’s field-path set so your client code sees the same shape on application_field_verifications whether it’s running against sandbox or live.
  • The 1-hour fallback applies to customer-onboarding applications only and makes it safe to ignore simulation entirely for happy-path tests — submit, wait, observe an approved outcome. Other application types do not auto-resolve; drive them with simulate/decision { outcome: "approved" | "rejected" }.

See also