Skip to main content
This guide walks you through how to enable onramp orders to external wallets (EOAs or any other smart wallet from a different wallet provider). Before creating an onramp order to an external wallet, you must 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/{userLocator}/linked-wallets/{walletAddress} \
    --header 'X-API-KEY: <x-api-key>' \
    --header 'Content-Type: application/json' \
    --data '{
        "chainType": "evm",
        "proof": "<signature>"
    }'
The proof field is optional:
  • If you omit it, you are simply linking the external wallet to the user without proving ownership yet.
  • If you pass it, you prove ownership of the wallet in the same request.
When linking without proof, the API responds with a verification challenge:
{
    "address": "0x1234567890abcdef1234567890abcdef12345678",
    "chainType": "evm",
    "type": "external-wallet",
    "ownership": {
        "verified": false,
        "verificationChallenge": "crossmint.com wants you to sign in with your blockchain account:\n0x1234...5678\n\nI am signing this message to prove ownership of my wallet address 0x1234...5678 for Crossmint verification.\n\nURI: https://..."
    }
}
The verificationChallenge follows the CAIP-122 standard.

2. Create Onramp Order

Create an onramp order using the Create Order API with the linked external wallet address as the recipient.
curl --request POST \
    --url https://staging.crossmint.com/api/2022-06-09/orders \
    --header 'X-API-KEY: <x-api-key>' \
    --header 'Content-Type: application/json' \
    --data '{
        "recipient": {
            "walletAddress": "0x1234567890abcdef1234567890abcdef12345678"
        },
        "payment": {
            "method": "card",
            "receiptEmail": "user@example.com"
        },
        "lineItems": [
            {
                "tokenLocator": "base-sepolia:0x036CbD53842c5426634e7929541eC2318f3dCF7e",
                "executionParameters": {
                    "mode": "exact-in",
                    "amount": "10"
                }
            }
        ]
    }'
Depending on the transaction value and the user’s past activity, the order may or may not require wallet ownership verification:
  • Below threshold: If the transaction value is below 1,000 euros and the user’s past 30-day onramp transaction volume is below 1,000 euros, ownership verification is not required. The order proceeds directly to the kyc/payment phase.
  • Above threshold: If either threshold is surpassed, the order status will be requires-recipient-verification and the user must sign a message to prove wallet ownership.
When ownership verification is required, the order response will look like this:
{
    "clientSecret": "...",
    "order": {
        "orderId": "987e81ab-8c8f-464e-95e9-11ceda80d559",
        "phase": "payment",
        "lineItems": [...],
        "quote": {...},
        "payment": {
            "status": "requires-recipient-verification",
            "method": "card",
            "currency": "usd",
            "preparation": {
                "message": "crossmint.com wants you to sign in with your blockchain account:\n0x1234...5678\n\nI am signing this message to prove ownership of my wallet address 0x1234...5678 for Crossmint verification.\n\nURI: https://...\nVersion: 1\nNonce: ...\nIssued At: ...\nExpiration Time: ...\nRequest ID: ...\nChain ID: base-sepolia",
                "email": "user@example.com"
            }
        }
    }
}

3. Sign Message

If the order requires ownership verification, the user must sign the preparation.message returned in the order response using their wallet’s private key.
import { Wallet } from "ethers";

const wallet = new Wallet("<private_key>");
const message = order.payment.preparation.message;
const signature = await wallet.signMessage(message);

4. Submit Signature

Use the same Link External Wallet API to submit the signature as proof of ownership. Pass the signature in the proof field:
curl --request PUT \
    --url https://staging.crossmint.com/api/2025-06-09/users/{userLocator}/linked-wallets/{walletAddress} \
    --header 'X-API-KEY: <x-api-key>' \
    --header 'Content-Type: application/json' \
    --data '{
        "chainType": "evm",
        "proof": "<signature>"
    }'
Once ownership is verified, the response will confirm verification:
{
    "address": "0x1234567890abcdef1234567890abcdef12345678",
    "chainType": "evm",
    "type": "external-wallet",
    "ownership": {
        "verified": true
    }
}

5. Complete Order

Once the signature is submitted and verified, fetch the order using the Get Order API. The order status should now have proceeded to the next phase:
  • requires-kyc: The user hasn’t completed KYC yet and will be guided through the KYC flow first.
  • awaiting-payment: The user has completed KYC and can proceed to complete payment.
The user will be guided through Crossmint’s embedded components to complete their order, handling payment and any remaining compliance steps automatically.