CrossmintIdentityVerification component.
This mostly affects where the verification step lives in your UI. You can surface it as its own screen, a modal, or a step in your flow, rather than having it appear inside the checkout iframe. The underlying flow stays Crossmint’s, and the credentials on the order are enough to render it.
Crossmint runs the underlying identity verification provider on your behalf, and your application only ever integrates with Crossmint’s component.If you instead want to run verification with your own UI and your own identity verification provider, see the Identity quickstart for sharing the resulting KYC data with Crossmint.
How It Works
1
Create the order and check the payment status
Create an onramp order via API. If the buyer needs to verify their identity, it comes back with
payment.status: "requires-kyc".2
Read the verification credentials from the order
The
requires-kyc response includes payment.preparation.kyc, the verification session Crossmint has prepared for this buyer. Pass it through as it comes; its shape depends on the verification flow of the order.3
Render the verification step in your own view
Pass those credentials to
CrossmintIdentityVerification and render it wherever you want in your app.4
Poll the order until verification resolves
Once the buyer finishes verifying, poll the order until the status moves off
requires-kyc, then continue with payment as usual.Prerequisites
Install the Crossmint React SDK, along with the base package that exports the shared types. No provider SDK is needed, since the verification UI is rendered by Crossmint:The
appearance prop needs @crossmint/client-sdk-react-ui 4.10.0 or later.Create the Order and Detect the Verification Requirement
Create the order server-side as you normally would (see the onramp quickstart). When the response comes back, inspectpayment.status. If it is requires-kyc, read the credentials from payment.preparation.kyc:
Example order response
payment.preparation.kyc object straight to the component as it comes, not the whole order.
If you only want to preview what an order would look like, you can pass
state: "draft" on creation. A draft order is not persisted and starts no identity verification, so its payment.status is draft and it cannot be polled or paid: create the order for real (omit state, or pass state: "create") and use that order’s credentials and orderId for the verification step and the polling below.Render the Verification Step in Your Own View
Instead of letting the checkout collect the verification, renderCrossmintIdentityVerification yourself with those credentials. You can place it wherever suits your app, such as a dedicated route, a modal, or a step in your onboarding. The component must be rendered inside CrossmintProvider:
components/VerificationStep.tsx
- Keep it mounted until
onCompleteoronCancel. The order leavesrequires-kycbefore the flow shows its result screen, so do not unmount the component when the credentials go away. - Handle
onCancel. The Done button on a blocked screen, and closing the document capture, send it. Without a handler, Done does nothing. - Leave 24px around the iframe and no fixed height. The screens have no outer padding of their own, and a fixed height cuts off the Continue button. See placing the screens on your page.
- Allow the camera. The ID document and selfie step uses it. The component already sets
allow="camera"on the iframe; the browser still asks the user for permission.
Match Your Theme
appearance takes the same object as the embedded checkout’s appearance prop, so one theme covers both. The KYC screens read light or dark from variables.colors.backgroundPrimary. The identity verification UI customization guide lists the settings that apply and the defaults.
Verification Outcomes
onComplete reports one of verified, pending-review, pending-manual-review, declined, expired, failed, or unknown. Treat unknown as an unresolved outcome rather than a success, and fall back to the order status.
If you also use the embedded checkout for payment
If the buyer pays through the embedded checkout rather than a fully headless integration, tell the checkout that your application owns the verification step by passingidentityVerificationHandling="external". The checkout then renders nothing for verification and keeps polling the order in the background, so it picks the flow back up at the payment step on its own:
components/OnrampCheckout.tsx
getIdentityVerificationCredentials(order) function is also exported from @crossmint/client-sdk-react-ui.
Poll the Order Until Verification Resolves
The component callbacks fire when the buyer finishes, but the order status is the source of truth. AfteronComplete, poll the order until payment.status moves off requires-kyc:
maxAttempts or add your own deadline to fit your UX. If you use the embedded checkout with identityVerificationHandling="external", the checkout already polls for you, and useCrossmintCheckout returns a fresh order instead.
The resulting status tells you what to do next:
Because the checkout suppresses its own verification screens when your application owns the step, the pending, review, and rejected states are yours to render as well.
See the Status Codes page for the authoritative list of order statuses.
Continue with Payment
Once the order reachesawaiting-payment, continue as you would in the standard flow, rendering the embedded checkout for payment or driving it yourself if you are fully headless. Decoupling verification only affects that step; the rest of the order lifecycle stays the same.

