Skip to main content

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.

When onramping to non-Crossmint wallets, the onramp may require the user to prove they own the recipient wallet by signing a message. This is a legal requirement under anti-money laundering (AML) and counter-terrorism financing (CTF) regulations, which mandate verification of the beneficiary wallet owner’s identity above certain transaction thresholds. This page explains when proof of ownership is required and how it works.

When Is Proof of Ownership Required?

Proof of ownership is triggered based on transaction volume thresholds:
ConditionVerification Required?
Transaction below 1,000 EUR AND 30-day volume below 1,000 EURNo
Transaction above 1,000 EUR OR 30-day volume above 1,000 EURYes
Proof of ownership only applies to non-Crossmint wallets. Crossmint-managed wallets do not require ownership verification.

How It Works

1

Link External Wallet

Before creating an onramp order to an external wallet, link the wallet to a Crossmint user using the Link External Wallet API:
curl --request PUT \
    --url https://staging.crossmint.com/api/2025-06-09/users/YOUR_USER_LOCATOR/linked-wallets/YOUR_WALLET_ADDRESS \
    --header 'X-API-KEY: YOUR_API_KEY' \
    --header 'Content-Type: application/json' \
    --data '{
        "chain": "base-sepolia"
    }'
The API responds with a verification challenge following the CAIP-122 standard:
{
    "address": "0x1234...5678",
    "chain": "base-sepolia",
    "type": "external-wallet",
    "ownership": {
        "verified": false,
        "verificationChallenge": "crossmint.com wants you to sign in with your blockchain account:\n0x1234...5678\n\n..."
    }
}
2

Create Order

Create the onramp order as usual. If verification is required, the order response will have status requires-recipient-verification:
{
    "order": {
        "payment": {
            "status": "requires-recipient-verification",
            "preparation": {
                "message": "crossmint.com wants you to sign in with your blockchain account:\n0x1234...5678\n\n..."
            }
        }
    }
}
3

Sign the Message

Have the user sign the preparation.message using their wallet’s private key:
import { Wallet } from "ethers";

const wallet = new Wallet("YOUR_PRIVATE_KEY");
const message = order.payment.preparation.message;
const signature = await wallet.signMessage(message);
4

Submit Signature

Submit the signature as proof of ownership using the same Link External Wallet API:
curl --request PUT \
    --url https://staging.crossmint.com/api/2025-06-09/users/YOUR_USER_LOCATOR/linked-wallets/YOUR_WALLET_ADDRESS \
    --header 'X-API-KEY: YOUR_API_KEY' \
    --header 'Content-Type: application/json' \
    --data '{
        "chain": "base-sepolia",
        "proof": "YOUR_SIGNATURE"
    }'
Once verified, the response confirms ownership:
{
    "address": "0x1234...5678",
    "chain": "base-sepolia",
    "type": "external-wallet",
    "ownership": {
        "verified": true
    }
}
5

Complete Order

After ownership is verified, fetch the order using the Get Order API. The status will advance to:
  • requires-kyc — the user has not completed KYC yet.
  • awaiting-payment — the user can proceed to payment.

Pre-Verifying Ownership

You can verify wallet ownership at the time of linking (before any order is created) by including the proof field in the initial Link External Wallet call. This avoids requiring verification during the checkout flow.
curl --request PUT \
    --url https://staging.crossmint.com/api/2025-06-09/users/YOUR_USER_LOCATOR/linked-wallets/YOUR_WALLET_ADDRESS \
    --header 'X-API-KEY: YOUR_API_KEY' \
    --header 'Content-Type: application/json' \
    --data '{
        "chain": "base-sepolia",
        "proof": "YOUR_SIGNATURE"
    }'