Skip to main content
Regulatory status: Pay-ins are not a regulated activity. No customer identity registration is required to receive stablecoin payments.
This guide walks you through receiving stablecoin payments from your customers — whether they are individual users, businesses, or AI agents. You will create a wallet for each customer (or payment context), share the wallet address, and listen for incoming transfers via webhooks.

Prerequisites

  • A Crossmint server API key with the scopes wallets.create, wallets.read
  • The Crossmint Wallets SDK installed
npm i @crossmint/wallets-sdk

Step 1: Create a Pay-in Wallet

Create a wallet on the chain your customers will send stablecoins on. Each wallet acts as a unique deposit address you can assign to a customer, invoice, or payment context.
index.ts
import { CrossmintWallets, createCrossmint } from "@crossmint/wallets-sdk";

const crossmint = createCrossmint({
    apiKey: "<your-server-api-key>",
});

const crossmintWallets = CrossmintWallets.from(crossmint);

const payInWallet = await crossmintWallets.createWallet({
    chain: "base-sepolia", // or "polygon", "ethereum", "solana", etc.
    recovery: {
        type: "server",
        secret: process.env.RECOVERY_SIGNER_SECRET,
    },
    signers: [
        { type: "server", secret: process.env.WALLET_SIGNER_SECRET },
    ],
    alias: "payin-customer-123", // use a meaningful alias per customer or invoice
});

console.log("Deposit address:", payInWallet.address);
Share the payInWallet.address with your customer so they can send stablecoins to it.
Instead of a server signer, you can use a Cloud KMS signer for enhanced security in production environments. Cloud KMS signers keep the private key inside a hardware security module (HSM) and support advanced enterprise controls like IP allowlisting and audit logs.

Step 2: Listen for Incoming Payments with Webhooks

Once your customer sends stablecoins to the wallet address, Crossmint fires a wallets.transfer.in webhook event. Set up a webhook endpoint to receive these notifications in real time.
  1. Configure a webhook endpoint in the Crossmint Console by following the Add an Endpoint guide. Select the wallets.transfer.in event type.
  2. Verify the webhook signature to ensure the request is legitimate. See Verify Webhooks.
  3. Process the event in your handler. The payload includes the sender address, recipient address, token, amount, and on-chain transaction details:
{
  "id": "whevnt_12324",
  "type": "wallets.transfer.in",
  "data": {
    "sender": {
      "address": "0x1234...5678",
      "chain": "base"
    },
    "recipient": {
      "address": "0xYourPayInWalletAddress",
      "chain": "base"
    },
    "token": {
      "symbol": "USDC",
      "amount": "250.00",
      "chain": "base"
    },
    "status": "succeeded",
    "onChain": {
      "txId": "0xabc...def",
      "explorerLink": "https://basescan.org/tx/0xabc...def"
    }
  }
}
For the full webhook schema and best practices, see the Transfer Webhooks guide.

Next Steps

Transfer Webhooks

Full schema and best practices for monitoring transfers

Check Balances

Query token balances across your wallets

Payouts

Send stablecoins to your customers

Internal Transfers

Move funds between your own treasury wallets