Prerequisites
To use Reap with Crossmint wallets, you need:- Crossmint wallet: a wallet on Base Sepolia
- Crossmint API key: a staging Client API Key with the scopes
users.create,users.read,wallets.create,wallets.read,wallets:transactions.create,wallets:transactions.sign,wallets:balance.read, andwallets.fund(create in the Crossmint Console). In staging, all scopes are included by default. - Reap API key: a sandbox API key for a Program-Funded project, issued by Reap (see the Reap API overview)
- Next.js project: an App Router project with the Crossmint React SDK installed
- Test tokens: USDXM in the wallet from
wallet.stagingFund()(see Fund a Staging Wallet) - Program treasury: an EVM address your program controls on Base Sepolia that receives user deposits
- Gas: ETH on Base Sepolia for gas fees (not required if gas sponsorship is enabled)
What You Will Build
High-level steps:- Set up Crossmint authentication and wallet providers.
- Build a server-side Reap client.
- Create the Reap user, complete KYC, and issue a virtual card.
- Fund the card from the Crossmint wallet.
- Simulate a purchase and reveal the card.
/simulation/* endpoints for KYC approval, collateral deposits, and card authorizations. These
endpoints do not exist in production and are marked as sandbox only below.Set Up Crossmint
Configure the providers


base-sepolia address and the USDXM balance:
Wallet created on login and funded with 10 USDXM from the staging faucet
Add environment variables
NEXT_PUBLIC_ prefix.TREASURY_TOKEN_ADDRESSES lists the stablecoin contracts your treasury accepts; the value above is USDXM on base-sepolia.Build the Reap Integration Layer
Reap authenticates with a bearer token and pins the API version through theReap-Version header. Create-style requests also require an Idempotency-Key. Keep every Reap call in Next.js server actions so the API key never reaches the browser.
Create a Reap client
Add user, account, and card operations
externalId so a returning user maps to the same Reap user. List endpoints return results under items.Add balance, funding, and reveal operations
DEPOSIT against the user’s account after their on-chain transfer settles.Verify the deposit on-chain
Transfer event. Only accept transfers emitted by the stablecoin contracts you trust (USDXM in staging, USDC in production) and sent from the signed-in user’s wallet; otherwise any token transfer to the treasury would count as USD funding.Issue and Fund the Card
Create the user, approve KYC, and issue a card
204 immediately and the application flips to APPROVED a few seconds later, so poll the user until it does.
User approved, account active, and virtual card issued


Fund the card from the wallet
wallet.stagingFund() mints USDXM, so read and send "usdxm"; in production use "usdc".
5 USDXM sent to the treasury and mirrored as 5 USD of Reap spending power

Virtual asset postings credited to the user account after each wallet transfer
send and balances parameters.Simulate a purchase and reveal the card
amount as a running total ({ authorized, reversed, current }), while declines omit amount and return a scalar originalAmount with a declineReason.<iframe> so the PAN and CVV are rendered by Reap and never pass through your servers.



Verify the Integration
Runnpm run dev, sign in with an email, and click through the flow. A successful run shows:
- The wallet address on
base-sepoliawith a USDXM balance afterstagingFund. - A Reap user with
application.status: "APPROVED", anACTIVEaccount, and anACTIVEvirtual card. - The wallet balance decreasing by the funded amount and
availableBalanceon the Reap account increasing by the same amount. - A
PENDINGauthorization after the simulated purchase, withavailableBalancereduced by the purchase amount. - Card number, expiry, and CVV rendered inside the reveal iframe.

Reap PoC after funding, a simulated purchase, and a secure reveal
Troubleshooting
KYC status stays PENDING after the simulation call
KYC status stays PENDING after the simulation call
/simulation/users/{id}/application endpoint returns 204 when the request is accepted, not when the application is approved. Poll GET /users/{id} until application.status is APPROVED; the sandbox usually takes 5 to 15 seconds.Wallet balance shows 0 after stagingFund
Wallet balance shows 0 after stagingFund
wallet.stagingFund() mints Crossmint’s staging stablecoin USDXM, not testnet USDC. Read the balance with wallet.balances(["usdxm"]) and send with wallet.send(recipient, "usdxm", amount). Base Sepolia has several USDC-like tokens, so do not assume a single USDC address.Purchase amount renders as [object Object]
Purchase amount renders as [object Object]
amount as an object with authorized, reversed, and current, while declines return a scalar originalAmount. Normalize the response in the server action as shown above before rendering it.Reveal URL fails to load or shows an expired session
Reveal URL fails to load or shows an expired session

