> ## Documentation Index
> Fetch the complete documentation index at: https://docs.crossmint.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Pay-ins

> Receive stablecoin payments from your customers

<Info>
  **Regulatory status:** Pay-ins are **not a regulated activity**. No customer identity registration is required to receive stablecoin payments.
</Info>

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 <a href="https://www.npmjs.com/package/@crossmint/wallets-sdk" target="_blank">Crossmint Wallets SDK</a> installed

<Snippet file="wallets-sdk-installation-cmd.mdx" />

***

## 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.

<CodeGroup>
  ```bash cURL theme={null}
  curl --request POST \
      --url 'https://staging.crossmint.com/api/2025-06-09/wallets' \
      --header 'X-API-KEY: <your-server-api-key>' \
      --header 'Content-Type: application/json' \
      --data '{
          "chain": "base-sepolia",
          "adminSigner": {
              "type": "evm-keypair",
              "address": "<your-recovery-signer-address>"
          },
          "delegatedSigners": [
              {
                  "type": "evm-keypair",
                  "address": "<your-operational-signer-address>"
              }
          ],
          "alias": "payin-customer-123"
      }'
  ```

  ```typescript Node.js theme={null}
  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);
  ```

  ```python Python theme={null}
  import requests

  url = "https://staging.crossmint.com/api/2025-06-09/wallets"

  payload = {
      "chain": "base-sepolia",
      "adminSigner": {
          "type": "evm-keypair",
          "address": "<your-recovery-signer-address>"
      },
      "delegatedSigners": [
          {
              "type": "evm-keypair",
              "address": "<your-operational-signer-address>"
          }
      ],
      "alias": "payin-customer-123"
  }
  headers = {
      "X-API-KEY": "<your-server-api-key>",
      "Content-Type": "application/json"
  }

  response = requests.post(url, json=payload, headers=headers)

  print("Deposit address:", response.json().get("address"))
  ```
</CodeGroup>

Share the `payInWallet.address` with your customer so they can send stablecoins to it.

<Note>
  Instead of a server signer, you can use a [Cloud KMS signer](/wallets/guides/signers/cloud-kms) 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.
</Note>

***

## 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 <a href="https://www.crossmint.com/console" target="_blank">Crossmint Console</a> by following the [Add an Endpoint](/introduction/platform/webhooks/add-endpoint) guide. Select the `wallets.transfer.in` event type.

2. **Verify the webhook signature** to ensure the request is legitimate. See [Verify Webhooks](/introduction/platform/webhooks/verify-webhooks).

3. **Process the event** in your handler. The payload includes the sender address, recipient address, token, amount, and on-chain transaction details:

```json theme={null}
{
  "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](/wallets/guides/webhooks) guide.

***

## Next Steps

<CardGroup cols={2}>
  <Card title="Transfer Webhooks" icon="bell" href="/wallets/guides/webhooks">
    Full schema and best practices for monitoring transfers
  </Card>

  <Card title="Check Balances" icon="wallet" href="/wallets/guides/check-balances">
    Query token balances across your wallets
  </Card>

  <Card title="Payouts" icon="arrow-right" href="/stablecoin-orchestration/regulated-transfers/overview">
    Send stablecoins to your customers
  </Card>

  <Card title="Internal Transfers" icon="arrow-right-arrow-left" href="/stablecoin-orchestration/guides/internal-transfers">
    Move funds between your own treasury wallets
  </Card>
</CardGroup>
