Skip to main content
By default, when an onramp order requires identity verification (KYC), Crossmint collects it inside the embedded checkout component. If you would like more control over when and where the verification step shows up, you can decouple it: create the order via API, read the verification credentials that Crossmint already returns on the order, and render the step yourself with Crossmint’s 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.
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.

1. 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:
Be sure to use the latest SDK versions.

2. 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, inspect payment.status. If it is requires-kyc, read the credentials from payment.preparation.kyc:
Example order response
Pass the payment.preparation.kyc object straight to the component, 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, so 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.

3. Render the verification step in your own view

Instead of letting the checkout collect the verification, render CrossmintIdentityVerification 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
Since you own the surrounding view, the verification tends to feel more like a native step in your product than something embedded inside the checkout. The component renders a Crossmint-hosted iframe that resizes itself to its content, so your container controls the width and placement, and the height follows the current verification screen.

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 payment flow, tell the checkout that your application owns the verification step by passing identityVerificationHandling="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
For an order that does not come from the checkout context, the plain getIdentityVerificationCredentials(order) function is also exported from @crossmint/client-sdk-react-ui.
Passing identityVerificationHandling="external" without rendering CrossmintIdentityVerification leaves the buyer with no way to finish the order. The checkout suppresses the verification step and all of its outcome screens, on the assumption that your application shows them instead.

4. Poll the order until verification resolves

The component callbacks fire when the buyer finishes, but the order status is the source of truth. After onComplete, poll the order until payment.status moves off requires-kyc:
Verification usually resolves within 15 seconds, so the loop above is generous on purpose: it allows for about two minutes before giving up. Adjust 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.

5. Continue with payment

Once the order reaches awaiting-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.

User Onboarding and KYC

Import KYC Data

Status Codes

Onramp Quickstart (React)