Crossmint
Wallet provisioning, payment orders, and Svix webhook integration with Crossmint.
Crossmint provides two capabilities in the backend/ service:
- EVM wallet provisioning — each user gets a non-custodial EVM wallet used for USDC payments
- Payment order creation — Crossmint processes USDC payments and delivers physical goods
Authentication
All Crossmint API calls use a server-side API key configured in backend/:
CROSSMINT_SERVER_API_KEY=sk_staging_... # staging
CROSSMINT_SERVER_API_KEY=sk_production_... # production
CROSSMINT_API_URL=https://staging.crossmint.com # override API base URL (default: staging)The frontend requires a separate client API key:
NEXT_PUBLIC_CROSSMINT_API_KEY=pk_staging_...Wallet Provisioning
When a user completes authentication via the Crossmint OTP flow, the backend can provision an EVM wallet:
The EVM address is required for payment orders. Wallet status transitions: none → pending → active (or failed).
Frontend Auth Provider
The frontend (frontend/) uses @crossmint/client-sdk-react-ui in providers.tsx:
<CrossmintProvider apiKey={apiKey}>
<CrossmintAuthProvider loginMethods={['email', 'google']} logoutRoute="/api/auth/logout">
<CrossmintWalletProvider createOnLogin={{ chain: 'base-sepolia', signer: { type: 'email' } }}>
...
</CrossmintWalletProvider>
</CrossmintAuthProvider>
</CrossmintProvider>After Crossmint OTP login, the frontend calls POST /api/auth/session with the JWT to exchange it for server-side session cookies.
Payment Orders
Checkout creates a Crossmint headless order via the server SDK:
const order = await crossmint.orders.create({
payment: {
method: env.CROSSMINT_EVM_CHAIN_TYPE, // e.g. "base-sepolia"
currency: "usdc",
receiptEmail: user.email,
},
lineItems: [{
productLocator: `${retailer}:${productId}`,
callData: { /* Sui PTB parameters */ }
}],
recipient: {
email: user.email,
physicalAddress: { /* shipping address */ }
}
})The order ID is stored in orders.crossmint_order_id for webhook correlation.
EVM Chain Configuration
Set CROSSMINT_EVM_CHAIN_TYPE to select the payment chain:
| Value | Network |
|---|---|
base-sepolia | Base testnet (default) |
base | Base mainnet |
ethereum-sepolia | Ethereum testnet |
polygon | Polygon mainnet |
Webhook Events
Configure your webhook URL in the Crossmint dashboard under Developers → Webhooks:
https://your-domain.com/api/webhooks/crossmintSet the signing secret in backend/:
CROSSMINT_WEBHOOK_SECRET=whsec_...Event Lifecycle
On-Chain Checkout Trigger
When CART_SERVICE=onchain, the backend automatically submits a Sui PTB on payment success and delivery completion:
- Query order + cart item + user from DB
- Build checkout PTB via
buildCheckoutTx(walletAddress, orderId, onChainObjectId) - Submit via relayer (sponsored) or user key (if available)
- Save Sui digest to
orders.tx_hash
Idempotency is enforced: if tx_hash is already set, the PTB is skipped.
SDK Usage
The backend uses @crossmint/server-sdk:
import CrossmintSDK from "@crossmint/server-sdk"
const crossmint = CrossmintSDK({
apiKey: env.CROSSMINT_SERVER_API_KEY,
apiUrl: env.CROSSMINT_API_URL,
})See backend/src/lib/crossmint-client.ts for the singleton instance.
How is this guide?